o
    VÛë\(~  ã                   @   s0  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 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 ddlmZmZmZm Z m!Z!m"Z" g d¢Z#e $dej%¡Z&dd„ Z'G dd„ de(ƒZ)G dd„ de*ƒZ+dZ,erŒdd„ Z-neZ-G dd„ de(ƒZ.dS )zÅ
    babel.messages.catalog
    ~~~~~~~~~~~~~~~~~~~~~~

    Data structures for message catalogs.

    :copyright: (c) 2013-2019 by the Babel Team.
    :license: BSD, see LICENSE for more details.
é    N)Úparse_header)ÚOrderedDict)ÚdatetimeÚtime)Úget_close_matches)Úmessage_from_string)Úcopy)Ú__version__)ÚLocaleÚUnknownLocaleError)Úformat_datetime)Ú
get_plural)ÚdistinctÚLOCALTZÚFixedOffsetTimezone)Ústring_typesÚnumber_typesÚPY2ÚcmpÚ	text_typeÚ
force_text)ÚMessageÚCatalogÚTranslationErrorz¨
    \%
        (?:\(([\w]*)\))?
        (
            [-#0\ +]?(?:\*|[\d]+)?
            (?:\.(?:\*|[\d]+))?
            [hlL]?
        )
        ([diouxXeEfFgGcrs%])
c                 C   sÀ   t  d| ¡}t | d¡d¡}t |¡}t |¡}| 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})?$r   z%Y-%m-%d %H:%MÚtzoffsetr   é   é   Ú1é<   ©Útzinfo)ÚreÚmatchr   ÚstrptimeÚgroupÚmktimer   ÚfromtimestampÚintr   Úreplace)Úvaluer"   ÚttÚtsÚdtr   Úplus_minus_sÚrestÚhours_offset_sÚmins_offset_sÚ
plus_minusÚhours_offsetÚmins_offsetÚnet_mins_offset© r5   ú8/usr/lib/python3/dist-packages/babel/messages/catalog.pyÚ_parse_datetime_header,   s"   


r7   c                   @   s”   e Zd ZdZ		d!dd„Zdd„ Zd	d
„ Zdd„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zd"dd„Zedd„ ƒZedd„ ƒZedd „ ƒZdS )#r   z0Representation of a single message in a catalog.Ú r5   Nc
           
      C   s    || _ |s
| jr
d}|| _tt|ƒƒ| _t|ƒ| _|r%| jr%| j 	d¡ n| j 
d¡ tt|ƒƒ| _tt|ƒƒ| _t|tƒrC|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
        )r8   r8   zpython-formatN)ÚidÚpluralizableÚstringÚlistr   Ú	locationsÚsetÚflagsÚpython_formatÚaddÚdiscardÚauto_commentsÚuser_commentsÚ
isinstancer   Úprevious_idÚlinenoÚcontext)
Úselfr9   r;   r=   r?   rC   rD   rF   rG   rH   r5   r5   r6   Ú__init__O   s    






zMessage.__init__c                 C   s   dt | ƒj| jt| jƒf S )Nz<%s %r (flags: %r)>)ÚtypeÚ__name__r9   r<   r?   ©rI   r5   r5   r6   Ú__repr__t   s   ÿzMessage.__repr__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pdfS )Nr   r8   )rE   r   r:   r9   rH   )Úobjr5   r5   r6   Úvalues_to_comparez   s   z*Message.__cmp__.<locals>.values_to_compare)r   )rI   ÚotherrP   r5   r5   r6   Ú__cmp__x   s   zMessage.__cmp__c                 C   s   |   |¡dkS ©Nr   ©rR   ©rI   rQ   r5   r5   r6   Ú__gt__€   ó   zMessage.__gt__c                 C   s   |   |¡dk S rS   rT   rU   r5   r5   r6   Ú__lt__ƒ   rW   zMessage.__lt__c                 C   s   |   |¡dkS rS   rT   rU   r5   r5   r6   Ú__ge__†   rW   zMessage.__ge__c                 C   s   |   |¡dkS rS   rT   rU   r5   r5   r6   Ú__le__‰   rW   zMessage.__le__c                 C   s   |   |¡dkS rS   rT   rU   r5   r5   r6   Ú__eq__Œ   rW   zMessage.__eq__c                 C   s   |   |¡dkS rS   rT   rU   r5   r5   r6   Ú__ne__�   rW   zMessage.__ne__c                 C   s2   t tt| j| j| j| j| j| j| j	| j
| jf	ƒŽ S ©N)r   Úmapr   r9   r;   r=   r?   rC   rD   rF   rG   rH   rM   r5   r5   r6   Úclone’   s
   ýzMessage.clonec                 C   sZ   ddl m} g }|D ] }z||| ƒ W q
 ty* } z| |¡ W Y d}~q
d}~ww |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)Úbabel.messages.checkersr`   r   Úappend)rI   Úcatalogr`   ÚerrorsÚcheckerÚer5   r5   r6   Ú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©r?   rM   r5   r5   r6   rh   «   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`)rE   r9   r<   ÚtuplerM   r5   r5   r6   r:   º   ó   
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 r]   )ÚPYTHON_FORMATÚsearch)Ú.0r9   r5   r5   r6   Ú	<genexpr>Ó   s   € z(Message.python_format.<locals>.<genexpr>)r9   rE   r<   rj   Úany)rI   Úidsr5   r5   r6   r@   Æ   s   
zMessage.python_format)r8   r5   r5   r5   r5   r5   NNr]   )rL   Ú
__module__Ú__qualname__Ú__doc__rJ   rN   rR   rV   rX   rY   rZ   r[   r\   r_   rg   Úpropertyrh   r:   r@   r5   r5   r5   r6   r   L   s*    
ÿ%


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)rL   rr   rs   rt   r5   r5   r5   r6   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.
#c                 C   sD   t |  d¡ƒ}i }| ¡ D ]\}}| d¡}| d¡}|||< q|S )NÚutf8)r   ÚencodeÚitemsÚdecode)Úheader_stringÚheadersÚdecoded_headersÚnamer)   r5   r5   r6   Ú_parse_headerä   s   


r~   c                   @   s4  e Zd ZdZddeddddddddddfdd„Zdd„ Zdd	„ Zd
d„ Ze	eeƒZ
e	eƒZdd„ Zdd„ Ze	eedd�Zdd„ Zdd„ Ze	eedd�Ze	dd„ ƒZe	dd„ ƒZe	dd„ ƒZdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Z	+	d9d,d-„Zd.d/„ Zd:d0d1„Zd:d2d3„Zd;d5d6„Z d:d7d8„Z!dS )<r   z$Representation of a message catalog.NTc                 C   sè   || _ || _|| _tƒ | _|pd| _|pd| _|pd| _|pd| _|
p$d| _		 |p*d| _
	 |p0d| _|du r<t t¡}nt|tƒrJ|jsJ|jtd	�}|| _|	du rTd
}	nt|	tƒrb|	jsb|	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>zutf-8Nr   zYEAR-MO-DA HO:MI+ZONE)ÚdomainÚlocaleÚ_header_commentr   Ú	_messagesÚprojectÚversionÚcopyright_holderÚmsgid_bugs_addressÚlast_translatorÚlanguage_teamÚcharsetr   Únowr   rE   r    r(   Úcreation_dateÚrevision_daterh   ÚobsoleteÚ_num_pluralsÚ_plural_expr)rI   rƒ   r‚   Úheader_commentr†   r‡   rˆ   r‰   rŽ   r�   rŠ   r‹   rŒ   rh   r5   r5   r6   rJ   õ   s6   







zCatalog.__init__c                 C   s„   |d u rd | _ d | _d S t|tƒrt|ƒ| _ || _d S t|tƒr<t|ƒ| _ z	t |¡| _W d S  ty;   d | _Y d S w td| ƒ‚)NzF`locale` must be a Locale, a locale identifier string, or None; got %r)	Ú_locale_identifierÚ_localerE   r
   r   r   Úparser   Ú	TypeError©rI   rƒ   r5   r5   r6   Ú_set_locale/  s$   



þþzCatalog._set_localec                 C   ó   | j S r]   )r•   rM   r5   r5   r6   Ú_get_localeD  ó   zCatalog._get_localec                 C   rš   r]   )r”   rM   r5   r5   r6   Ú_get_locale_identifierG  rœ   zCatalog._get_locale_identifierc                 C   s„   | j }t t¡ d¡}t| jdƒr| j d¡}| d| j¡ d| j	¡ d|¡ d| j
¡}| jr3| jjn| j}|r@| dd| ¡}|S )	Nz%YÚstrftimer   r€   ÚYEARr�   zTranslations templatez%s translations)r„   r   r�   r   rž   Úhasattrr�   r(   r†   r‡   rˆ   rƒ   Úenglish_nameÚlocale_identifier)rI   ÚcommentÚyearÚlocale_namer5   r5   r6   Ú_get_header_commentM  s   

ýzCatalog._get_header_commentc                 C   s
   || _ d S r]   )r„   )rI   r;   r5   r5   r6   Ú_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`
    )Údocc                 C   sJ  g }|  dd| j| jf f¡ |  d| jf¡ |  dt| jddd�f¡ t| jtt	ft
 ƒr<|  dt| jddd�f¡ n|  d| jf¡ |  d	| jf¡ | jrY|  d
t| jƒf¡ | jrqd| jv rq|  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 f¡ |S )NzProject-Id-Versionz%s %szReport-Msgid-Bugs-TozPOT-Creation-Datezyyyy-MM-dd HH:mmZÚen)rƒ   zPO-Revision-DatezLast-TranslatorÚLanguageÚLANGUAGEzLanguage-TeamzPlural-Forms)zMIME-Versionz1.0zContent-Typeztext/plain; charset=%s)zContent-Transfer-EncodingÚ8bitzGenerated-Byz	Babel %s
)rb   r†   r‡   r‰   r   rŽ   rE   r�   r   Útime_r   rŠ   r¢   Ústrr‹   r(   rƒ   Úplural_formsrŒ   r€   )rI   r{   r5   r5   r6   Ú_get_mime_headers  sH   ÿÿÿÿÿÿÿ

ÿ
zCatalog._get_mime_headersc                 C   sH  |D ]Ÿ\}}t | ¡ | jd�}t || jd�}|dkr/| d¡}d |d d… ¡| _|d | _q|dkr7|| _q|dkr?|| _q|dkrO| 	dd	¡}|  
|¡ q|d
krW|| _q|dkrmt|ƒ\}}d|v rl|d  ¡ | _q|dkrŠtd| ƒ\}}t| dd¡ƒ| _| dd¡| _q|dkr”t|ƒ| _q|dkr¡d|vr¡t|ƒ| _qd S )N)Úencodingzproject-id-versionú éÿÿÿÿzreport-msgid-bugs-tozlast-translatorÚlanguageú-Ú_zlanguage-teamzcontent-typerŒ   zplural-formsz ;Únpluralsr   Úpluralú(n != 1)zpot-creation-datezpo-revision-daterŸ   )r   ÚlowerrŒ   ÚsplitÚjoinr†   r‡   r‰   rŠ   r(   r™   r‹   r   r'   Úgetr‘   r’   r7   rŽ   r�   )rI   r{   r}   r)   ÚpartsÚmimetypeÚparamsr¶   r5   r5   r6   Ú_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
    >>> 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`
    c                 C   ó.   | 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`Nr   r   )r‘   rƒ   r   )rI   Únumr5   r5   r6   Únum_pluralsò  s   

zCatalog.num_pluralsc                 C   rÂ   )a`  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: `string_types`Nr¹   r   )r’   rƒ   r   )rI   Úexprr5   r5   r6   Úplural_expr  s   
zCatalog.plural_exprc                 C   s   d| j | jf 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=%s; plural=%s)rÄ   rÆ   rM   r5   r5   r6   r¯     rk   zCatalog.plural_formsc                 C   s   |   |¡| jv S )z?Return whether the catalog has a message with the specified ID.©Ú_key_forr…   ©rI   r9   r5   r5   r6   Ú__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…   rM   r5   r5   r6   Ú__len__&  s   
zCatalog.__len__c                 c   sp   � g }| j D ]\}}| d||f ¡ qtƒ }| jr|dhO }tdd |¡|d�V  | jD ]}| j| V  q-d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%s: %srh   r8   Ú
ri   N)Úmime_headersrb   r>   rh   r   r¼   r…   )rI   Úbufr}   r)   r?   Úkeyr5   r5   r6   Ú__iter__,  s   €

ÿzCatalog.__iter__c                 C   s*   d}| j r
d| j  }dt| ƒj| j|f S )Nr8   z %sz	<%s %r%s>)rƒ   rK   rL   r‚   r˜   r5   r5   r6   rN   ;  s   
zCatalog.__repr__c                 C   s   |   |¡ dS )z)Delete the message with the specified ID.N)ÚdeleterÉ   r5   r5   r6   Ú__delitem__A  s   zCatalog.__delitem__c                 C   s
   |   |¡S )zUReturn the message with the specified ID.

        :param id: the message ID
        )r½   rÉ   r5   r5   r6   Ú__getitem__E  s   
zCatalog.__getitem__c                 C   s   t |tƒs	J dƒ‚|  ||j¡}| j |¡}|rS|jr&|js&|j|_|j|_t	t
|j|j ƒƒ|_t	t
|j|j ƒƒ|_t	t
|j|j ƒƒ|_| j|jO  _|}dS |dkrqt|jƒ ¡ | _d dd„ |jD ƒ¡| _|j| _dS 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 objectr8   rÍ   c                 S   s   g | ]}d |   ¡ ‘qS )z# %s)Úrstrip)rn   Úcr5   r5   r6   Ú
<listcomp>u  s    z'Catalog.__setitem__.<locals>.<listcomp>zExpected sequence but got %sN)rE   r   rÈ   rH   r…   r½   r:   r9   r;   r<   r   r=   rC   rD   r?   r~   rx   rÎ   r¼   r“   rh   rj   rK   )rI   r9   ÚmessagerÐ   Úcurrentr5   r5   r6   Ú__setitem__L  s:   
ÿ
ÿ
ÿ

ÿÿzCatalog.__setitem__r5   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
        )rG   rH   )r   r<   )rI   r9   r;   r=   r?   rC   rD   rF   rG   rH   rØ   r5   r5   r6   rA   ~  s   þzCatalog.addc                 c   s0   � | j  ¡ D ]}|j| d�}|r||fV  qdS )aB  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: ``iterator``
        )rc   N)r…   Úvaluesrg   )rI   rØ   rd   r5   r5   r6   rg   Ÿ  s   €	
€ýzCatalog.checkc                 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È   )rI   r9   rH   r5   r5   r6   r½   ­  s   zCatalog.getc                 C   s&   |   ||¡}|| jv r| j|= dS 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Ç   ©rI   r9   rH   rÐ   r5   r5   r6   rÒ   µ  s   
ÿzCatalog.deleteFc                    s6  ˆj ‰ˆ ¡ ‰tƒ ˆ_ g }|st‡‡fdd„ˆD ƒƒ}tƒ ‰ ‡ ‡‡‡‡fdd„}|D ]R}|jr|ˆ |j|j¡}|ˆv rB||||ƒ q*|du rwt|t	ƒrP|d }	n|}	t
|	 ¡  ¡ | ¡ dƒ}
|
rw|
d }|| }|durp||f}||||ƒ q*|ˆ|j< q*ˆD ]}|s‡|ˆ vrŽˆ| ˆj|< q|r•|jˆ_|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
        c                    s.   g | ]}|rˆ | j rˆ |¡ˆ | jf‘qS r5   )r;   rÈ   rH   )rn   Úmsgid)ÚmessagesrI   r5   r6   r×   û  s    þþÿz"Catalog.update.<locals>.<listcomp>c                    sD  |   ¡ } d}||kr)d}ˆ  |¡ ˆ |¡}t|jtƒr"|jg| _nt|jƒ| _nˆ |d ¡}|j	| _	ˆr=tt
|jƒƒ| _t| jttfƒryt| j	ttfƒsad}t| j	gdgt| jƒd   ƒ| _	n(t| j	ƒˆjkrxd}t| j	d t|j	ƒ… ƒ| _	nt| j	ttfƒr‰d}| j	d | _	|  j|jO  _|r›|  jdhO  _| ˆ| j< d S )NFTr8   r   r   rh   )r_   rA   r½   rE   r9   r   rF   r<   Úpopr;   r   rD   rj   rË   rÄ   r?   )rØ   ÚoldkeyÚnewkeyrh   Úoldmsg©Úfuzzy_matchesÚkeep_user_commentsrÞ   Ú	remainingrI   r5   r6   Ú_merge  s<   

ÿ€zCatalog.update.<locals>._mergeFr   r   N)r…   r   r   Údictr>   r9   rÈ   rH   rE   rj   r   rº   ÚstripÚkeysr�   r“   rŽ   )rI   ÚtemplateÚno_fuzzy_matchingÚupdate_header_commentrå   Úfuzzy_candidatesrç   rØ   rÐ   ÚmatchkeyÚmatchesrá   ÚnewctxtrÝ   r5   rã   r6   Úupdate¿  sL   5þ#

ÿ
€€zCatalog.updatec                 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)rE   r<   rj   rÜ   r5   r5   r6   rÈ   I  s   zCatalog._key_for)Nr5   r5   r5   r5   r5   NNr]   )FFT)"rL   rr   rs   rt   ÚDEFAULT_HEADERrJ   r™   r›   r�   ru   rƒ   r¢   r¦   r§   r“   r°   rÁ   rÎ   rÄ   rÆ   r¯   rÊ   rÌ   rÑ   rN   rÓ   rÔ   rÚ   rA   rg   r½   rÒ   rò   rÈ   r5   r5   r5   r6   r   ò   sR    
ü:
!  3


2
ÿ!



 r   )/rt   r!   r   Úcgir   Úcollectionsr   r   r­   Údifflibr   Úemailr   r   Úbabelr	   r€   Ú
babel.corer
   r   Úbabel.datesr   Úbabel.messages.pluralsr   Ú
babel.utilr   r   r   Úbabel._compatr   r   r   r   r   r   Ú__all__ÚcompileÚVERBOSErl   r7   Úobjectr   Ú	Exceptionr   ró   r~   r   r5   r5   r5   r6   Ú<module>   s8   
 	÷  
