a
    :XhZ                     @  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rd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 )zReverse `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   Z/var/www/viveiro_mudafortebrasil/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 )#PoFileParserzSupport 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rd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 rd| _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rz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	|
  qnP|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 )zEscape 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rt  }g }| dD ]}t t|| |krt|}|  |rg }d}|rt t|d d | }	||	 |k r||  ||	7 }qX|s||  qqX|d| qLq"|| q"n
| d}t |dkrt| 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rg }| 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rd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 ) zYield 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  qnf| 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