a
    ÇZEgÝŽ  ã                   @  sj  U 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m	Z	 ddl
m
Z
 ddlmZ ddlm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 ddlmZ ddlmZmZm Z m!Z! eröddl"m#Z# e$e%e$df B e&e$ B Z'de(d< g d¢Z)d)dd„Z*e +dej,¡Z-dddœdd„Z.G dd „ d ƒZ/G d!d"„ d"e0ƒZ1d#Z2dd$dœd%d&„Z3G d'd(„ d(ƒZ4dS )*zÅ
    babel.messages.catalog
    ~~~~~~~~~~~~~~~~~~~~~~

    Data structures for message catalogs.

    :copyright: (c) 2013-2024 by the Babel Team.
    :license: BSD, see LICENSE for more details.
é    )ÚannotationsN)ÚOrderedDict)ÚIterableÚIterator)Úcopy)ÚSequenceMatcher)Úmessage_from_string)Únlargest)ÚTYPE_CHECKING)Ú__version__)ÚLocaleÚUnknownLocaleError)Úformat_datetime)Ú
get_plural)ÚLOCALTZÚFixedOffsetTimezoneÚ_cmpÚdistinct)Ú	TypeAlias.r   Ú
_MessageID)ÚMessageÚCatalogÚTranslationErroré   ç333333ã?c                 C  s´   |dkst d|›�ƒ‚d|  kr*dks:n t d|›�ƒ‚g }tdd�}| | ¡ |D ]D}| |¡ | ¡ |krV| ¡ |krV| ¡ |krV| | ¡ |f¡ qVt||ƒ}dd	„ |D ƒS )
z¿A modified version of ``difflib.get_close_matches``.

    It just passes ``autojunk=False`` to the ``SequenceMatcher``, to work
    around https://github.com/python/cpython/issues/90825.
    r   zn must be > 0: g        g      ð?zcutoff must be in [0.0, 1.0]: F)Zautojunkc                 S  s   g | ]\}}|‘qS © r   )Ú.0ZscoreÚxr   r   úO/var/www/sistema_ama/venv/lib/python3.9/site-packages/babel/messages/catalog.pyÚ
<listcomp>:   ó    z%get_close_matches.<locals>.<listcomp>)	Ú
ValueErrorr   Zset_seq2Zset_seq1Zreal_quick_ratioZquick_ratioZratioÚappendr	   )ÚwordÚpossibilitiesÚnÚcutoffÚresultÚsr   r   r   r   Úget_close_matches#   s"    



ÿ
þ
r)   z¨
    \%
        (?:\(([\w]*)\))?
        (
            [-#0\ +]?(?:\*|[\d]+)?
            (?:\.(?:\*|[\d]+))?
            [hlL]?
        )
        ([diouxXeEfFgGcrs%])
Ústrzdatetime.datetime)ÚvalueÚreturnc                 C  s°   t  d| ¡}tj | d¡d¡}| d¡}|d ur¬|d |dd …  }}|d d… |dd …  }}t|› d�ƒ}t|ƒ}	t|ƒ}
|	d	 }||
7 }||9 }t|ƒ}|j|d
�}|S )Nz+^(?P<datetime>.*?)(?P<tzoffset>[+-]\d{4})?$Údatetimez%Y-%m-%d %H:%MÚtzoffsetr   é   é   Ú1é<   ©Útzinfo)ÚreÚmatchr-   ÚstrptimeÚgroupÚintr   Úreplace)r+   r6   Údtr.   Zplus_minus_sÚrestZhours_offset_sZmins_offset_sZ
plus_minusZhours_offsetZmins_offsetZnet_mins_offsetr   r   r   Ú_parse_datetime_headerI   s    
r=   c                   @  s  e Zd ZdZd4dddddddd	d
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 ddœd%d&„Zd dœd'd(„Zd5d)d*d+œd,d-„Zeddœd.d/„ƒZeddœd0d1„ƒZeddœd2d3„ƒZdS )6r   z0Representation of a single message in a catalog.Ú r   Nr   ú_MessageID | NoneúIterable[tuple[str, int]]úIterable[str]ú
int | Noneú
str | NoneÚNone©
ÚidÚstringÚ	locationsÚflagsÚauto_commentsÚuser_commentsÚprevious_idÚlinenoÚcontextr,   c
           
      C  s    || _ |s| jrd}|| _tt|ƒƒ| _t|ƒ| _|rJ| jrJ| j 	d¡ n| j 
d¡ tt|ƒƒ| _tt|ƒƒ| _t|tƒr†|g| _n
t|ƒ| _|| _|	| _dS )a_  Create the message object.

        :param id: the message ID, or a ``(singular, plural)`` tuple for
                   pluralizable messages
        :param string: the translated message string, or a
                       ``(singular, plural)`` tuple for pluralizable messages
        :param locations: a sequence of ``(filename, lineno)`` tuples
        :param flags: a set or sequence of flags
        :param auto_comments: a sequence of automatic comments for the message
        :param user_comments: a sequence of user comments for the message
        :param previous_id: the previous message ID, or a ``(singular, plural)``
                            tuple for pluralizable messages
        :param lineno: the line number on which the msgid line was found in the
                       PO file, if any
        :param context: the message context
        )r>   r>   zpython-formatN)rF   ÚpluralizablerG   Úlistr   rH   ÚsetrI   Úpython_formatÚaddÚdiscardrJ   rK   Ú
isinstancer*   rL   rM   rN   )
ÚselfrF   rG   rH   rI   rJ   rK   rL   rM   rN   r   r   r   Ú__init__j   s     





zMessage.__init__r*   ©r,   c                 C  s&   dt | ƒj› d| j›dt| jƒ›d�S )Nú<ú z	 (flags: z)>)ÚtypeÚ__name__rF   rP   rI   ©rV   r   r   r   Ú__repr__™   s    zMessage.__repr__Úobjectr9   ©Úotherr,   c                 C  s   dd„ }t || ƒ||ƒƒS )z0Compare Messages, taking into account plural idsc                 S  s4   t | tƒr$| jr$| jd | jp dfS | j| jp0dfS )Nr   r>   )rU   r   rO   rF   rN   )Úobjr   r   r   Úvalues_to_comparež   s    z*Message.__cmp__.<locals>.values_to_compare)r   )rV   ra   rc   r   r   r   Ú__cmp__œ   s    zMessage.__cmp__Úboolc                 C  s   |   |¡dkS ©Nr   ©rd   ©rV   ra   r   r   r   Ú__gt__¤   s    zMessage.__gt__c                 C  s   |   |¡dk S rf   rg   rh   r   r   r   Ú__lt__§   s    zMessage.__lt__c                 C  s   |   |¡dkS rf   rg   rh   r   r   r   Ú__ge__ª   s    zMessage.__ge__c                 C  s   |   |¡dkS rf   rg   rh   r   r   r   Ú__le__­   s    zMessage.__le__c                 C  s   |   |¡dkS rf   rg   rh   r   r   r   Ú__eq__°   s    zMessage.__eq__c                 C  s   |   |¡dkS rf   rg   rh   r   r   r   Ú__ne__³   s    zMessage.__ne__c                 C  s   t |tƒsJ ‚| j|jkS )z[Checks whether messages are identical, taking into account all
        properties.
        )rU   r   Ú__dict__rh   r   r   r   Úis_identical¶   s    zMessage.is_identicalc                 C  s2   t tt| j| j| j| j| j| j| j	| j
| jf	ƒŽ S ©N)r   Úmapr   rF   rG   rH   rI   rJ   rK   rL   rM   rN   r]   r   r   r   Úclone½   s
    ýzMessage.clonezCatalog | Nonezlist[TranslationError])Úcatalogr,   c                 C  s\   ddl m} g }|D ]B}z||| ƒ W q tyT } z| |¡ W Y d}~qd}~0 0 q|S )a•  Run various validation checks on the message.  Some validations
        are only performed if the catalog is provided.  This method returns
        a sequence of `TranslationError` objects.

        :rtype: ``iterator``
        :param catalog: A catalog instance that is passed to the checkers
        :see: `Catalog.check` for a way to perform checks for all messages
              in a catalog.
        r   )ÚcheckersN)Zbabel.messages.checkersru   r   r"   )rV   rt   ru   ÚerrorsÚcheckerÚer   r   r   ÚcheckÃ   s    
"zMessage.checkc                 C  s
   d| j v S )a   Whether the translation is fuzzy.

        >>> Message('foo').fuzzy
        False
        >>> msg = Message('foo', 'foo', flags=['fuzzy'])
        >>> msg.fuzzy
        True
        >>> msg
        <Message 'foo' (flags: ['fuzzy'])>

        :type:  `bool`Úfuzzy©rI   r]   r   r   r   rz   Ö   s    zMessage.fuzzyc                 C  s   t | jttfƒS )z¯Whether the message is plurizable.

        >>> Message('foo').pluralizable
        False
        >>> Message(('foo', 'bar')).pluralizable
        True

        :type:  `bool`)rU   rF   rP   Útupler]   r   r   r   rO   å   s    
zMessage.pluralizablec                 C  s,   | j }t|ttfƒs|g}tdd„ |D ƒƒS )zâWhether the message contains Python-style parameters.

        >>> Message('foo %(name)s bar').python_format
        True
        >>> Message(('foo %(name)s', 'foo %(name)s')).python_format
        True

        :type:  `bool`c                 s  s   | ]}t  |¡V  qd S rq   )ÚPYTHON_FORMATÚsearch)r   rF   r   r   r   Ú	<genexpr>þ   r    z(Message.python_format.<locals>.<genexpr>)rF   rU   rP   r|   Úany)rV   Úidsr   r   r   rR   ñ   s    
zMessage.python_format)r>   r   r   r   r   r   NN)N)r\   Ú
__module__Ú__qualname__Ú__doc__rW   r^   rd   ri   rj   rk   rl   rm   rn   rp   rs   ry   Úpropertyrz   rO   rR   r   r   r   r   r   g   s6           ö"/r   c                   @  s   e Zd ZdZdS )r   z_Exception thrown by translation checkers when invalid message
    translations are encountered.N)r\   r‚   rƒ   r„   r   r   r   r   r     s   r   z¸# Translations template for PROJECT.
# Copyright (C) YEAR ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#zdict[str, str]c                 C  s&   ddl m} |ƒ }| |d< t| ¡ ƒS )Nr   )r   úcontent-type)Úemail.messager   ÚdictÚ
get_params)r+   r   Úmr   r   r   Úparse_separated_header  s    r‹   c                   @  sH  e Zd ZdZddeddddddddddfdddddddddddddd	d
œdd„Zdd	dœdd„Zddœdd„Zddœdd„Ze	eeƒZ
e	eƒZddœdd„Zdd	dœdd„Ze	eedd�Zddœd d!„Zded$dddd%œd&d'„Zd(d	d)œd*d+„Ze	eed,d�Ze	d-dœd.d/„ƒZe	ddœd0d1„ƒZe	ddœd2d3„ƒZd4dd5œd6d7„Zd-dœd8d9„Zd:dœd;d<„Zddœd=d>„Zd4d	d5œd?d@„Zd4dAd5œdBdC„Zd4dAd	dDœdEdF„Zdfd4dHdIdJdJdJd4dKddAdLœ
dMdN„ZdOdœdPdQ„Zdgd4ddRdSœdTdU„Zdhd4dd	dSœdVdW„Z did ddddd	dYœdZd[„Z!d\dd]œd^d_„Z"djd4dd\dSœd`da„Z#d ddbœdcdd„Z$dS )kr   z$Representation of a message catalog.NTzstr | Locale | NonerC   zdatetime.datetime | str | Nonez6datetime.datetime | datetime.time | float | str | Nonere   rD   )ÚlocaleÚdomainÚheader_commentÚprojectÚversionÚcopyright_holderÚmsgid_bugs_addressÚcreation_dateÚrevision_dateÚlast_translatorÚlanguage_teamÚcharsetrz   r,   c                 C  sê   || _ || _|| _tƒ | _|p d| _|p*d| _|p4d| _|p>d| _|
pHd| _	|pRd| _
|p\d| _|du rvtj t¡}nt|tjƒr”|js”|jtd	�}|| _|	du r¨d
}	nt|	tjƒrÆ|	jsÆ|	jtd	�}	|	| _|| _tƒ | _d| _d| _dS )aD  Initialize the catalog object.

        :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 header_comment: the header comment as string, or `None` for the
                               default header
        :param project: the project's name
        :param version: the project's version
        :param copyright_holder: the copyright holder of the catalog
        :param msgid_bugs_address: the email address or URL to submit bug
                                   reports to
        :param creation_date: the date the catalog was created
        :param revision_date: the date the catalog was revised
        :param last_translator: the name and email of the last translator
        :param language_team: the name and email of the language team
        :param charset: the encoding to use in the output (defaults to utf-8)
        :param fuzzy: the fuzzy bit on the catalog header
        ÚPROJECTÚVERSIONÚORGANIZATIONzEMAIL@ADDRESSzFULL NAME <EMAIL@ADDRESS>zLANGUAGE <LL@li.org>úutf-8Nr3   zYEAR-MO-DA HO:MI+ZONE)r�   rŒ   Ú_header_commentr   Ú	_messagesr�   r�   r‘   r’   r•   r–   r—   r-   Únowr   rU   r4   r:   r“   r”   rz   ÚobsoleteÚ_num_pluralsÚ_plural_expr)rV   rŒ   r�   rŽ   r�   r�   r‘   r’   r“   r”   r•   r–   r—   rz   r   r   r   rW     s2    $






zCatalog.__init__zLocale | str | None)rŒ   r,   c                 C  sŠ   |d u rd | _ d | _d S t|tƒr6t|ƒ| _ || _d S t|tƒrxt|ƒ| _ zt |¡| _W n tyr   d | _Y n0 d S td|›�ƒ‚d S )NzD`locale` must be a Locale, a locale identifier string, or None; got )Ú_locale_identifierÚ_localerU   r   r*   Úparser   Ú	TypeError©rV   rŒ   r   r   r   Ú_set_locale_  s     



zCatalog._set_localezLocale | NonerX   c                 C  s   | j S rq   )r£   r]   r   r   r   Ú_get_localet  s    zCatalog._get_localec                 C  s   | j S rq   )r¢   r]   r   r   r   Ú_get_locale_identifierw  s    zCatalog._get_locale_identifierr*   c                 C  sˆ   | j }tj t¡ d¡}t| jdƒr0| j d¡}| d| j¡ d| j	¡ d|¡ d| j
¡}| jrh| jjn| j}|r„| d|› d�¡}|S )	Nz%YÚstrftimer˜   r™   ÚYEARrš   zTranslations templatez translations)rœ   r-   rž   r   rª   Úhasattrr”   r:   r�   r�   r‘   rŒ   Zenglish_nameÚlocale_identifier)rV   ÚcommentÚyearZlocale_namer   r   r   Ú_get_header_comment}  s    ÿþýzCatalog._get_header_comment)rG   r,   c                 C  s
   || _ d S rq   )rœ   )rV   rG   r   r   r   Ú_set_header_comment‹  s    zCatalog._set_header_commenta…      The header comment for the catalog.

    >>> catalog = Catalog(project='Foobar', version='1.0',
    ...                   copyright_holder='Foo Company')
    >>> print(catalog.header_comment) #doctest: +ELLIPSIS
    # Translations template for Foobar.
    # Copyright (C) ... Foo Company
    # This file is distributed under the same license as the Foobar project.
    # FIRST AUTHOR <EMAIL@ADDRESS>, ....
    #

    The header can also be set from a string. Any known upper-case variables
    will be replaced when the header is retrieved again:

    >>> catalog = Catalog(project='Foobar', version='1.0',
    ...                   copyright_holder='Foo Company')
    >>> catalog.header_comment = '''\
    ... # The POT for my really cool PROJECT project.
    ... # Copyright (C) 1990-2003 ORGANIZATION
    ... # This file is distributed under the same license as the PROJECT
    ... # project.
    ... #'''
    >>> print(catalog.header_comment)
    # The POT for my really cool Foobar project.
    # Copyright (C) 1990-2003 Foo Company
    # This file is distributed under the same license as the Foobar
    # project.
    #

    :type: `unicode`
    )Údoczlist[tuple[str, str]]c                 C  sX  g }|  d| j› d| j› �f¡ |  d| jf¡ |  dt| jddd�f¡ t| jtjtj	t
tfƒr~|  dt| jddd�f¡ n|  d| jf¡ |  d	| jf¡ | jr¸|  d
t| jƒf¡ | jrèd| jv rè|  d| j dt| jƒ¡f¡ n|  d| jf¡ | jd u�r|  d| jf¡ |  d¡ |  dd| j› �f¡ |  d¡ |  ddt› d�f¡ |S )NzProject-Id-VersionrZ   zReport-Msgid-Bugs-TozPOT-Creation-Datezyyyy-MM-dd HH:mmZÚen)rŒ   zPO-Revision-DatezLast-TranslatorZLanguageÚLANGUAGEzLanguage-TeamzPlural-Forms)zMIME-Versionz1.0zContent-Typeztext/plain; charset=)zContent-Transfer-EncodingÚ8bitzGenerated-ByzBabel Ú
)r"   r�   r�   r’   r   r“   rU   r”   r-   Útimer9   Úfloatr•   r­   r*   r–   r:   rŒ   Úplural_formsr—   r™   )rV   Úheadersr   r   r   Ú_get_mime_headers¯  s@    ÿÿÿÿÿÿ

zCatalog._get_mime_headersr›   Ústrictzstr | bytes)r(   Úencodingrv   r,   c                 C  s,   t |tƒr|S t |tƒr$| ||¡S t|ƒS rq   )rU   r*   ÚbytesÚdecode)rV   r(   r½   rv   r   r   r   Ú_force_textÍ  s
    

zCatalog._force_textzIterable[tuple[str, str]])rº   r,   c                 C  sP  |D �]D\}}| j | ¡ | jd�}| j || jd�}|dkrd| d¡}d |d d… ¡| _|d | _q|dkrt|| _q|dkr„|| _q|dkr¨| 	dd	¡}|  
|p¢d ¡ q|d
kr¸|| _q|dkràt|ƒ}d|v rÞ|d  ¡ | _q|dk�rtd|› �ƒ}t| dd¡ƒ| _| dd¡| _q|dk�r0t|ƒ| _q|dkrd|vrt|ƒ| _qd S )N)r½   zproject-id-versionrZ   éÿÿÿÿzreport-msgid-bugs-tozlast-translatorÚlanguageú-Ú_zlanguage-teamr†   r—   zplural-formsz ;Znpluralsr0   Úpluralú(n != 1)zpot-creation-datezpo-revision-dater«   )rÀ   Úlowerr—   ÚsplitÚjoinr�   r�   r’   r•   r:   r§   r–   r‹   r9   Úgetr    r¡   r=   r“   r”   )rV   rº   Únamer+   ÚpartsÚparamsr   r   r   Ú_set_mime_headersÔ  s:    


zCatalog._set_mime_headersaê      The MIME headers of the catalog, used for the special ``msgid ""`` entry.

    The behavior of this property changes slightly depending on whether a locale
    is set or not, the latter indicating that the catalog is actually a template
    for actual translations.

    Here's an example of the output for such a catalog template:

    >>> from babel.dates import UTC
    >>> from datetime import datetime
    >>> created = datetime(1990, 4, 1, 15, 30, tzinfo=UTC)
    >>> catalog = Catalog(project='Foobar', version='1.0',
    ...                   creation_date=created)
    >>> for name, value in catalog.mime_headers:
    ...     print('%s: %s' % (name, value))
    Project-Id-Version: Foobar 1.0
    Report-Msgid-Bugs-To: EMAIL@ADDRESS
    POT-Creation-Date: 1990-04-01 15:30+0000
    PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
    Last-Translator: FULL NAME <EMAIL@ADDRESS>
    Language-Team: LANGUAGE <LL@li.org>
    MIME-Version: 1.0
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: 8bit
    Generated-By: Babel ...

    And here's an example of the output when the locale is set:

    >>> revised = datetime(1990, 8, 3, 12, 0, tzinfo=UTC)
    >>> catalog = Catalog(locale='de_DE', project='Foobar', version='1.0',
    ...                   creation_date=created, revision_date=revised,
    ...                   last_translator='John Doe <jd@example.com>',
    ...                   language_team='de_DE <de@example.com>')
    >>> for name, value in catalog.mime_headers:
    ...     print('%s: %s' % (name, value))
    Project-Id-Version: Foobar 1.0
    Report-Msgid-Bugs-To: EMAIL@ADDRESS
    POT-Creation-Date: 1990-04-01 15:30+0000
    PO-Revision-Date: 1990-08-03 12:00+0000
    Last-Translator: John Doe <jd@example.com>
    Language: de_DE
    Language-Team: de_DE <de@example.com>
    Plural-Forms: nplurals=2; plural=(n != 1);
    MIME-Version: 1.0
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: 8bit
    Generated-By: Babel ...

    :type: `list`
    r9   c                 C  s.   | j du r(d}| jr"t| jƒd }|| _ | j S )z¹The number of plurals used by the catalog or locale.

        >>> Catalog(locale='en').num_plurals
        2
        >>> Catalog(locale='ga').num_plurals
        5

        :type: `int`Nr0   r   )r    rŒ   r   )rV   Únumr   r   r   Únum_plurals,  s    

zCatalog.num_pluralsc                 C  s.   | j du r(d}| jr"t| jƒd }|| _ | j S )aW  The plural expression used by the catalog or locale.

        >>> Catalog(locale='en').plural_expr
        '(n != 1)'
        >>> Catalog(locale='ga').plural_expr
        '(n==1 ? 0 : n==2 ? 1 : n>=3 && n<=6 ? 2 : n>=7 && n<=10 ? 3 : 4)'
        >>> Catalog(locale='ding').plural_expr  # unknown locale
        '(n != 1)'

        :type: `str`NrÆ   r/   )r¡   rŒ   r   )rV   Úexprr   r   r   Úplural_expr=  s    
zCatalog.plural_exprc                 C  s   d| j › d| j› d�S )zöReturn the plural forms declaration for the locale.

        >>> Catalog(locale='en').plural_forms
        'nplurals=2; plural=(n != 1);'
        >>> Catalog(locale='pt_BR').plural_forms
        'nplurals=2; plural=(n > 1);'

        :type: `str`z	nplurals=z	; plural=ú;)rÐ   rÒ   r]   r   r   r   r¹   P  s    
zCatalog.plural_formsr   )rF   r,   c                 C  s   |   |¡| jv S )z?Return whether the catalog has a message with the specified ID.©Ú_key_forr�   ©rV   rF   r   r   r   Ú__contains__\  s    zCatalog.__contains__c                 C  s
   t | jƒS )zeThe number of messages in the catalog.

        This does not include the special ``msgid ""`` entry.)Úlenr�   r]   r   r   r   Ú__len__`  s    zCatalog.__len__zIterator[Message]c                 c  sp   g }| j D ]\}}| |› d|› �¡ q
tƒ }| jr>|dhO }tdd |¡|d�V  | jD ]}| j| V  qZdS )z¡Iterates through all the entries in the catalog, in the order they
        were added, yielding a `Message` object for every entry.

        :rtype: ``iterator``z: rz   r>   r¶   r{   N)Úmime_headersr"   rQ   rz   r   rÉ   r�   )rV   ÚbufrË   r+   rI   Úkeyr   r   r   Ú__iter__f  s    

zCatalog.__iter__c                 C  s4   d}| j rd| j › �}dt| ƒj› d| j›|› d�S )Nr>   rZ   rY   ú>)rŒ   r[   r\   r�   r¦   r   r   r   r^   u  s    zCatalog.__repr__c                 C  s   |   |¡ dS )z)Delete the message with the specified ID.N)ÚdeleterÖ   r   r   r   Ú__delitem__{  s    zCatalog.__delitem__r   c                 C  s
   |   |¡S )zUReturn the message with the specified ID.

        :param id: the message ID
        )rÊ   rÖ   r   r   r   Ú__getitem__  s    zCatalog.__getitem__)rF   Úmessager,   c                 C  s"  t |tƒsJ dƒ‚|  ||j¡}| j |¡}|r¤|jrL|jsL|j|_|j|_t	t
|j|j ƒƒ|_t	t
|j|j ƒƒ|_t	t
|j|j ƒƒ|_| j|jO  _|}nz|dkrÞt|jƒ ¡ | _d dd„ |jD ƒ¡| _|j| _n@t |t	tfƒ�rt |jt	tfƒ�sJ dt|jƒ› �ƒ‚|| j|< dS )aé  Add or update the message with the specified ID.

        >>> catalog = Catalog()
        >>> catalog[u'foo'] = Message(u'foo')
        >>> catalog[u'foo']
        <Message u'foo' (flags: [])>

        If a message with that ID is already in the catalog, it is updated
        to include the locations and flags of the new message.

        >>> catalog = Catalog()
        >>> catalog[u'foo'] = Message(u'foo', locations=[('main.py', 1)])
        >>> catalog[u'foo'].locations
        [('main.py', 1)]
        >>> catalog[u'foo'] = Message(u'foo', locations=[('utils.py', 5)])
        >>> catalog[u'foo'].locations
        [('main.py', 1), ('utils.py', 5)]

        :param id: the message ID
        :param message: the `Message` object
        zexpected a Message objectr>   r¶   c                 S  s   g | ]}d |› �  ¡ ‘qS )z# )Úrstrip)r   Úcr   r   r   r   ¯  r    z'Catalog.__setitem__.<locals>.<listcomp>zExpected sequence but got N)rU   r   rÕ   rN   r�   rÊ   rO   rF   rG   rP   r   rH   rJ   rK   rI   r   ÚitemsrÚ   rÉ   rŽ   rz   r|   r[   )rV   rF   râ   rÜ   Úcurrentr   r   r   Ú__setitem__†  s6    ÿ
ÿ
ÿ

ÿzCatalog.__setitem__r   r?   r@   rA   rB   rE   c
                 C  s*   t ||t|ƒ||||||	d�	}
|
| |< |
S )at  Add or update the message with the specified ID.

        >>> catalog = Catalog()
        >>> catalog.add(u'foo')
        <Message ...>
        >>> catalog[u'foo']
        <Message u'foo' (flags: [])>

        This method simply constructs a `Message` object with the given
        arguments and invokes `__setitem__` with that object.

        :param id: the message ID, or a ``(singular, plural)`` tuple for
                   pluralizable messages
        :param string: the translated message string, or a
                       ``(singular, plural)`` tuple for pluralizable messages
        :param locations: a sequence of ``(filename, lineno)`` tuples
        :param flags: a set or sequence of flags
        :param auto_comments: a sequence of automatic comments
        :param user_comments: a sequence of user comments
        :param previous_id: the previous message ID, or a ``(singular, plural)``
                            tuple for pluralizable messages
        :param lineno: the line number on which the msgid line was found in the
                       PO file, if any
        :param context: the message context
        )rM   rN   )r   rP   )rV   rF   rG   rH   rI   rJ   rK   rL   rM   rN   râ   r   r   r   rS   ·  s    %þzCatalog.addz0Iterable[tuple[Message, list[TranslationError]]]c                 c  s.   | j  ¡ D ]}|j| d�}|r
||fV  q
dS )a\  Run various validation checks on the translations in the catalog.

        For every message which fails validation, this method yield a
        ``(message, errors)`` tuple, where ``message`` is the `Message` object
        and ``errors`` is a sequence of `TranslationError` objects.

        :rtype: ``generator`` of ``(message, errors)``
        )rt   N)r�   Úvaluesry   )rV   râ   rv   r   r   r   ry   â  s    	zCatalog.checkzMessage | None)rF   rN   r,   c                 C  s   | j  |  ||¡¡S )z©Return the message with the specified ID and context.

        :param id: the message ID
        :param context: the message context, or ``None`` for no context
        )r�   rÊ   rÕ   )rV   rF   rN   r   r   r   rÊ   ð  s    zCatalog.getc                 C  s"   |   ||¡}|| jv r| j|= dS )z©Delete the message with the specified ID and context.

        :param id: the message ID
        :param context: the message context, or ``None`` for no context
        NrÔ   ©rV   rF   rN   rÜ   r   r   r   rß   ø  s    
zCatalog.deleteF)ÚtemplateÚno_fuzzy_matchingÚupdate_header_commentÚkeep_user_commentsÚupdate_creation_dater,   c                   s`  ˆj ‰ˆ ¡ ‰tƒ ˆ_ i }|s\ˆD ]8}|r"ˆ| jr"ˆ |¡}ˆ| j}	||	f|ˆ |¡< q"tƒ ‰ dddddœ‡ ‡‡‡‡fdd„}
|D ]Ž}|jr†ˆ |j|j¡}|ˆv r¶|
|||ƒ q†|�s
t	ˆ |¡| 
¡ dƒ}|�r
|d }|| \}}|d	urü||f}|
|||ƒ q†|ˆ|j< q†ˆD ]$}|�s.|ˆ v�rˆ| ˆj|< �q|�rN|jˆ_|�r\|jˆ_d	S )
a¨  Update the catalog based on the given template catalog.

        >>> from babel.messages import Catalog
        >>> template = Catalog()
        >>> template.add('green', locations=[('main.py', 99)])
        <Message ...>
        >>> template.add('blue', locations=[('main.py', 100)])
        <Message ...>
        >>> template.add(('salad', 'salads'), locations=[('util.py', 42)])
        <Message ...>
        >>> catalog = Catalog(locale='de_DE')
        >>> catalog.add('blue', u'blau', locations=[('main.py', 98)])
        <Message ...>
        >>> catalog.add('head', u'Kopf', locations=[('util.py', 33)])
        <Message ...>
        >>> catalog.add(('salad', 'salads'), (u'Salat', u'Salate'),
        ...             locations=[('util.py', 38)])
        <Message ...>

        >>> catalog.update(template)
        >>> len(catalog)
        3

        >>> msg1 = catalog['green']
        >>> msg1.string
        >>> msg1.locations
        [('main.py', 99)]

        >>> msg2 = catalog['blue']
        >>> msg2.string
        u'blau'
        >>> msg2.locations
        [('main.py', 100)]

        >>> msg3 = catalog['salad']
        >>> msg3.string
        (u'Salat', u'Salate')
        >>> msg3.locations
        [('util.py', 42)]

        Messages that are in the catalog but not in the template are removed
        from the main collection, but can still be accessed via the `obsolete`
        member:

        >>> 'head' in catalog
        False
        >>> list(catalog.obsolete.values())
        [<Message 'head' (flags: [])>]

        :param template: the reference catalog, usually read from a POT file
        :param no_fuzzy_matching: whether to use fuzzy matching of message IDs
        r   útuple[str, str] | strrD   )râ   ÚoldkeyÚnewkeyr,   c                   sd  |   ¡ } d}||kr^d}ˆ  |¡ ˆ |¡}|d us8J ‚t|jtƒrP|jg| _qvt|jƒ| _nˆ |d ¡}|d usvJ ‚|j	| _	ˆr’tt
|jƒƒ| _t| jttfƒ�rt| j	ttfƒsÜd}t| j	gdgt| jƒd   ƒ| _	n0t| j	ƒˆjk�r0d}t| j	d t|j	ƒ… ƒ| _	n"t| j	ttfƒ�r0d}| j	d | _	|  j|jO  _|�rV|  jdhO  _| ˆ| j< d S )NFTr>   r/   r   rz   )rs   rS   rÊ   rU   rF   r*   rL   rP   ÚpoprG   r   rK   r|   rØ   rÐ   rI   )râ   rð   rñ   rz   Zoldmsg©Zfuzzy_matchesrí   ÚmessagesÚ	remainingrV   r   r   Ú_mergeL  s>    

ÿzCatalog.update.<locals>._merger/   r   N)r�   r   r   rG   rÕ   rN   Ú_to_fuzzy_match_keyrQ   rF   r)   ÚkeysrŸ   rŽ   r“   )rV   rê   rë   rì   rí   rî   Zfuzzy_candidatesÚmsgidrÜ   Zctxtrö   râ   ÚmatchesZmodified_keyrñ   Znewctxtr   ró   r   Úupdate  sL    <

 %ýzCatalog.updaterï   )rÜ   r,   c                 C  s$   t |tƒr|d }n|}| ¡  ¡ S )z?Converts a message key to a string suitable for fuzzy matching.r   )rU   r|   rÇ   Ústrip)rV   rÜ   Zmatchkeyr   r   r   r÷   –  s    

zCatalog._to_fuzzy_match_keyc                 C  s.   |}t |ttfƒr|d }|dur*||f}|S )z©The key for a message is just the singular ID even for pluralizable
        messages, but is a ``(msgid, msgctxt)`` tuple for context-specific
        messages.
        r   N)rU   rP   r|   ré   r   r   r   rÕ   ž  s    zCatalog._key_forr`   c                 C  sp   t |tƒsJ ‚| j ¡ |j ¡ B D ]8}|  |¡}| |¡}|du sT|du sT| |¡s" dS q"t| jƒt|jƒkS )z\Checks if catalogs are identical, taking into account messages and
        headers.
        NF)rU   r   r�   rø   rÊ   rp   rˆ   rÚ   )rV   ra   rÜ   Z	message_1Z	message_2r   r   r   rp   ª  s    

ÿþýzCatalog.is_identical)r›   r¼   )Nr   r   r   r   r   NN)N)N)FFTT)N)%r\   r‚   rƒ   r„   ÚDEFAULT_HEADERrW   r§   r¨   r©   r…   rŒ   r­   r°   r±   rŽ   r»   rÀ   rÎ   rÚ   rÐ   rÒ   r¹   r×   rÙ   rÝ   r^   rà   rá   rç   rS   ry   rÊ   rß   rû   r÷   rÕ   rp   r   r   r   r   r     sz   ò*F
!$44        ö"+    ú r   )r   r   )5r„   Ú
__future__r   r-   r5   Úcollectionsr   Úcollections.abcr   r   r   Údifflibr   Úemailr   Úheapqr	   Útypingr
   Zbabelr   r™   Z
babel.corer   r   Zbabel.datesr   Zbabel.messages.pluralsr   Z
babel.utilr   r   r   r   Ztyping_extensionsr   r*   r|   rP   r   Ú__annotations__Ú__all__r)   ÚcompileÚVERBOSEr}   r=   r   Ú	Exceptionr   rý   r‹   r   r   r   r   r   Ú<module>   s<   	 
	÷ 