a
    ÇZEgýZ  ã                   @  s’  d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	m
Z
 ddlmZmZ ddlmZmZ er�dd	lmZmZ dd
lmZ ddlmZ dddœdd„Zdddœdd„ZG dd„ deƒZG dd„ dƒZG dd„ dƒZd;ddddddddœdd „Ze d!¡Zdddœd"d#„Z d<ddd&dd'œd(d)„Z!d=d+dd&dddddddd,d-œd.d/„Z"dd*ddddd%d0œddddddd1d&d2d3œ	d4d5„Z#d6d1d7d8œd9d:„Z$dS )>zî
    babel.messages.pofile
    ~~~~~~~~~~~~~~~~~~~~~

    Reading and writing of files in the ``gettext`` PO (portable object)
    format.

    :copyright: (c) 2013-2024 by the Babel Team.
    :license: BSD, see LICENSE for more details.
é    )ÚannotationsN)ÚIterable)ÚTYPE_CHECKING)ÚLocale)ÚCatalogÚMessage)Ú_cmpÚwraptext)ÚIOÚAnyStr)ÚSupportsWrite)ÚLiteralÚstr)ÚstringÚreturnc                 C  s"   dd„ }t  d¡ || dd… ¡S )z¿Reverse `escape` the given string.

    >>> print(unescape('"Say:\\n  \\"hello, world!\\"\\n"'))
    Say:
      "hello, world!"
    <BLANKLINE>

    :param string: the string to unescape
    c                 S  s2   |   d¡}|dkrdS |dkr"dS |dkr.dS |S )Né   ÚnÚ
Útú	Úrú)Úgroup)ÚmatchÚm© r   úN/var/www/sistema_ama/venv/lib/python3.9/site-packages/babel/messages/pofile.pyÚreplace_escapes'   s    
z!unescape.<locals>.replace_escapesz\\([\\trn"])r   éÿÿÿÿ)ÚreÚcompileÚsub)r   r   r   r   r   Úunescape   s    

r"   c                 C  sF   d| v r:|   ¡ }|  d¡r&|dd… }tt|ƒ}d |¡S t| ƒS dS )aì  Reverse the normalization done by the `normalize` function.

    >>> print(denormalize(r'''""
    ... "Say:\n"
    ... "  \"hello, world!\"\n"'''))
    Say:
      "hello, world!"
    <BLANKLINE>

    >>> print(denormalize(r'''""
    ... "Say:\n"
    ... "  \"Lorem ipsum dolor sit "
    ... "amet, consectetur adipisicing"
    ... " elit, \"\n"'''))
    Say:
      "Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
    <BLANKLINE>

    :param string: the string to denormalize
    r   ú""r   NÚ )Ú
splitlinesÚ
startswithÚmapr"   Újoin)r   Zescaped_linesÚlinesr   r   r   Údenormalize4   s    


r*   c                      s.   e Zd ZdZddddddœ‡ fdd„Z‡  ZS )	ÚPoFileErrorzDException thrown by PoParser when an invalid po file is encountered.r   r   ÚintÚNone)ÚmessageÚcatalogÚlineÚlinenor   c                   s,   t ƒ  |› d|› �¡ || _|| _|| _d S )Nz on )ÚsuperÚ__init__r/   r0   r1   )Úselfr.   r/   r0   r1   ©Ú	__class__r   r   r3   V   s    zPoFileError.__init__)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r3   Ú__classcell__r   r   r5   r   r+   S   s   r+   c                   @  sÆ   e Zd Zdddœdd„Zdddœdd„Zdd	œd
d„Zdd	œdd„Zdd	œdd„Zdddœdd„Zdddœdd„Z	dddœdd„Z
dddœdd„Zdddœdd„Zdddœdd„Zdddœd d!„Zd"S )#Ú_NormalizedStringr   r-   )Úargsr   c                 G  s   g | _ |D ]}|  |¡ q
d S ©N)Ú_strsÚappend)r4   r=   Úargr   r   r   r3   _   s    z_NormalizedString.__init__)Úsr   c                 C  s   | j  | ¡ ¡ d S r>   )r?   r@   Ústrip)r4   rB   r   r   r   r@   d   s    z_NormalizedString.append©r   c                 C  s   d  tt| jƒ¡S )Nr$   )r(   r'   r"   r?   ©r4   r   r   r   r*   g   s    z_NormalizedString.denormalizeÚboolc                 C  s
   t | jƒS r>   )rF   r?   rE   r   r   r   Ú__bool__j   s    z_NormalizedString.__bool__c                 C  s   t j | j¡S r>   )ÚosÚlinesepr(   r?   rE   r   r   r   Ú__repr__m   s    z_NormalizedString.__repr__Úobjectr,   )Úotherr   c                 C  s   |sdS t t| ƒt|ƒƒS )Nr   )r   r   ©r4   rL   r   r   r   Ú__cmp__p   s    z_NormalizedString.__cmp__c                 C  s   |   |¡dkS ©Nr   ©rN   rM   r   r   r   Ú__gt__v   s    z_NormalizedString.__gt__c                 C  s   |   |¡dk S rO   rP   rM   r   r   r   Ú__lt__y   s    z_NormalizedString.__lt__c                 C  s   |   |¡dkS rO   rP   rM   r   r   r   Ú__ge__|   s    z_NormalizedString.__ge__c                 C  s   |   |¡dkS rO   rP   rM   r   r   r   Ú__le__   s    z_NormalizedString.__le__c                 C  s   |   |¡dkS rO   rP   rM   r   r   r   Ú__eq__‚   s    z_NormalizedString.__eq__c                 C  s   |   |¡dkS rO   rP   rM   r   r   r   Ú__ne__…   s    z_NormalizedString.__ne__N)r7   r8   r9   r3   r@   r*   rG   rJ   rN   rQ   rR   rS   rT   rU   rV   r   r   r   r   r<   ]   s   r<   c                   @  s²   e Zd ZdZg d¢Zd dddddœdd	„Zdd
œdd„Zdd
œdd„Zdd
œdd„Zd!dd
œdd„Z	d"dd
œdd„Z
dd
œdd„Zdd
œdd„Zdddœdd„Zdd
œdd„ZdS )#ÚPoFileParserz–Support class to  read messages from a ``gettext`` PO (portable object) file
    and add them to a `Catalog`

    See `read_po` for simple cases.
    )ÚmsgidÚmsgstrÚmsgctxtÚmsgid_pluralFr   rF   r-   )r/   Úignore_obsoleteÚabort_invalidr   c                 C  s*   || _ || _d| _d| _|| _|  ¡  d S rO   )r/   r\   ÚcounterÚoffsetr]   Ú_reset_message_state)r4   r/   r\   r]   r   r   r   r3   —   s    zPoFileParser.__init__rD   c                 C  sF   g | _ g | _g | _g | _g | _g | _d | _d| _d| _d| _	d| _
d S )NF)ÚmessagesÚtranslationsÚ	locationsÚflagsÚuser_commentsÚauto_commentsÚcontextÚobsoleteÚin_msgidÚ	in_msgstrÚ
in_msgctxtrE   r   r   r   r`   Ÿ   s    z!PoFileParser._reset_message_statec              
   C  s:  | j  ¡  t| jƒdkr.tdd„ | jD ƒƒ}n| jd  ¡ }t|ttfƒr¤dd„ t| j	j
ƒD ƒ}| j D ]2\}}|| j	j
krŒ|  d| jd¡ qf| ¡ ||< qft|ƒ}n| j d d  ¡ }| jrÆ| j ¡ nd	}t||t| jƒt| jƒ| j| j| jd |d
�}| j�r| j�s || j	j|< n
|| j	|< |  jd7  _|  ¡  d	S )z�
        Add a message to the catalog based on the current parser state and
        clear the state ready to process the next message.
        r   c                 s  s   | ]}|  ¡ V  qd S r>   )r*   )Ú.0r   r   r   r   Ú	<genexpr>³   ó    z,PoFileParser._add_message.<locals>.<genexpr>r   c                 S  s   g | ]}d ‘qS )r$   r   )rl   Ú_r   r   r   Ú
<listcomp>·   rn   z-PoFileParser._add_message.<locals>.<listcomp>r$   z5msg has more translations than num_plurals of catalogN)r1   rg   )rb   ÚsortÚlenra   Útupler*   Ú
isinstanceÚlistÚranger/   Únum_pluralsÚ_invalid_pofiler_   rg   r   rc   Úsetrd   rf   re   rh   r\   r^   r`   )r4   rX   r   ÚidxÚtranslationrZ   r.   r   r   r   Ú_add_message¬   s0    

þ
zPoFileParser._add_messagec                 C  s   | j r|  ¡  d S r>   )ra   r|   rE   r   r   r   Ú_finish_current_messageÌ   s    z$PoFileParser._finish_current_messagec                 C  s*   |  d¡r|  ||¡ n|  |||¡ d S )Nú")r&   Ú!_process_string_continuation_lineÚ_process_keyword_line)r4   r1   r0   rh   r   r   r   Ú_process_message_lineÐ   s    
z"PoFileParser._process_message_linec              	   C  sF  | j D ]Z}z4| |¡r<|t|ƒ dv r<|t|ƒd … }W  qtW q ty^   |  ||d¡ Y q0 q|  ||d¡ d S |dv r„|  ¡  || _|dkr˜|| _|dv r¾d| _d| _	| j
 t|ƒ¡ n„|d	k�r(d| _	d| _| d
¡�r|dd …  dd¡\}}| j t|ƒt|ƒg¡ n| j dt|ƒg¡ n|dk�rBd| _t|ƒ| _d S )N)ú ú[z$Keyword must be followed by a stringz0Start of line didn't match any expected keyword.)rX   rZ   rX   )rX   r[   FTrY   rƒ   r   ú]r   rZ   )Ú	_keywordsr&   rr   Ú
IndexErrorrx   r}   rh   r_   rk   ri   ra   r@   r<   rj   Úsplitrb   r,   rg   )r4   r1   r0   rh   ÚkeywordrA   rz   Úmsgr   r   r   r€   Ö   s8    



z"PoFileParser._process_keyword_linec                 C  sV   | j r| jd }n6| jr(| jd d }n | jr6| j}n|  ||d¡ d S | |¡ d S )Nr   r   z<Got line starting with " but not in msgid, msgstr or msgctxt)ri   ra   rj   rb   rk   rg   rx   r@   )r4   r0   r1   rB   r   r   r   r   ÿ   s    z.PoFileParser._process_string_continuation_linec              	   C  s6  |   ¡  |dd …  d¡r¢|dd …  ¡  ¡ D ]p}| d¡}|dkrŽzt||d d … ƒ}W n tyr   Y q.Y n0 | j |d |… |f¡ q.| j |d f¡ q.n�|dd …  d¡râ|dd …  ¡  d¡D ]}| j	 | 
¡ ¡ qÊnP|dd …  d¡�r|dd …  
¡ }|�r2| j |¡ n| j |dd …  
¡ ¡ d S )Nr   ú:é   r   ú,Ú.)r}   r&   Úlstripr‡   Úrfindr,   Ú
ValueErrorrc   r@   rd   rC   rf   re   )r4   r0   ÚlocationÚposr1   ÚflagÚcommentr   r   r   Ú_process_comment  s&    

zPoFileParser._process_commentúIO[AnyStr] | Iterable[AnyStr])Úfileobjr   c                 C  sÚ   t |ƒD ]€\}}| ¡ }t|tƒs0| | jj¡}|s6q| d¡r||dd…  d¡rp| j||dd…  	¡ dd� qˆ|  
|¡ q|  ||¡ q|  ¡  | jsÖ| jsª| jsª| jrÖ| j tdƒ¡ | j d	tdƒg¡ |  ¡  dS )
z˜
        Reads from the file-like object `fileobj` and adds any po file
        units found in it to the `Catalog` supplied to the constructor.
        ú#r   Nú~r‹   T)rh   r#   r   )Ú	enumeraterC   rt   r   Údecoder/   Úcharsetr&   r�   rŽ   r•   r}   r^   rd   re   rf   ra   r@   r<   rb   r|   )r4   r—   r1   r0   r   r   r   Úparse&  s     

zPoFileParser.parsec                 C  sJ   t |tƒsJ ‚| jr$t|| j||ƒ‚td|ƒ td|d › d|›�ƒ d S )NzWARNING:zWARNING: Problem on line r   z: )rt   r   r]   r+   r/   Úprint)r4   r0   r1   r‰   r   r   r   rx   C  s
    
zPoFileParser._invalid_pofileN)FF)F)F)r7   r8   r9   r:   r…   r3   r`   r|   r}   r�   r€   r   r•   r�   rx   r   r   r   r   rW   ‰   s    )rW   Fr–   zstr | Locale | Nonez
str | NonerF   r   )r—   ÚlocaleÚdomainr\   rœ   r]   r   c                 C  s*   t |||d�}t|||d�}| | ¡ |S )aµ  Read messages from a ``gettext`` PO (portable object) file from the given
    file-like object (or an iterable of lines) and return a `Catalog`.

    >>> from datetime import datetime
    >>> from io import StringIO
    >>> buf = StringIO('''
    ... #: main.py:1
    ... #, fuzzy, python-format
    ... msgid "foo %(name)s"
    ... msgstr "quux %(name)s"
    ...
    ... # A user comment
    ... #. An auto comment
    ... #: main.py:3
    ... msgid "bar"
    ... msgid_plural "baz"
    ... msgstr[0] "bar"
    ... msgstr[1] "baaz"
    ... ''')
    >>> catalog = read_po(buf)
    >>> catalog.revision_date = datetime(2007, 4, 1)

    >>> for message in catalog:
    ...     if message.id:
    ...         print((message.id, message.string))
    ...         print(' ', (message.locations, sorted(list(message.flags))))
    ...         print(' ', (message.user_comments, message.auto_comments))
    (u'foo %(name)s', u'quux %(name)s')
      ([(u'main.py', 1)], [u'fuzzy', u'python-format'])
      ([], [])
    ((u'bar', u'baz'), (u'bar', u'baaz'))
      ([(u'main.py', 3)], [])
      ([u'A user comment'], [u'An auto comment'])

    .. versionadded:: 1.0
       Added support for explicit charset argument.

    :param fileobj: the file-like object (or iterable of lines) to read the PO file from
    :param locale: the locale identifier or `Locale` object, or `None`
                   if the catalog is not bound to a locale (which basically
                   means it's a template)
    :param domain: the message domain
    :param ignore_obsolete: whether to ignore obsolete messages in the input
    :param charset: the character set of the catalog.
    :param abort_invalid: abort read if po file is invalid
    )rŸ   r    rœ   )r]   )r   rW   r�   )r—   rŸ   r    r\   rœ   r]   r/   Úparserr   r   r   Úread_poK  s    6
r¢   zL(\s+|[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))c                 C  s0   d|   dd¡  dd¡  dd¡  dd	¡  d
d¡ S )zõEscape the given string so that it can be included in double-quoted
    strings in ``PO`` files.

    >>> escape('''Say:
    ...   "hello, world!"
    ... ''')
    '"Say:\\n  \\"hello, world!\\"\\n"'

    :param string: the string to escape
    z"%s"ú\z\\r   z\tr   z\rr   z\nr~   z\")Úreplace)r   r   r   r   ÚescapeŽ  s    ÿþýür¥   r$   éL   r,   )r   ÚprefixÚwidthr   c           
        s0  |rÐ|dkrÐt ˆ ƒ}g }|  d¡D ]ª}t t|ƒƒ| |krÂt |¡}| ¡  |rÌg }d}|r®t t|d ƒƒd | }	||	 |k r˜| | ¡ ¡ ||	7 }qX|s®| | ¡ ¡ q®qX| d |¡¡ qLq"| |¡ q"n
|  d¡}t |ƒdkrît| ƒS |�r|d �s|d= |d  d7  < dd ‡ fd	d
„|D ƒ¡ S )a©  Convert a string into a format that is appropriate for .po files.

    >>> print(normalize('''Say:
    ...   "hello, world!"
    ... ''', width=None))
    ""
    "Say:\n"
    "  \"hello, world!\"\n"

    >>> print(normalize('''Say:
    ...   "Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
    ... ''', width=32))
    ""
    "Say:\n"
    "  \"Lorem ipsum dolor sit "
    "amet, consectetur adipisicing"
    " elit, \"\n"

    :param string: the string to normalize
    :param prefix: a string that should be prepended to every line
    :param width: the maximum line width; use `None`, 0, or a negative number
                  to completely disable line wrapping
    r   Tr‹   r   r$   r   r   z""
c                   s   g | ]}ˆ t |ƒ ‘qS r   )r¥   )rl   r0   ©r§   r   r   rp   Ú  rn   znormalize.<locals>.<listcomp>)	rr   r%   r¥   ÚWORD_SEPr‡   Úreverser@   Úpopr(   )
r   r§   r¨   Ú	prefixlenr)   r0   ÚchunksÚbufÚsizeÚlengthr   r©   r   Ú	normalize   s6    


r²   TzSupportsWrite[bytes]r-   )r—   r/   r¨   Úno_locationÚomit_headerÚsort_outputÚsort_by_filer\   Úinclude_previousÚinclude_linenor   c
              
   C  sZ   d}
|rd}
n|rd}
t |||	||||
|d�D ]&}t|tƒrJ| |jd¡}|  |¡ q.dS )aÍ  Write a ``gettext`` PO (portable object) template file for a given
    message catalog to the provided file-like object.

    >>> catalog = Catalog()
    >>> catalog.add(u'foo %(name)s', locations=[('main.py', 1)],
    ...             flags=('fuzzy',))
    <Message...>
    >>> catalog.add((u'bar', u'baz'), locations=[('main.py', 3)])
    <Message...>
    >>> from io import BytesIO
    >>> buf = BytesIO()
    >>> write_po(buf, catalog, omit_header=True)
    >>> print(buf.getvalue().decode("utf8"))
    #: main.py:1
    #, fuzzy, python-format
    msgid "foo %(name)s"
    msgstr ""
    <BLANKLINE>
    #: main.py:3
    msgid "bar"
    msgid_plural "baz"
    msgstr[0] ""
    msgstr[1] ""
    <BLANKLINE>
    <BLANKLINE>

    :param fileobj: the file-like object to write to
    :param catalog: the `Catalog` instance
    :param width: the maximum line width for the generated output; use `None`,
                  0, or a negative number to completely disable line wrapping
    :param no_location: do not emit a location comment for every message
    :param omit_header: do not include the ``msgid ""`` entry at the top of the
                        output
    :param sort_output: whether to sort the messages in the output by msgid
    :param sort_by_file: whether to sort the messages in the output by their
                         locations
    :param ignore_obsolete: whether to ignore obsolete messages and not include
                            them in the output; by default they are included as
                            comments
    :param include_previous: include the old msgid as a comment when
                             updating the catalog
    :param include_lineno: include line number in the location comment
    Nr.   r‘   ©r\   r¸   r·   r³   r´   Úsort_byr¨   Úbackslashreplace)Úgenerate_port   r   Úencoderœ   Úwrite)r—   r/   r¨   r³   r´   rµ   r¶   r\   r·   r¸   rº   r0   r   r   r   Úwrite_poÝ  s$    8ø


r¿   r¹   z%Literal['message', 'location'] | NonezIterable[str])	r/   r\   r¸   r·   r³   r´   rº   r¨   r   c             	   #  sz  ˆrˆdkrˆnd‰d‡fdd„	}d‡ ‡fdd„	}	t ˆ |d�D �]à}
|
jsœ|rPq>ˆ j}ˆr�ˆdkr�g }| ¡ D ]}|t|ˆd	d
�7 }qnd |¡}|› d�V  |
jD ]}||ƒE dH  q¢|
jD ]}||dd�E dH  q¼|�svg }zt|
j	dd„ d�}W n t
�y   |
j	}Y n0 |D ]H\}}| tjd¡}|�rF|�rF|› d|d›�}||v�r| |¡ �q|d |¡dd�E dH  |
j�rždd dgt|
jƒ¢¡› d�V  |
j�r|�r|dt|
jd ˆd�› �dd�E dH  t|
jƒdk�rt|
jd ˆd�}|d|› �dd�E dH  |	|
ƒE dH  dV  q>|�svt ˆ j ¡ |d�D ]:}
|
jD ]}||ƒE dH  �qD|	|
dd�E dH  dV  �q:dS ) z„Yield text strings representing a ``gettext`` PO (portable object) file.

    See `write_po()` for a more detailed description.
    r   r¦   r$   c                 3  s,   t | ˆ ƒD ]}d|› d| ¡ › d�V  q
d S )Nr˜   r‚   r   )r	   rC   )r”   r§   r0   )Úcomment_widthr   r   Ú_format_comment=  s    z$generate_po.<locals>._format_commentc              
   3  s>  t | jttfƒrÔ| jr4|› dt| j|ˆd�› d�V  |› dt| jd |ˆd�› d�V  |› dt| jd |ˆd�› d�V  tˆ jƒD ]N}z| j| }W n t	yª   d}Y n0 |› d	|d
›dt||ˆd�› d�V  q‚nf| jrø|› dt| j|ˆd�› d�V  |› dt| j|ˆd�› d�V  |› dt| j�p(d|ˆd�› d�V  d S )Nzmsgctxt )r§   r¨   r   úmsgid r   úmsgid_plural r   r$   zmsgstr[Údz] zmsgstr )
rt   Úidru   rs   rg   r²   rv   rw   r   r†   )r.   r§   rz   r   )r/   r¨   r   r   Ú_format_messageA  s    ""
(z$generate_po.<locals>._format_message)rº   z# )r¨   Úsubsequent_indentr   Nr�   r©   c                 S  s"   | d t | d tƒr| d pdfS )Nr   r   r   )rt   r,   )Úxr   r   r   Ú<lambda>o  rn   zgenerate_po.<locals>.<lambda>©Úkeyú/rŠ   rÄ   r‚   r˜   z, rÂ   )r¨   ú|r   rÃ   z#~ )r$   )r$   )Ú_sort_messagesrÅ   Zheader_commentr%   r	   r(   re   rf   Úsortedrc   Ú	TypeErrorr¤   rH   Úsepr@   rd   Zprevious_idr²   rr   rh   Úvalues)r/   r\   r¸   r·   r³   r´   rº   r¨   rÁ   rÆ   r.   Zcomment_headerr)   r0   r”   Zlocsrc   Úfilenamer1   r‘   Znorm_previous_idr   )r/   rÀ   r¨   r   r¼   *  sp    ÿ



ÿ

 þþ

r¼   zIterable[Message]zlist[Message])ra   rº   r   c                 C  s6   t | ƒ} |dkr|  ¡  n|dkr2| jdd„ d� | S )zø
    Sort the given message iterable by the given criteria.

    Always returns a list.

    :param messages: An iterable of Messages.
    :param sort_by: Sort by which criteria? Options are `message` and `location`.
    :return: list[Message]
    r.   r‘   c                 S  s   | j S r>   )rc   )r   r   r   r   rÉ   ¢  rn   z _sort_messages.<locals>.<lambda>rÊ   )ru   rq   )ra   rº   r   r   r   rÎ   ”  s    

rÎ   )NNFNF)r$   r¦   )r¦   FFFFFFT)%r:   Ú
__future__r   rH   r   Úcollections.abcr   Útypingr   Z
babel.corer   Zbabel.messages.catalogr   r   Z
babel.utilr   r	   r
   r   Z	_typeshedr   Ztyping_extensionsr   r"   r*   Ú	Exceptionr+   r<   rW   r¢   r    rª   r¥   r²   r¿   r¼   rÎ   r   r   r   r   Ú<module>   sZ   

, E     ú<
@        ö$P÷"j