
    CcQ                     $   d Z g dZddlZddlZddlmZ ddlmZ ddlm	Z	m
Z
mZ ddlmZmZmZmZmZmZmZmZmZmZ d Z ed	      \  ZZZd
ZdZdZ G d de      Z G d de      Z  G d de      Z! G d de      Z" G d de#      Z$ G d de      Z% G d de%e	      Z&e&Z' ee(e       edd      d               Z)d Z*d  Z+ G d! d"e#      Z,e G d# d$e,             Z- G d% d&e-e      Z.e G d' d(e,             Z/ G d) d*e-      Z0 G d+ d,e
      Z1y)-a  APEv2 reading and writing.

The APEv2 format is most commonly used with Musepack files, but is
also the format of choice for WavPack and other formats. Some MP3s
also have APEv2 tags, but this can cause problems with many MP3
decoders and taggers.

APEv2 tags, like Vorbis comments, are freeform key=value pairs. APEv2
keys can be any ASCII string with characters from 0x20 to 0x7E,
between 2 and 255 characters long.  Keys are case-sensitive, but
readers are recommended to be case insensitive, and it is forbidden to
multiple keys which differ only in case.  Keys are usually stored
title-cased (e.g. 'Artist' rather than 'artist').

APEv2 values are slightly more structured than Vorbis comments; values
are flagged as one of text, binary, or an external reference (usually
a URI).

Based off the format specification found at
http://wiki.hydrogenaudio.org/index.php?title=APEv2_specification.
)APEv2	APEv2FileOpendelete    N)BytesIO)MutableSequence)MetadataFileType
StreamInfo)
	DictMixincdatadelete_bytestotal_orderingMutagenErrorloadfileconvert_errorseek_endget_sizereraisec                     t        | t              st        d      dt        |       cxk  xr dk  nc xr$ t	        |       dk\  xr t        |       dk  xr | dvS )NzAPEv2 key must be str       ~)OggSTAGID3zMP+)
isinstancestr	TypeErrorlenminmaxkeys    //usr/lib/python3/dist-packages/mutagen/apev2.pyis_valid_apev2_keyr'   *   s_    c3/00 #c(!c! ;CD(8 ;X;99<       l        i   @i    c                       e Zd Zy)errorN__name__
__module____qualname__ r(   r&   r+   r+   ?       r(   r+   c                       e Zd Zy)APENoHeaderErrorNr,   r0   r(   r&   r3   r3   C   r1   r(   r3   c                       e Zd Zy)APEUnsupportedVersionErrorNr,   r0   r(   r&   r5   r5   G   r1   r(   r5   c                       e Zd Zy)APEBadItemErrorNr,   r0   r(   r&   r7   r7   K   r1   r(   r7   c                   T    e Zd ZdxZxZxZxZZdZdZ	dZ
dZdZdZdZd Zd Zd Zd Zy)
_APEv2DataNr   Fc                    | j                  |       | j                  | j                  | _        nC| j                  | j                  | _        n%t	        | j                  | j                        | _        | j                  y| j                  |       | j                  |       | j                  <|j                  | j                         |j                  | j                        | _        yy)Raises IOError and apev2.errorN)_APEv2Data__find_metadataheaderfootermetadatar#   _APEv2Data__fill_missing_APEv2Data__fix_brokennessdataseekreadsizetagselffileobjs     r&   __init__z_APEv2Data.__init__a   s     	W%;; KKDM[[  KKDMT[[9DM== G$g&99 LL#||DII.DH !r(   c                     	 |j                  dd       |j                  d      dk(  r/|j                  dd       |j                         x| _        | _        y 	 t        |      dk  rt        |j                  d	d       |j                  d
      dk(  r|j                  dd       |j                  d      dk(  r(|j                  dd       |j                         | _        y |j                  dd       |j                  d      dk(  r|j                  dd       	 t        |j                  d            }|j                  d|z
  dz
  d       |j                  d      dk(  r(|j                  dd       |j                         | _        y |j                  dd       |j                  d      dk(  rd| _	        d| _
        y y # t        $ r |j                  dd       Y y w xY w# t        $ r t        w xY w# t        $ r Y uw xY w)Nir   r         APETAGEX      ir)   s   TAGi   	   s	   LYRICS200i   T)rC   IOErrorrD   tellr>   r?   r   int
ValueErroris_at_startr=   )rH   rI   offsets      r&   __find_metadataz_APEv2Data.__find_metadatav   s   	LLa  <<?k)LLQ*1,,.8DK$-	 3&LLq!||A&(S!$<<?k1LLQ'"),,.DK
 R#<<?l2LLa(&!$W\\!_!5 LLv!115||A+5R+&-lln 	Q<<?k)#DDK *W  	LLA	: & &%&  		sC   F= BG1  8G1 G 3AG1 =GGG..G1 1	G=<G=c                    |j                  | j                  dz          |j                  d      }t        |      dk7  rt        |dd | _        t        j                  |dd       | _        t        j                  |dd       | _	        t        j                  |dd       | _
        | j                  z| j                  dz   | _        | j                  | j                  z   | _        |j                  | j                  dz
  d       |j                  d      dk(  r| j                  dz
  | _        n| j                  l| j                  dz   | _        | j                  | j                  z
  | _        | j                  t        z  r| j                  dz
  | _        n| j                  | _        nt!        d	      | j                  | xj                  dz  c_        yy)
r;   rL      N          r   rM   No APE tag found)rC   r?   rD   r!   r+   versionr   	uint32_lerE   itemsflagsr=   rB   endr>   
HAS_HEADERr3   )rH   rI   rB   s      r&   __fill_missingz_APEv2Data.__fill_missing   si    	T]]Q&'||Bt9?KBQxOOD1I.	__T!BZ0
__T"#Y/
;;"b(DI yy499,DHLLB*||A+-"hhm[[${{R'DH499,DIzzJ&"ii"n"ii"#566 ;;"IIOI #r(   c                 f   | j                   | j                   }n| j                  }|j                  |       |dkD  rY	 |j                  dd       |j                  d      dk(  r#|j                  dd       |j	                         }n		 || _        y |dkD  rY|| _        y # t
        $ r
 Y || _        y w xY w)Nr   irO   rL   rM   rN   )r=   rB   rC   rD   rU   rT   start)rH   rI   ri   s      r&   __fix_brokennessz_APEv2Data.__fix_brokenness   s    ;;"KKEIIEUai	S!$ <<?k1LLQ'#LLNE
 ai 
   
s   B 	B0/B0)r-   r.   r/   ri   r=   rB   r>   re   r?   rF   ra   rE   rc   rd   rX   rJ   r<   r@   rA   r0   r(   r&   r9   r9   O   sV    +//E/F/T/FSH
CGDEE
 K/*3j"Hr(   r9   c                   6     e Zd Z fdZd Zd Zd Zd Z xZS )_CIDictProxyc                 H    i | _         i | _        t        t        |   |i | y N)_CIDictProxy__casemap_CIDictProxy__dictsuperrl   rJ   )rH   argskwargs	__class__s      r&   rJ   z_CIDictProxy.__init__   s%    lD*D;F;r(   c                 <    | j                   |j                            S rn   )rp   lowerrH   r%   s     r&   __getitem__z_CIDictProxy.__getitem__   s    {{399;''r(   c                 `    |j                         }|| j                  |<   || j                  |<   y rn   rv   ro   rp   )rH   r%   valuerv   s       r&   __setitem__z_CIDictProxy.__setitem__   s)    		 #u"Er(   c                 X    |j                         }| j                  |= | j                  |= y rn   rz   )rH   r%   rv   s      r&   __delitem__z_CIDictProxy.__delitem__   s%    		NN5!KKr(   c                     | j                   j                         D cg c]  }| j                  j                  ||        c}S c c}w rn   )rp   keysro   getrw   s     r&   r   z_CIDictProxy.keys  s4    8<8H8H8JK""3,KKKs   #A)	r-   r.   r/   rJ   rx   r|   r~   r   __classcell__rt   s   @r&   rl   rl      s    <(#
 
Lr(   rl   c                        e Zd ZdZdZd Z eee       e	       d               Z
d Z fdZ fdZ fdZ eee       e	d	d	
      dd              Z eee       e	d	      dd              Z xZS )r   zoAPEv2(filething=None)

    A file with an APEv2 tag.

    ID3v1 tags are silently ignored and overwritten.
    Nc                 d    t        | j                               }dj                  d |D              S )z6Return tag key=value pairs in a human-readable format.
c              3   L   K   | ]  \  }}|d |j                           yw)=N)pprint).0kvs      r&   	<genexpr>zAPEv2.pprint.<locals>.<genexpr>  s     GAa4Gs   "$)sortedrc   join)rH   rc   s     r&   r   zAPEv2.pprint  s)     tzz|$zzGGGGr(   c                     t        |j                        }|j                  r7| j                          | j	                  |j                  |j
                         yt        d      )z?Load tags from a filename.

        Raises apev2.error
        r`   N)r9   rI   rF   clear_APEv2__parse_tagrc   r3   )rH   	filethingrB   s      r&   loadz
APEv2.load  sH     )++,88JJLTXXtzz2"#566r(   c                    t        |      }t        |      D ]%  }|j                  d      }|s yt        |      dk7  rt        t        j                  |dd       }t        j                  |dd       }|dz  dz	  }|dk(  rt        d      |j                  d      x}	}
|	st        |	dd d	k7  r+|
r)|j                  d      }
|
st        |	|
z  }	|	dd d	k7  r|
r)|	dd d	k(  r|	dd }		 |	j                  d
      }	|j                  |      }
t        |
      |k7  rt        t        |      j                  |
      }
|
| |	<   ( y# t        $ r0}t        t        |t        j                         d          Y d}~|d}~ww xY w)z"Raises IOError and APEBadItemErrorrL   Nr]   rS   rO   r)   zvalue type must be 0, 1, or 2    asciir   )r   rangerD   r!   r+   r   rb   r7   decodeUnicodeErrorr   sysexc_info_get_value_type_new)rH   rF   countrI   itag_datarE   rd   kindr%   r{   errs               r&   __parse_tagzAPEv2.__parse_tag%  s    #,u %	A||AH8}!??8BQ<0DOOHQqM2E AI!#Dqy%&EFF!,,q/)C%%%bc(g%%Q))u	 bc(g%%
 23x7"#2hAjj) LL&E5zT!%%#D)..u5EDIK%	:   AcllnQ.?@@As   (E	E:
&E55E:c                 \    t        |      st        d|z        t        t        |   |      S N%r is not a valid APEv2 key)r'   KeyErrorrq   r   rx   rH   r%   rt   s     r&   rx   zAPEv2.__getitem__Q  s.    !#&83>??UD-c22r(   c                 ^    t        |      st        d|z        t        t        |   |       y r   )r'   r   rq   r   r~   r   s     r&   r~   zAPEv2.__delitem__W  s+    !#&83>??eT&s+r(   c                    t        |      st        d|z        t        |t              st        |t              rt        |t              }nut        |t              rUg }|D ].  }t        |t              st        d      |j                  |       0 t        dj                  |      t              }nt        |t              }t        t        | ;  ||       y)aA  'Magic' value setter.

        This function tries to guess at what kind of value you want to
        store. If you pass in a valid UTF-8 or Unicode string, it
        treats it as a text value. If you pass in a list, it treats it
        as a list of string/Unicode values.  If you pass in a string
        that is not valid UTF-8, it assumes it is a binary value.

        Python 3: all bytes will be assumed to be a byte value, even
        if they are valid utf-8.

        If you need to force a specific type of value (e.g. binary
        data that also happens to be valid UTF-8, or an external
        reference), use the APEValue factory and set the value to the
        result of that::

            from mutagen.apev2 import APEValue, EXTERNAL
            tag['Website'] = APEValue('http://example.org', EXTERNAL)
        r   zitem in list not str N)r'   r   r   	_APEValuer   APEValueTEXTlistr    appendr   BINARYrq   r   r|   )rH   r%   r{   rc   r   rt   s        r&   r|   zAPEv2.__setitem__]  s    * "#&83>??%+%% -E4( $A%a-'(>??LLO$ !E!2D9 /eT&sE2r(   T)writablecreatec           	      P   |j                   }t        |      }|j                  r/t        ||j                  |j
                  z
  |j
                         n7|j
                  +|j                  |j
                         |j                          |j                  dd       g }| j                         D ]  \  }}|j                         }t        |t              s|j                  d      }t               }|t        j                  dt!        |      |j"                  dz        z  }||dz   |z   z  }|j%                  t        |              |j'                  d 	       t!        |      }	d
j)                  |      }t        d      }
|
t        j                  ddt!        |      dz   |	t*        t,        z        z  }
|
dz  }
|j/                  |
       |j/                  |       t        d      }|t        j                  ddt!        |      dz   |	t*              z  }|dz  }|j/                  |       y)zSave changes to a file.

        If no filename is given, the one most recently loaded is used.

        Tags are always written at the end of the file, and include
        a header and a footer.
        Nr   r   utf-8z<2IrO   r   c                     t        |       | fS rn   r!   )rF   s    r&   <lambda>zAPEv2.save.<locals>.<lambda>  s    3s8S/ r(   r$   r(   rM   z<4Ii  r_   s           )rI   r9   rX   r   re   ri   rC   truncaterc   _writer   bytesencode	bytearraystructpackr!   r   r   sortr   rf   	IS_HEADERwrite)rH   r   rI   rB   tagsr%   r{   
value_datar   num_tagsr=   r>   s               r&   savez
APEv2.save  s    ##'"$((TZZ"7DZZ#LL$Q**, 	)JC Jc5)jj) {HE3z?EJJ!OLLHej00HKKh(	)$ 			1	2t9xx~;'&++eT3t9r>8(946 	6)fd;'&++eT3t9r>8(* 	*)fr(   )r   c                     |j                   }t        |      }|j                  :|j                  .t	        ||j
                  |j                  z
  |j                         | j                          y)zRemove tags from a file.N)rI   r9   ri   rE   r   re   r   )rH   r   rI   rB   s       r&   r   zAPEv2.delete  sR    
 ##'"::!dii&;$((TZZ"7D

r(   rn   )r-   r.   r/   __doc__filenamer   r   rT   r+   r   r   r   rx   r~   r|   r   r   r   r   s   @r&   r   r     s     HH 7E"Z7  #7*X3,)3V 7E"tD): * #:x 7E"t  #r(   r   FT)methodr   c                     	 t        |       }| j                  j                  d       |j	                  |        y# t        $ r Y yw xY w)zdelete(filething)

    Arguments:
        filething (filething)
    Raises:
        mutagen.MutagenError

    Remove tags from a file.
    Nr   )r   r3   rI   rC   r   )r   ts     r&   r   r     sG    ) 1HHY  s   : 	AAc                 x    | t         k(  rt        S | t        k(  rt        S | t        k(  rt
        S t        d| z        )z1Returns a _APEValue subclass or raises ValueErrorzunknown kind %r)r   APETextValuer   APEBinaryValueEXTERNALAPEExtValuerW   )r   s    r&   r   r     s=     t|			
&-
..r(   c                 Z    	 t        |      } ||       S # t        $ r t        d      w xY w)zAPEv2 tag value factory.

    Use this if you need to specify the value's type manually.  Binary
    and text data are automatically detected by APEv2.__setitem__.
    z&kind must be TEXT, BINARY, or EXTERNAL)r   rW   )r{   r   type_s      r&   r   r     s<    % U|  CABBCs    *c                   L    e Zd ZU eed<   dZd	dZed        Zd Z	d Z
d Zd Zy)
r   r   Nc                 ^    ||| j                   k7  rt        | j                  |      | _        y rn   )r   rW   	_validater{   )rH   r{   r   s      r&   rJ   z_APEValue.__init__
  s)    		 1^^E*
r(   c                 J    | j                  |       }|j                  |       |S rn   )__new___parse)clsrB   instances      r&   r   z_APEValue._new  s!    ;;s#r(   c                     t         )z$Sets value or raises APEBadItemErrorNotImplementedErrorrH   rB   s     r&   r   z_APEValue._parse  
     "!r(   c                     t         )zReturns bytesr   rH   s    r&   r   z_APEValue._write  r   r(   c                     t         )z5Returns validated value or raises TypeError/ValueErrrr   rH   r{   s     r&   r   z_APEValue._validate   r   r(   c                 `    dt        |       j                  | j                  | j                  fz  S )Nz
%s(%r, %d))typer-   r{   r   r   s    r&   __repr__z_APEValue.__repr__%  s&    tDz22DJJ		JJJr(   rn   )r-   r.   r/   rV   __annotations__r{   rJ   classmethodr   r   r   r   r   r0   r(   r&   r   r     s:    
IE+  
"
"
"
Kr(   r   c                   <    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
y	)
_APEUtf8Valuec                     	 |j                  d      | _        y # t        $ r0}t        t        |t        j                         d          Y d }~y d }~ww xY w)Nr   r   )r   r{   UnicodeDecodeErrorr   r7   r   r   )rH   rB   es      r&   r   z_APEUtf8Value._parse,  sA    	;W-DJ! 	;OQq(9::	;s    	A&AAc                 <    t        |t              st        d      |S )Nvalue not str)r   r   r    r   s     r&   r   z_APEUtf8Value._validate2  s    %%O,,r(   c                 8    | j                   j                  d      S )Nr   )r{   r   r   s    r&   r   z_APEUtf8Value._write7  s    zz  ))r(   c                 ,    t        | j                        S rn   r!   r{   r   s    r&   __len__z_APEUtf8Value.__len__:      4::r(   c                 "    | j                         S rn   r   r   s    r&   	__bytes__z_APEUtf8Value.__bytes__=      {{}r(   c                      | j                   |k(  S rn   r{   rH   others     r&   __eq__z_APEUtf8Value.__eq__@      zzU""r(   c                      | j                   |k  S rn   r   r   s     r&   __lt__z_APEUtf8Value.__lt__C      zzE!!r(   c                     | j                   S rn   r   r   s    r&   __str__z_APEUtf8Value.__str__F      zzr(   N)r-   r.   r/   r   r   r   r   r   r   r  r  r0   r(   r&   r   r   )  s*    ;
*#"r(   r   c                   >    e Zd ZdZeZd Zd Zd Zd Z	d Z
d Zd Zy	)
r   zAn APEv2 text value.

    Text values are Unicode/UTF-8 strings. They can be accessed like
    strings (with a null separating the values), or arrays of strings.
    c                 J    t        | j                  j                  d            S )z:Iterate over the strings of the value (not the characters)r   )iterr{   splitr   s    r&   __iter__zAPETextValue.__iter__S  s     DJJ$$U+,,r(   c                 >    | j                   j                  d      |   S Nr   )r{   r  )rH   indexs     r&   rx   zAPETextValue.__getitem__X  s    zz&u--r(   c                 >    | j                   j                  d      dz   S )Nr   rO   )r{   r   r   s    r&   r   zAPETextValue.__len__[  s    zz&**r(   c                     t        |t              st        d      t        |       }|||<   dj	                  |      | _        y Nr   r   )r   r   r    r   r   r{   rH   r  r{   valuess       r&   r|   zAPETextValue.__setitem__^  s9    %%O,,duZZ'
r(   c                     t        |t              st        d      t        |       }|j	                  ||       dj                  |      | _        y r  )r   r   r    r   insertr   r{   r  s       r&   r  zAPETextValue.insertf  s>    %%O,,deU#ZZ'
r(   c                 L    t        |       }||= dj                  |      | _        y r  )r   r   r{   )rH   r  r  s      r&   r~   zAPETextValue.__delitem__n  s"    d5MZZ'
r(   c                 $    dj                  |       S )Nz / )r   r   s    r&   r   zAPETextValue.pprints  s    {{4  r(   N)r-   r.   r/   r   r   r   r  rx   r   r|   r  r~   r   r0   r(   r&   r   r   J  s1     D-
.+(((
!r(   r   c                   D    e Zd ZdZeZd Zd Zd Zd Z	d Z
d Zd Zd	 Zy
)r   zAn APEv2 binary value.c                     || _         y rn   r   r   s     r&   r   zAPEBinaryValue._parse}  s	    
r(   c                     | j                   S rn   r   r   s    r&   r   zAPEBinaryValue._write  r  r(   c                 N    t        |t              st        d      t        |      S )Nzvalue not bytes)r   r   r    r   s     r&   r   zAPEBinaryValue._validate  s"    %'-..U|r(   c                 ,    t        | j                        S rn   r   r   s    r&   r   zAPEBinaryValue.__len__  r   r(   c                 "    | j                         S rn   r   r   s    r&   r   zAPEBinaryValue.__bytes__  r   r(   c                      | j                   |k(  S rn   r   r   s     r&   r   zAPEBinaryValue.__eq__  r  r(   c                      | j                   |k  S rn   r   r   s     r&   r  zAPEBinaryValue.__lt__  r  r(   c                     dt        |       z  S )Nz
[%d bytes]r   r   s    r&   r   zAPEBinaryValue.pprint  s    s4y((r(   N)r-   r.   r/   r   r   r   r   r   r   r   r   r   r  r   r0   r(   r&   r   r   w  s2     D
#")r(   r   c                       e Zd ZdZeZd Zy)r   zRAn APEv2 external value.

    External values are usually URI or IRI strings.
    c                      d| j                   z  S )Nz[External] %sr   r   s    r&   r   zAPEExtValue.pprint  s    $**,,r(   N)r-   r.   r/   r   r   r   r   r0   r(   r&   r   r     s    
 D-r(   r   c                   V    e Zd ZdZ G d de      Z e       d        Zd Ze	d        Z
y)r   zoAPEv2File(filething)

    Arguments:
        filething (filething)

    Attributes:
        tags (`APEv2`)
    c                   *    e Zd ZdZdZd Zed        Zy)APEv2File._Infor   c                      y rn   r0   rG   s     r&   rJ   zAPEv2File._Info.__init__  s    r(   c                       y)NzUnknown format with APEv2 tag.r0   r0   r(   r&   r   zAPEv2File._Info.pprint  s    4r(   N)r-   r.   r/   lengthbitraterJ   staticmethodr   r0   r(   r&   _Infor&    s%    	 
	5 
	5r(   r,  c                     |j                   }| j                  |      | _        	 |j                  dd       	 t        |      | _        y # t        $ r}t        |      d }~ww xY w# t        $ r
 d | _        Y y w xY w)Nr   )	rI   r,  inforC   rT   r+   r   r   r3   )rH   r   rI   r   s       r&   r   zAPEv2File.load  sr    ##JJw'		LLA	gDI	  	(N	
   	DI	s(   A A$ 	A!AA!$A76A7c                 n    | j                   t               | _         y t        | d| j                         )Nz already has tags: )r   r   r+   r   s    r&   add_tagszAPEv2File.add_tags  s)    99DIT499EFFr(   c                     	 t        |d       |j                         }d|v |j                  d      z
  S # t        $ r Y yw xY w)N   r   rM   s   ID3)r   rD   rT   
startswith)r   rI   r=   r>   s       r&   scorezAPEv2File.score  sM    	Wc"\\^F &&*;*;F*CCD  		s   4 	A A N)r-   r.   r/   r   r   r,  r   r   r0  r+  r4  r0   r(   r&   r   r     sE    	5
 	5 Z G E Er(   r   )2r   __all__r   r   ior   collections.abcr   mutagenr	   r
   r   mutagen._utilr   r   r   r   r   r   r   r   r   r   r'   r   r   r   r   rf   HAS_NO_FOOTERr   r+   r3   r5   r7   objectr9   rl   r   r   rT   r   r   r   r   r   r   r   r   r   r0   r(   r&   <module>r<     sd  , 3 
   + 2 2G G G< q fh
		L 		u 		 		e 	U UpL9 L<JL( JZ  w	& ' &	/!K !KH I  @*!=/ *!Z )Y ) )@	-- 	-1E 1Er(   