a
    +h7                     @   sN  d dl Z d dlZd dlmZmZ d dlmZmZ d dlm	Z	m
Z
mZmZmZmZ G dd deZG dd dZG d	d
 d
eZG dd deeZG dd deZG dd deeZG dd deZG dd deZG dd deZG dd deZG dd deZG dd dZG dd deZG dd  d eZG d!d" d"eeZG d#d$ d$eeZ G d%d& d&eZ!G d'd( d(Z"G d)d* d*eZ#G d+d, d,eeZ$G d-d. d.Z%G d/d0 d0Z&G d1d2 d2Z'G d3d4 d4eZ(G d5d6 d6Z)G d7d8 d8eZ*G d9d: d:Z+G d;d< d<eZ,G d=d> d>eZ-G d?d@ d@eZ.dAdB Z/dCdD Z0dEdF Z1dGdH Z2dS )I    N)BasePathMixinGroupedBasePathMixin)format_date_timeparse)ext_oatcls_scte35ext_x_asset	ext_x_key	ext_x_mapext_x_session_keyext_x_startc                   @   s   e Zd ZdS )MalformedPlaylistErrorN__name__
__module____qualname__ r   r   ?/mnt/pikpak/tmp/myenv/lib/python3.9/site-packages/m3u8/model.pyr      s   r   c                   @   s   e Zd ZdZdZd'ddZdd Zd	d
 Zedd Z	e	j
dd Z	edd Zej
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd(d!d"Zd#d$ Zd%d& ZdS ))M3U8a,  
    Represents a single M3U8 playlist. Should be instantiated with
    the content as string.

    Parameters:

     `content`
       the m3u8 content as string

     `base_path`
       all urls (key and segments url) will be updated with this base_path,
       ex.:
           base_path = "http://videoserver.com/hls"

            /foo/bar/key.bin           -->  http://videoserver.com/hls/key.bin
            http://vid.com/segment1.ts -->  http://videoserver.com/hls/segment1.ts

       can be passed as parameter or setted as an attribute to ``M3U8`` object.
     `base_uri`
      uri the playlist comes from. it is propagated to SegmentList and Key
      ex.: http://example.com/path/to

    Attributes:

     `keys`
       Returns the list of `Key` objects used to encrypt the segments from m3u8.
       It covers the whole list of possible situations when encryption either is
       used or not.

       1. No encryption.
       `keys` list will only contain a `None` element.

       2. Encryption enabled for all segments.
       `keys` list will contain the key used for the segments.

       3. No encryption for first element(s), encryption is applied afterwards
       `keys` list will contain `None` and the key used for the rest of segments.

       4. Multiple keys used during the m3u8 manifest.
       `keys` list will contain the key used for each set of segments.

     `session_keys`
       Returns the list of `SessionKey` objects used to encrypt multiple segments from m3u8.

     `segments`
       a `SegmentList` object, represents the list of `Segment`s from this playlist

     `is_variant`
        Returns true if this M3U8 is a variant playlist, with links to
        other M3U8s with different bitrates.

        If true, `playlists` is a list of the playlists available,
        and `iframe_playlists` is a list of the i-frame playlists available.

     `is_endlist`
        Returns true if EXT-X-ENDLIST tag present in M3U8.
        http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.8

      `playlists`
        If this is a variant playlist (`is_variant` is True), returns a list of
        Playlist objects

      `iframe_playlists`
        If this is a variant playlist (`is_variant` is True), returns a list of
        IFramePlaylist objects

      `playlist_type`
        A lower-case string representing the type of the playlist, which can be
        one of VOD (video on demand) or EVENT.

      `media`
        If this is a variant playlist (`is_variant` is True), returns a list of
        Media objects

      `target_duration`
        Returns the EXT-X-TARGETDURATION as an integer
        http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.2

      `media_sequence`
        Returns the EXT-X-MEDIA-SEQUENCE as an integer
        http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.3

      `program_date_time`
        Returns the EXT-X-PROGRAM-DATE-TIME as a string
        http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.5

      `version`
        Return the EXT-X-VERSION as is

      `allow_cache`
        Return the EXT-X-ALLOW-CACHE as is

      `files`
        Returns an iterable with all files from playlist, in order. This includes
        segments and key uri, if present.

      `base_uri`
        It is a property (getter and setter) used by
        SegmentList and Key to have absolute URIs.

      `is_i_frames_only`
        Returns true if EXT-X-I-FRAMES-ONLY tag present in M3U8.
        http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.12

      `is_independent_segments`
        Returns true if EXT-X-INDEPENDENT-SEGMENTS tag present in M3U8.
        https://tools.ietf.org/html/draft-pantos-http-live-streaming-13#section-3.4.16

      `image_playlists`
        If this is a variant playlist (`is_variant` is True), returns a list of
        ImagePlaylist objects

      `is_images_only`
        Returns true if EXT-X-IMAGES-ONLY tag present in M3U8.
        https://github.com/image-media-playlist/spec/blob/master/image_media_playlist_v0_4.pdf
    ))
is_variantr   )
is_endlistr   )is_i_frames_onlyr   )target_durationZtargetduration)media_sequencer   )program_date_timer   )is_independent_segmentsr   )versionr   )allow_cacher   )playlist_typer   )discontinuity_sequencer   )is_images_onlyr   NFc                 C   sV   |d urt |||| _ni | _|| _| jrD| jdsD|  jd7  _|   || _d S )N/)r   data	_base_uriendswith_initialize_attributes	base_path)selfcontentr%   base_uristrictZcustom_tags_parserr   r   r   __init__   s    zM3U8.__init__c                    s   fdd j dg D  _ fdd j dg D  _t fdd j dg D  _ jD ]\}}t | j | qdt j j	pdD ]\}}||_	qg  _
 jD ]"}|r|j j
vr j
|j q j
 jj t fd	d j d
g D  _t fdd j dg D  _t  _ j dg D ]&} jt j|d |d d q>t  _ j dg D ]&} jt j|d |d d q| j dd }|otf i | _ j dd }	|	otf i |	 _ j dd }
|
otf i |
 _ j dd }|o0tf i | _t fdd j dg D  _ t!dd  j dg D  _" fdd j dg D  _# j dd }|ot$f d ji| _% j d d }|ot&f d ji| _'d S )!Nc                    s(   g | ] }|r t f d  ji|ndqS r(   N)Keyr(   .0paramsr&   r   r   
<listcomp>   s   z/M3U8._initialize_attributes.<locals>.<listcomp>keysc                    s(   g | ] }|r t f d  ji|ndqS r+   )InitializationSectionr(   r-   r0   r   r   r1      s   segment_mapc              
      s2   g | ]*}t f  jt|d i  jd|qS )key)r(   	keyobject)Segmentr(   find_keygetr2   r.   segmentr0   r   r   r1      s   segmentsr   c                    s    g | ]}t f d  ji|qS r(   )Mediar(   r.   mediar0   r   r   r1      s   r@   c                    s$   g | ]}t f  j jd |qS ))r(   r@   )Playlistr(   r@   )r.   playlistr0   r   r   r1      s   	playlistsiframe_playlistsuriiframe_stream_info)r(   rE   rF   image_playlistsimage_stream_info)r(   rE   rH   startserver_controlpart_infskipc                    s    g | ]}t f d  ji|qS r=   )RenditionReportr(   )r.   Zrendition_reportr0   r   r   r1     s   rendition_reportsc                 S   s"   g | ]}d |v rt f i |qS )data_id)SessionData)r.   session_datar   r   r   r1     s   rQ   c                    s(   g | ] }|r t f d  ji|ndqS r+   )
SessionKeyr(   r-   r0   r   r   r1     s   session_keyspreload_hintr(   content_steering)(r!   r9   r2   r4   SegmentListr<   simple_attributessetattr	enumerater   filesrE   appendextend	MediaListr@   PlaylistListrC   rD   IFramePlaylistr(   rG   ImagePlaylistStartrI   ServerControlrJ   PartInformationrK   SkiprL   RenditionReportListrN   SessionDataListrQ   rS   PreloadHintrT   ContentSteeringrU   )r&   attrparamir;   r5   Zifr_plZimg_plrI   rJ   rK   rL   rT   rU   r   r0   r   r$      s    







zM3U8._initialize_attributesc                 C   s   |   S Ndumpsr0   r   r   r   __unicode__  s    zM3U8.__unicode__c                 C   s   | j S rl   r"   r0   r   r   r   r(   !  s    zM3U8.base_uric                 C   s   || _ || j_|| j_|| j_|| j_|| j_|| j_| jD ]}|r<||_q<| j	D ]}|rR||_qR| j
rp|| j
_| jr~|| j_d S rl   )r"   r@   r(   rC   rD   r<   rN   rG   r2   rS   rT   rU   )r&   Znew_base_urir5   r   r   r   r(   %  s"    

c                 C   s   | j S rl   )
_base_pathr0   r   r   r   r%   9  s    zM3U8.base_pathc                 C   s   || _ |   d S rl   )rq   _update_base_pathr&   Znewbase_pathr   r   r   r%   =  s    c                 C   s   | j d u rd S | jD ]}|r| j |_q| jD ]}|r,| j |_q,| j | j_| j | j_| j | j_| j | j_| j | j_| j | j	_| j
r| j | j
_| jr| j | j_d S rl   )rq   r2   r%   rS   r@   r<   rC   rD   rG   rN   rT   rU   r&   r5   r   r   r   rr   B  s$    











zM3U8._update_base_pathc                 C   s   d| _ | j| d S NT)r   rC   r[   )r&   rB   r   r   r   add_playlistV  s    zM3U8.add_playlistc                 C   s   |d urd| _ | j| d S ru   )r   rD   r[   )r&   Ziframe_playlistr   r   r   add_iframe_playlistZ  s    zM3U8.add_iframe_playlistc                 C   s   |d urd| _ | j| d S ru   )r   rG   r[   )r&   Zimage_playlistr   r   r   add_image_playlist_  s    zM3U8.add_image_playlistc                 C   s   | j | d S rl   )r@   r[   )r&   r@   r   r   r   	add_mediad  s    zM3U8.add_mediac                 C   s   | j | d S rl   )r<   r[   )r&   r;   r   r   r   add_segmentg  s    zM3U8.add_segmentc                 C   s   | j | d S rl   )rN   r[   r&   reportr   r   r   add_rendition_reportj  s    zM3U8.add_rendition_reportmillisecondsautoc                 C   sp  dg}| j r|t| j  | jr6|dt| j  | jrN|d| j  | jrh|d| j   | jr|dt| j  | jr|d | j	r|dt
| j	  | jdu s| jd	ks|d
t| j   | jr|t| j | jr|d | jr|d | jr(|t| j | jr| jrH|t| j |t| j | jrp|t| j | jr|t| j | jr|t| j | jr|t| j | jr|t| j | jD ]}|t| q|| j|| | jr|t| j | jr0|t| j | jrB|d |d rf|d dsf|d	 d|S )zy
        Returns the current m3u8 as a string.
        You could also use unicode(<this obj>) or str(<this obj>)
        z#EXTM3Uz#EXT-X-MEDIA-SEQUENCE:z#EXT-X-DISCONTINUITY-SEQUENCE:z#EXT-X-ALLOW-CACHE:z#EXT-X-VERSION:z#EXT-X-INDEPENDENT-SEGMENTSz#EXT-X-TARGETDURATION:N z#EXT-X-PLAYLIST-TYPE:%sz#EXT-X-I-FRAMES-ONLYz#EXT-X-IMAGES-ONLYz#EXT-X-ENDLIST
) rU   r[   strr   r   r   upperr   r   r   number_to_stringr   rI   r   r   rJ   r   r@   rC   rD   rG   rK   rL   rQ   rS   r<   rn   rT   rN   r   r#   join)r&   timespecinfspecoutputr5   r   r   r   rn   m  sn    






z
M3U8.dumpsc                 C   sF   |  | t|d}||   W d   n1 s80    Y  dS )z8
        Saves the current m3u8 to ``filename``
        wN)_create_sub_directoriesopenwritern   )r&   filenamefileobjr   r   r   dump  s    
z	M3U8.dumpc                 C   s@   t j|st jt  |}t j|}|r<t j|dd d S )NT)exist_ok)ospathisabsr   getcwddirnamemakedirs)r&   r   basenamer   r   r   r     s
    zM3U8._create_sub_directories)NNNFN)r~   r   )r   r   r   __doc__rW   r*   r$   ro   propertyr(   setterr%   rr   rv   rw   rx   ry   rz   r}   rn   r   r   r   r   r   r   r      s8   u     
m




E	r   c                       st   e Zd ZdZdddZdd Zdd
dZdd Ze fddZ	e	j
 fddZ	edd Zej
dd Z  ZS )r7   a  
    A video segment from a M3U8 playlist

    `uri`
      a string with the segment uri

    `title`
      title attribute from EXTINF parameter

    `program_date_time`
      Returns the EXT-X-PROGRAM-DATE-TIME as a datetime. This field is only set
      if EXT-X-PROGRAM-DATE-TIME exists for this segment
      http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.5

    `current_program_date_time`
      Returns a datetime of this segment, either the value of `program_date_time`
      when EXT-X-PROGRAM-DATE-TIME is set or a calculated value based on previous
      segments' EXT-X-PROGRAM-DATE-TIME and EXTINF values

    `discontinuity`
      Returns a boolean indicating if a EXT-X-DISCONTINUITY tag exists
      http://tools.ietf.org/html/draft-pantos-http-live-streaming-13#section-3.4.11

    `cue_out`
      Returns a boolean indicating if a EXT-X-CUE-OUT-CONT tag exists
      Note: for backwards compatibility, this will be True when cue_out_start
            is True, even though this tag did not exist in the input, and
            EXT-X-CUE-OUT-CONT will not exist in the output

    `cue_out_start`
      Returns a boolean indicating if a EXT-X-CUE-OUT tag exists

    `cue_out_explicitly_duration`
      Returns a boolean indicating if a EXT-X-CUE-OUT have the DURATION parameter when parsing

    `cue_in`
      Returns a boolean indicating if a EXT-X-CUE-IN tag exists

    `scte35`
      Base64 encoded SCTE35 metadata if available

    `scte35_duration`
      Planned SCTE35 duration

    `duration`
      duration attribute from EXTINF parameter

    `base_uri`
      uri the key comes from in URI hierarchy. ex.: http://example.com/path/to

    `bitrate`
      bitrate attribute from EXT-X-BITRATE parameter

    `byterange`
      byterange attribute from EXT-X-BYTERANGE parameter

    `key`
      Key used to encrypt the segment (EXT-X-KEY)

    `parts`
      partial segments that make up this segment

    `dateranges`
      any dateranges that should  precede the segment

    `gap_tag`
      GAP tag indicates that a Media Segment is missing

    `custom_parser_values`
        Additional values which custom_tags_parser might store per segment
    NFc                    s   | _ | _| _| _| _| _| _| _| _| _	|
 _
| _|	 _| _| _| _| _| _| _| _t|r fdd|D ng  _|d urt jfi | _nd  _t|rdd |D ng  _| _|pi  _d S )Nc                    s    g | ]}t f d  ji|qS r=   )PartialSegmentr"   )r.   partialr0   r   r   r1   ?      z$Segment.__init__.<locals>.<listcomp>c                 S   s   g | ]}t f i |qS r   	DateRanger.   	dateranger   r   r   r1   H  r   )r   rE   durationtitler"   bitrate	byteranger   current_program_date_timediscontinuitycue_out_startcue_out_explicitly_durationcue_outcue_inscte35oatcls_scte35scte35_durationscte35_elapsedtimeasset_metadatar5   PartialSegmentListpartsr3   init_sectionDateRangeList
daterangesgap_tagcustom_parser_values)r&   rE   r(   r   r   r   r   r   r   r   r   r   r   r   r5   r   r   r   r   r   r6   r   r   r   r   r   r   r   r0   r   r*     sB    zSegment.__init__c                 C   s   | j | d S rl   )r   r[   )r&   partr   r   r   add_partM  s    zSegment.add_partr~   r   c                 C   sF  g }|r0| j |j kr0|t| j  |d n(| j rX|d u rX|t| j  |d | jr|rn| j|jkr|t| j |d | jr|d | jr|dt| j|d  t| jr|t| j |d | j	r| j
r|t d| j
 d | jrXg }| j D ]"\}}||  d|  q|t dd| d | jrddnd}| jr~| | j nd	}	|d
|	 d n| jrg }
| jr|
d| j  | jr|
d| j  | jr|
d| j  |
rdd|
 }
nd	}
|d|
 d n4| jr2|d n | j
rR|t d| j
 d | jrt|t| j |d | jr<| jd ur|dkrd| j}n"|dkrd| j}n
t| j}|d|  | jr|| j |d | jr|d| j  | jr|d| j  | jr0|d || j d	|S )Nr   z#EXT-X-DISCONTINUITY
z#EXT-X-PROGRAM-DATE-TIME:%s
)r   :=,z
:DURATION=r   z#EXT-X-CUE-OUTzElapsedTime=z	Duration=zSCTE35=z#EXT-X-CUE-OUT-CONTz#EXT-X-CUE-IN
r~   z{:.3f}microsecondsz{:.6f}z#EXTINF:%s,z#EXT-X-BYTERANGE:%s
z#EXT-X-BITRATE:%d
#EXT-X-GAP
) r5   r[   r   r   r   r   r   lenr   r   r   r   r   itemsr   r   r   r   r   r   r   r   r   r   rE   r   formatr   r   r   r   r   )r&   last_segmentr   r   r   Zasset_suffixZmetadata_keyZmetadata_valueprefixZcue_infoZcue_out_cont_suffixr   r   r   r   rn   P  s    










zSegment.dumpsc                 C   s
   |  d S rl   rm   r0   r   r   r   __str__  s    zSegment.__str__c                    s   t  jS rl   )superr%   r0   	__class__r   r   r%     s    zSegment.base_pathc                    s4   t t| jj| | || j_| jd ur0|| j_d S rl   )r   r7   r   r%   fsetr   r   rs   r   r   r   r%     s    
c                 C   s   | j S rl   rp   r0   r   r   r   r(     s    zSegment.base_uric                 C   s$   || _ || j_| jd ur || j_d S rl   )r"   r   r(   r   )r&   Znewbase_urir   r   r   r(     s    
)NNNNNNNNFFFFFNNNNNNNNNNNNN)r~   r   )r   r   r   r   r*   r   rn   r   r   r%   r   r(   __classcell__r   r   r   r   r7     sN   J                          
@
[
r7   c                   @   s2   e Zd ZdddZdd Zedd Zd	d
 ZdS )rV   r~   r   c                 C   s4   g }d }| D ]}| |||| |}qd|S )Nr   )r[   rn   r   )r&   r   r   r   r   r;   r   r   r   rn     s    zSegmentList.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r     s    zSegmentList.__str__c                 C   s   dd | D S )Nc                 S   s   g | ]
}|j qS r   rE   )r.   segr   r   r   r1     r   z#SegmentList.uri.<locals>.<listcomp>r   r0   r   r   r   rE     s    zSegmentList.uric                    s    fdd| D S )Nc                    s   g | ]}|j  kr|qS r   r5   r:   r   r   r   r1     r   z&SegmentList.by_key.<locals>.<listcomp>r   rt   r   r   r   by_key  s    zSegmentList.by_keyN)r~   r   )r   r   r   rn   r   r   rE   r   r   r   r   r   rV     s
   

rV   c                   @   s*   e Zd ZdZd	ddZdd Zdd ZdS )
r   a  
    A partial segment from a M3U8 playlist

    `uri`
      a string with the segment uri

    `program_date_time`
      Returns the EXT-X-PROGRAM-DATE-TIME as a datetime. This field is only set
      if EXT-X-PROGRAM-DATE-TIME exists for this segment
      http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.5

    `current_program_date_time`
      Returns a datetime of this segment, either the value of `program_date_time`
      when EXT-X-PROGRAM-DATE-TIME is set or a calculated value based on previous
      segments' EXT-X-PROGRAM-DATE-TIME and EXTINF values

    `duration`
      duration attribute from EXTINF parameter

    `byterange`
      byterange attribute from EXT-X-BYTERANGE parameter

    `independent`
      the Partial Segment contains an independent frame

    `gap`
      GAP attribute indicates the Partial Segment is not available

    `dateranges`
      any dateranges that should precede the partial segment

    `gap_tag`
      GAP tag indicates one or more of the parent Media Segment's Partial
      Segments have a GAP=YES attribute. This tag should appear immediately
      after the first EXT-X-PART tag in the Parent Segment with a GAP=YES
      attribute.
    Nc                 C   sV   || _ || _|| _|| _|| _|| _|| _|| _t|	rDdd |	D ng | _	|
| _
d S )Nc                 S   s   g | ]}t f i |qS r   r   r   r   r   r   r1     r   z+PartialSegment.__init__.<locals>.<listcomp>)r(   rE   r   r   r   r   independentgapr   r   r   )r&   r(   rE   r   r   r   r   r   r   r   r   r   r   r   r*      s    zPartialSegment.__init__c                 C   s   g }t | jr(|t| j |d | jr8|d |dt| j| jf  | jrh|d| j  | j	r~|d| j	  | j
r|d| j
  d|S )Nr   r   z #EXT-X-PART:DURATION=%s,URI="%s"z,INDEPENDENT=%sz,BYTERANGE=%sz,GAP=%sr   )r   r   r[   r   r   r   r   rE   r   r   r   r   )r&   r   r   r   r   r   rn     s$    


zPartialSegment.dumpsc                 C   s
   |  d S rl   rm   r0   r   r   r   r   4  s    zPartialSegment.__str__)NNNNNNNr   r   r   r   r*   rn   r   r   r   r   r   r     s   +       
r   c                   @   s   e Zd Zdd ZdS )r   c                 C   s   dd | D }d |S )Nc                 S   s   g | ]}t |qS r   r   )r.   r   r   r   r   r1   :  r   z.PartialSegmentList.__str__.<locals>.<listcomp>r   r   r&   r   r   r   r   r   9  s    zPartialSegmentList.__str__Nr   r   r   r   r   r   r   r   r   8  s   r   c                   @   s6   e Zd ZdZeZdddZdd Zdd Zd	d
 Z	dS )r,   a  
    Key used to encrypt the segments in a m3u8 playlist (EXT-X-KEY)

    `method`
      is a string. ex.: "AES-128"

    `uri`
      is a string. ex:: "https://priv.example.com/key.php?r=52"

    `base_uri`
      uri the key comes from in URI hierarchy. ex.: http://example.com/path/to

    `iv`
      initialization vector. a string representing a hexadecimal number. ex.: 0X12A

    Nc                 K   s.   || _ || _|| _|| _|| _|| _|| _d S rl   )methodrE   iv	keyformatkeyformatversionsr(   Z_extra_params)r&   r   r(   rE   r   r   r   kwargsr   r   r   r*   R  s    
zKey.__init__c                 C   sx   d| j  g}| jr"|d| j  | jr8|d| j  | jrN|d| j  | jrd|d| j  | jd d| S )Nz	METHOD=%szURI="%s"zIV=%szKEYFORMAT="%s"zKEYFORMATVERSIONS="%s"r   r   )r   rE   r[   r   r   r   tagr   r   r   r   r   r   d  s    zKey.__str__c                 C   sP   |sdS | j |j koN| j|jkoN| j|jkoN| j|jkoN| j|jkoN| j|jkS NF)r   rE   r   r(   r   r   r&   otherr   r   r   __eq__s  s    




z
Key.__eq__c                 C   s   |  | S rl   r   r   r   r   r   __ne__  s    z
Key.__ne__)NNNN)
r   r   r   r   r   r   r*   r   r   r   r   r   r   r   r,   >  s       
r,   c                   @   s6   e Zd ZdZeZdddZdd Zdd Zd	d
 Z	dS )r3   aW  
    Used to obtain Media Initialization Section required to
    parse the applicable Media Segments (EXT-X-MAP)

    `uri`
      is a string. ex:: "https://priv.example.com/key.php?r=52"

    `byterange`
      value of BYTERANGE attribute

    `base_uri`
      uri the segment comes from in URI hierarchy. ex.: http://example.com/path/to
    Nc                 C   s   || _ || _|| _d S rl   )r(   rE   r   )r&   r(   rE   r   r   r   r   r*     s    zInitializationSection.__init__c                 C   sN   g }| j r|dt| j   | jr8|dt| j  dj| jd|dS )NURI=z
BYTERANGE=z{tag}:{attributes}r   )r   
attributes)rE   r[   quotedr   r   r   r   r   r   r   r   r     s    zInitializationSection.__str__c                 C   s,   |sdS | j |j ko*| j|jko*| j|jkS r   )rE   r   r(   r   r   r   r   r     s    

zInitializationSection.__eq__c                 C   s   |  | S rl   r   r   r   r   r   r     s    zInitializationSection.__ne__)N)
r   r   r   r   r	   r   r*   r   r   r   r   r   r   r   r3     s   
	r3   c                   @   s   e Zd ZeZdS )rR   N)r   r   r   r
   r   r   r   r   r   rR     s   rR   c                   @   s    e Zd ZdZdd Zdd ZdS )rA   a  
    Playlist object representing a link to a variant M3U8 with a specific bitrate.

    Attributes:

    `stream_info` is a named tuple containing the attributes: `program_id`,
    `bandwidth`, `average_bandwidth`, `resolution`, `codecs` and `resolution`
    which is a a tuple (w, h) of integers

    `media` is a list of related Media entries.

    More info: http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.10
    c           	         s
  || _ || _|d}|d urL|d}|d}t|d t|d f}nd }t|d |d|d|d	|d
|d|d||d|d|d|d|d|d|dd| _g | _dD ]0}||  sq|  jt	 fdd|7  _qd S )N
resolution"xr      	bandwidthvideoaudio	subtitlesclosed_captionsaverage_bandwidth
program_idcodecs
frame_ratevideo_range
hdcp_level
pathway_idstable_variant_idreq_video_layout)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   c                    s
   | j  kS rl   group_id)mr   r   r   <lambda>  r   z#Playlist.__init__.<locals>.<lambda>)
rE   r(   r9   stripsplitint
StreamInfostream_infor@   filter)	r&   rE   r   r@   r(   r   valuesresolution_pair
media_typer   r   r   r*     s>    



zPlaylist.__init__c                 C   sp   g }t | jg}| jD ]@}|j|v r(qq||jg7 }|j }|| d|j d qdd| d | j S )Nz="r   z#EXT-X-STREAM-INF:r   r   )	r   r   r@   typer   r[   r   r   rE   )r&   Zmedia_types
stream_infr@   r  r   r   r   r     s    


zPlaylist.__str__Nr   r   r   r   r*   r   r   r   r   r   rA     s   %rA   c                   @   s    e Zd ZdZdd Zdd ZdS )r_   a  
    IFramePlaylist object representing a link to a
    variant M3U8 i-frame playlist with a specific bitrate.

    Attributes:

    `iframe_stream_info` is a named tuple containing the attributes:
     `program_id`, `bandwidth`, `average_bandwidth`, `codecs`, `video_range`,
     `hdcp_level` and `resolution` which is a tuple (w, h) of integers

    More info: http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.13
    c                 C   s   || _ || _|d}|d urB|d}t|d t|d f}nd }t|d|d|dd d d |d||d	|d
|dd |d|dd d| _d S )Nr   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rE   r(   r9   r   r   r   rF   )r&   r(   rE   rF   r   r  r  r   r   r   r*     s0    

zIFramePlaylist.__init__c                 C   sF  g }| j jr|d| j j  | j jr8|d| j j  | j jrR|d| j j  | j jrt| j jd d t| j jd  }|d|  | j jr|dt| j j  | j j	r|d	| j j	  | j j
r|d
| j j
  | jr|dt| j  | j jr|dt| j j  | j jr8|dt| j j  dd| S )NPROGRAM-ID=%dBANDWIDTH=%dAVERAGE-BANDWIDTH=%dr   r   r   RESOLUTION=CODECS=VIDEO-RANGE=%sHDCP-LEVEL=%sr   PATHWAY-ID=STABLE-VARIANT-ID=z#EXT-X-I-FRAME-STREAM-INF:r   )rF   r   r[   r   r   r   r   r   r   r   r   rE   r   r   r   )r&   Ziframe_stream_infresr   r   r   r   !  sP    





zIFramePlaylist.__str__Nr  r   r   r   r   r_     s   r_   c                   @   sX   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdZdZdZdd Zdd ZdS )r   Nc                 K   s   | d| _| d| _| d| _| d| _| d| _| d| _| d| _| d| _| d	| _	| d
| _
| d| _| d| _| d| _| d| _| d| _d S )Nr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r9   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r&   r   r   r   r   r*   ]  s    zStreamInfo.__init__c                 C   s  g }| j d ur|d| j   | jd ur8|d| j  | jd urR|d| j  | jd url|d| j  | jd urt| jd d t| jd  }|d|  | jd ur|d	t	| j
t	d
  | jd ur|dt| j  | jd ur
|d| j  | jd ur&|d| j  | jd urF|dt| j  | jd urf|dt| j  | jd ur|dt| j  d|S )Nr  zCLOSED-CAPTIONS=%sr  r	  r   r   r   r
  zFRAME-RATE=%gz1.000r  r  r  r  r  zREQ-VIDEO_LAYOUT=r   )r   r[   r   r   r   r   r   r   decimalDecimalquantizer   r   r   r   r   r   r   r   )r&   r  r  r   r   r   r   n  s>    




 

zStreamInfo.__str__)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r*   r   r   r   r   r   r   L  s"   r   c                   @   s*   e Zd ZdZd	ddZdd Zdd ZdS )
r>   a  
    A media object from a M3U8 playlist
    https://tools.ietf.org/html/draft-pantos-http-live-streaming-16#section-4.3.4.1

    `uri`
      a string with the media uri

    `type`
    `group_id`
    `language`
    `assoc-language`
    `name`
    `default`
    `autoselect`
    `forced`
    `instream_id`
    `characteristics`
    `channels`
    `stable_rendition_id`
      attributes in the EXT-MEDIA tag

    `base_uri`
      uri the media comes from in URI hierarchy. ex.: http://example.com/path/to
    Nc                 K   s^   || _ || _|| _|| _|| _|| _|| _|| _|| _|| _	|| _
|	| _|
| _|| _|| _d S rl   )r(   rE   r  r   languagenamedefault
autoselectforcedassoc_languageinstream_idcharacteristicschannelsstable_rendition_idextras)r&   rE   r  r   r  r  r  r  r  r  r  r  r  r  r(   r  r   r   r   r*     s    zMedia.__init__c                 C   sZ  g }| j r|dt| j   | jr4|d| j  | jrN|dt| j  | jrh|dt| j  | jr|dt| j  | jr|dt| j  | jr|d| j  | j	r|d| j	  | j
r|d	| j
  | jr|d
t| j  | jr|dt| j  | jr0|dt| j  | jrL|dt| j  dd| S )Nr   TYPE=z	GROUP-ID=	LANGUAGE=zASSOC-LANGUAGE=zNAME=zDEFAULT=zAUTOSELECT=zFORCED=zINSTREAM-ID=zCHARACTERISTICS=z	CHANNELS=zSTABLE-RENDITION-ID=z#EXT-X-MEDIA:r   )rE   r[   r   r  r   r  r  r  r  r  r  r  r  r  r  r   )r&   Z	media_outr   r   r   rn     s8    zMedia.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r     s    zMedia.__str__)NNNNNNNNNNNNNNr   r   r   r   r   r>     s$                 
" r>   c                   @   s   e Zd Zdd ZdS )TagListc                 C   s   dd | D }d |S )Nc                 S   s   g | ]}t |qS r   r   )r.   r   r   r   r   r1     r   z#TagList.__str__.<locals>.<listcomp>r   r   r   r   r   r   r     s    zTagList.__str__Nr   r   r   r   r   r"    s   r"  c                   @   s   e Zd Zedd ZdS )r]   c                 C   s   dd | D S )Nc                 S   s   g | ]
}|j qS r   r   r?   r   r   r   r1     r   z!MediaList.uri.<locals>.<listcomp>r   r0   r   r   r   rE     s    zMediaList.uriN)r   r   r   r   rE   r   r   r   r   r]     s   r]   c                   @   s   e Zd ZdS )r^   Nr   r   r   r   r   r^     s   r^   c                   @   s   e Zd ZdS )rf   Nr   r   r   r   r   rf     s   rf   c                   @   s   e Zd ZdddZdd ZdS )ra   Nc                 C   s   t || _|| _d S rl   )floattime_offsetprecise)r&   r$  r%  r   r   r   r*     s    
zStart.__init__c                 C   sF   dt | j g}| jr4| jdv r4|dt | j  td d| S )NzTIME-OFFSET=)ZYESNOzPRECISE=r   r   )r   r$  r%  r[   r   r   r   r   r   r   r     s    zStart.__str__)N)r   r   r   r*   r   r   r   r   r   ra     s   
ra   c                   @   s&   e Zd ZdddZdd Zdd ZdS )	rM   Nc                 C   s   || _ || _|| _|| _d S rl   )r(   rE   last_msn	last_part)r&   r(   rE   r'  r(  r   r   r   r*     s    zRenditionReport.__init__c                 C   sX   g }| dt| j  | dt| j  | jd urJ| dt| j  dd| S )Nr   z	LAST-MSN=z
LAST-PART=z#EXT-X-RENDITION-REPORT:r   )r[   r   rE   r   r'  r(  r   r{   r   r   r   rn     s    
zRenditionReport.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r      s    zRenditionReport.__str__)Nr   r   r   r*   rn   r   r   r   r   r   rM     s   
	rM   c                   @   s   e Zd Zdd ZdS )re   c                 C   s   dd | D }d |S )Nc                 S   s   g | ]}t |qS r   r   )r.   r|   r   r   r   r1   &  r   z/RenditionReportList.__str__.<locals>.<listcomp>r   r   r   r   r   r   r   %  s    zRenditionReportList.__str__Nr   r   r   r   r   re   $  s   re   c                   @   s.   e Zd Zd
ddZdd Zdd Zdd	 ZdS )rb   Nc                 C   s"   || _ || _|| _|| _|| _d S rl   )can_skip_untilcan_block_reload	hold_backpart_hold_backcan_skip_dateranges)r&   r*  r+  r,  r-  r.  r   r   r   r*   +  s
    zServerControl.__init__c                 C   s
   t | |S rl   getattrr&   itemr   r   r   __getitem__9  s    zServerControl.__getitem__c                 C   s   g }| j r|d| j   dD ]*}| | r|dt|t| | f  q| jrz|dt| j  | jrz|d| j  dd| S )NzCAN-BLOCK-RELOAD=%s)r,  r-  z%s=%szCAN-SKIP-UNTIL=%szCAN-SKIP-DATERANGES=%sz#EXT-X-SERVER-CONTROL:r   )r+  r[   denormalize_attributer   r*  r.  r   )r&   Zctrlri   r   r   r   rn   <  s    zServerControl.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r   O  s    zServerControl.__str__)NNNNNr   r   r   r*   r3  rn   r   r   r   r   r   rb   *  s        
rb   c                   @   s&   e Zd ZdddZdd Zdd ZdS )	rd   Nc                 C   s   || _ || _d S rl   )skipped_segmentsrecently_removed_dateranges)r&   r6  r7  r   r   r   r*   T  s    zSkip.__init__c                 C   s@   g }| d| j  | jd ur2| dt| j  dd| S )NzSKIPPED-SEGMENTS=%szRECENTLY-REMOVED-DATERANGES=%sz#EXT-X-SKIP:r   )r[   r6  r7  r   r   )r&   rL   r   r   r   rn   X  s    
z
Skip.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r   c  s    zSkip.__str__)Nr)  r   r   r   r   rd   S  s   
rd   c                   @   s&   e Zd ZdddZdd Zdd ZdS )	rc   Nc                 C   s
   || _ d S rl   )part_target)r&   r8  r   r   r   r*   h  s    zPartInformation.__init__c                 C   s   dt | j S )Nz#EXT-X-PART-INF:PART-TARGET=%s)r   r8  r0   r   r   r   rn   k  s    zPartInformation.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r   n  s    zPartInformation.__str__)Nr)  r   r   r   r   rc   g  s   
rc   c                   @   s.   e Zd Zd
ddZdd Zdd Zdd	 ZdS )rg   Nc                 C   s"   || _ || _|| _|| _|| _d S rl   )	hint_typer(   rE   byterange_startbyterange_length)r&   r  r(   rE   r:  r;  r   r   r   r*   s  s
    zPreloadHint.__init__c                 C   s
   t | |S rl   r/  r1  r   r   r   r3  |  s    zPreloadHint.__getitem__c                 C   sh   g }| d| j  | dt| j  dD ],}| | d ur,| t| d| |   q,dd| S )Nr   r   )r:  r;  r   z#EXT-X-PRELOAD-HINT:r   )r[   r9  r   rE   r4  r   )r&   hintri   r   r   r   rn     s    zPreloadHint.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r     s    zPreloadHint.__str__)NNr5  r   r   r   r   rg   r  s
    
	rg   c                   @   s&   e Zd ZdddZdd Zdd ZdS )	rP   Nc                 C   s   || _ || _|| _|| _d S rl   )rO   valuerE   r  )r&   rO   r=  rE   r  r   r   r   r*     s    zSessionData.__init__c                 C   sn   dt | j g}| jr,|dt | j  n| jrF|dt | j  | jr`|dt | j  dd| S )NzDATA-ID=zVALUE=r   r!  z#EXT-X-SESSION-DATA:r   )r   rO   r=  r[   rE   r  r   )r&   Zsession_data_outr   r   r   rn     s    zSessionData.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r     s    zSessionData.__str__)NNNr)  r   r   r   r   rP     s   
rP   c                   @   s   e Zd ZdS )r   Nr   r   r   r   r   r     s   r   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )r   c                    s    d | _  d| _ d| _ d| _ d| _ d| _ d| _ d| _ d	| _	 d
| _
 fdd D | _d S )Nid
start_dateclassend_dater   planned_duration
scte35_cmd
scte35_out	scte35_inend_on_nextc                    s$   g | ]}| d r| |fqS )Zx_)
startswithr9   )r.   ri   r   r   r   r1     s   z&DateRange.__init__.<locals>.<listcomp>)r>  r9   r?  class_rA  r   rB  rC  rD  rE  rF  x_client_attrsr  r   rH  r   r*     s    

zDateRange.__init__c                 C   s,  g }| dt| j  | jr2| dt| j  | jrL| dt| j  | jrf| dt| j  | jr| dt| j  | jr| dt| j  | j	r| d| j	  | j
r| d| j
  | jr| d	| j  | jr| d
| j  t| jD ] \}}| t| d|  qdd| S )NzID=zSTART-DATE=zCLASS=z	END-DATE=	DURATION=zPLANNED-DURATION=zSCTE35-CMD=zSCTE35-OUT=z
SCTE35-IN=zEND-ON-NEXT=r   z#EXT-X-DATERANGE:r   )r[   r   r>  r?  rI  rA  r   r   rB  rC  rD  rE  rF  sortedrJ  r4  r   )r&   r   ri   r=  r   r   r   rn     s2    zDateRange.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r     s    zDateRange.__str__Nr)  r   r   r   r   r     s   #r   c                   @   s&   e Zd ZdddZdd Zdd ZdS )	rh   Nc                 C   s   || _ || _|| _d S rl   )r(   rE   r   )r&   r(   Z
server_urir   r   r   r   r*     s    zContentSteering.__init__c                 C   sD   g }| dt| j  | jd ur6| dt| j  dd| S )NzSERVER-URI=r  z#EXT-X-CONTENT-STEERING:r   )r[   r   rE   r   r   )r&   Zsteeringr   r   r   rn     s
    
zContentSteering.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r     s    zContentSteering.__str__)Nr)  r   r   r   r   rh     s   
	rh   c                   @   s    e Zd ZdZdd Zdd ZdS )r`   a~  
    ImagePlaylist object representing a link to a
    variant M3U8 image playlist with a specific bitrate.

    Attributes:

    `image_stream_info` is a named tuple containing the attributes:
     `bandwidth`, `resolution` which is a tuple (w, h) of integers and `codecs`,

    More info: https://github.com/image-media-playlist/spec/blob/master/image_media_playlist_v0_4.pdf
    c                 C   s   || _ || _|d}|d urB|d}t|d t|d f}nd }t|d|d|dd d d |d||d	d d d |d
|dd| _d S )Nr   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rE   r(   r9   r   r   r   rH   )r&   r(   rE   rH   r   r  r  r   r   r   r*      s.    

zImagePlaylist.__init__c                 C   s  g }| j jr|d| j j  | j jr8|d| j j  | j jrR|d| j j  | j jrt| j jd d t| j jd  }|d|  | j jr|dt| j j  | j	r|d	t| j	  | j j
r|d
t| j j
  | j jr|dt| j j  dd| S )Nr  r  r	  r   r   r   r
  r  r   r  r  z#EXT-X-IMAGE-STREAM-INF:r   )rH   r   r[   r   r   r   r   r   r   rE   r   r   r   )r&   Zimage_stream_infr  r   r   r   r     s<    

zImagePlaylist.__str__Nr  r   r   r   r   r`     s   r`   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	Tilesz
    Image tiles from a M3U8 playlist

    `resolution`
      resolution attribute from EXT-X-TILES tag

    `layout`
      layout attribute from EXT-X-TILES tag

    `duration`
      duration attribute from EXT-X-TILES tag
    c                 C   s   || _ || _|| _d S rl   )r   layoutr   )r&   r   rN  r   r   r   r   r*   M  s    zTiles.__init__c                 C   sB   g }| d| j  | d| j  | d| j  dd| S )Nr
  zLAYOUT=rK  z#EXT-X-TILES:r   )r[   r   rN  r   r   )r&   Ztilesr   r   r   rn   R  s
    zTiles.dumpsc                 C   s   |   S rl   rm   r0   r   r   r   r   Z  s    zTiles.__str__Nr   r   r   r   r   rM  ?  s   rM  c                 C   s`   | sd S |D ]F}|r|  dd |jkr|  dd|jkr|  dd |jkr|  S qtdd S )NrE   r   NONEr   zNo key found for key data)r9   rE   r   r   KeyError)ZkeydataZkeylistr5   r   r   r   r8   ^  s    
r8   c                 C   s   |  dd S )N_-)replacer   )	attributer   r   r   r4  m  s    r4  c                 C   s   d|  S )Nz"%s"r   )stringr   r   r   r   q  s    r   c                 C   sh   t  L}d|_t t| }t|| kr<|t dn| W  d    S 1 sZ0    Y  d S )N   r   )r  localcontextprecr  r   to_integral_valuer  	normalize)numberctxdr   r   r   r   u  s    

r   )3r  r   Zm3u8.mixinsr   r   Zm3u8.parserr   r   Zm3u8.protocolr   r   r   r	   r
   r   	Exceptionr   r   r7   listrV   r   r   r,   r3   rR   rA   r_   r   r>   r"  r]   r^   rf   ra   rM   re   rb   rd   rc   rg   rP   r   r   rh   r`   rM  r8   r4  r   r   r   r   r   r   <module>   sV    
   0  _E+BXC`)7L