ó
µ”ù\c        	   @  s+  d  Z  d d l m Z d d l Z d d l Z d d l m Z m Z d d l m	 Z	 d d l
 m Z m Z d „  Z d „  Z d	 e f d
 „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d d e d e d „ Z e j d ƒ Z d „  Z d d d „ Z d e e e e e e e d „ Z d „  Z d S(   sî   
    babel.messages.pofile
    ~~~~~~~~~~~~~~~~~~~~~

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

    :copyright: (c) 2013-2019 by the Babel Team.
    :license: BSD, see LICENSE for more details.
iÿÿÿÿ(   t   print_functionN(   t   Catalogt   Message(   t   wraptext(   t	   text_typet   cmpc         C  s)   d „  } t  j d ƒ j | |  d d !ƒ S(   s¿   Reverse `escape` the given string.

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

    :param string: the string to unescape
    c         S  sC   |  j  d ƒ } | d k r d S| d k r/ d S| d k r? d S| S(   Ni   t   ns   
t   ts   	t   rs   (   t   group(   t   matcht   m(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   replace_escapes    s    s   \\([\\trn"])i   iÿÿÿÿ(   t   ret   compilet   sub(   t   stringR   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   unescape   s    
	
c         C  s^   d |  k rP |  j  ƒ  } |  j d ƒ r4 | d } n  t t | ƒ } d j | ƒ St |  ƒ Sd S(   sì  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
    s   
s   ""i   t    N(   t
   splitlinest
   startswitht   mapR   t   join(   R   t   escaped_linest   lines(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   denormalize-   s    t   PoFileErrorc           B  s   e  Z d  Z d „  Z RS(   sD   Exception thrown by PoParser when an invalid po file is encountered.c         C  sG   t  t |  ƒ j d j d | d | ƒ ƒ | |  _ | |  _ | |  _ d  S(   Ns   {message} on {lineno}t   messaget   lineno(   t   superR   t   __init__t   formatt   catalogt   lineR   (   t   selfR   R    R!   R   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR   N   s    (		(   t   __name__t
   __module__t   __doc__R   (    (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR   L   s   t   _NormalizedStringc           B  sz   e  Z d  „  Z d „  Z d „  Z d „  Z e Z d „  Z d „  Z d „  Z	 d „  Z
 d „  Z d	 „  Z d
 „  Z d „  Z RS(   c         G  s+   g  |  _  x | D] } |  j | ƒ q Wd  S(   N(   t   _strst   append(   R"   t   argst   arg(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR   W   s    	c         C  s   |  j  j | j ƒ  ƒ d  S(   N(   R'   R(   t   strip(   R"   t   s(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR(   \   s    c         C  s   d j  t t |  j ƒ ƒ S(   NR   (   R   R   R   R'   (   R"   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR   _   s    c         C  s   t  |  j ƒ S(   N(   t   boolR'   (   R"   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __nonzero__b   s    c         C  s   t  j j |  j ƒ S(   N(   t   ost   linesepR   R'   (   R"   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __repr__g   s    c         C  s#   | s
 d St  t |  ƒ t | ƒ ƒ S(   Ni   (   R   R   (   R"   t   other(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __cmp__j   s    c         C  s   |  j  | ƒ d k S(   Ni    (   R3   (   R"   R2   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __gt__p   s    c         C  s   |  j  | ƒ d k  S(   Ni    (   R3   (   R"   R2   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __lt__s   s    c         C  s   |  j  | ƒ d k S(   Ni    (   R3   (   R"   R2   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __ge__v   s    c         C  s   |  j  | ƒ d k S(   Ni    (   R3   (   R"   R2   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __le__y   s    c         C  s   |  j  | ƒ d k S(   Ni    (   R3   (   R"   R2   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __eq__|   s    c         C  s   |  j  | ƒ d k S(   Ni    (   R3   (   R"   R2   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   __ne__   s    (   R#   R$   R   R(   R   R.   t   __bool__R1   R3   R4   R5   R6   R7   R8   R9   (    (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR&   U   s   											t   PoFileParserc           B  s†   e  Z d  Z d d d d g Z e e d „ Z d „  Z d „  Z d „  Z e d	 „ Z	 e d
 „ Z
 d „  Z d „  Z d „  Z d „  Z RS(   s–   Support class to  read messages from a ``gettext`` PO (portable object) file
    and add them to a `Catalog`

    See `read_po` for simple cases.
    t   msgidt   msgstrt   msgctxtt   msgid_pluralc         C  s;   | |  _  | |  _ d |  _ d |  _ | |  _ |  j ƒ  d  S(   Ni    (   R    t   ignore_obsoletet   countert   offsett   abort_invalidt   _reset_message_state(   R"   R    R@   RC   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR   ’   s    					c         C  sg   g  |  _  g  |  _ g  |  _ g  |  _ g  |  _ g  |  _ d  |  _ t |  _	 t |  _
 t |  _ t |  _ d  S(   N(   t   messagest   translationst	   locationst   flagst   user_commentst   auto_commentst   Nonet   contextt   Falset   obsoletet   in_msgidt	   in_msgstrt
   in_msgctxt(   R"   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyRD   š   s    										c   	      C  sÑ  |  j  j ƒ  t |  j ƒ d k rM t g  |  j D] } | j ƒ  ^ q/ ƒ } n |  j d j ƒ  } t | t t f ƒ rg  t |  j	 j
 ƒ D] } d ^ qˆ } xU |  j  D]J \ } } | |  j	 j
 k rÞ |  j d |  j d ƒ q¤ n  | j ƒ  | | <q¤ Wt | ƒ } n |  j  d d j ƒ  } |  j r3|  j j ƒ  } n d } t | | t |  j ƒ t |  j ƒ |  j |  j d |  j d d | ƒ} |  j r§|  j s´| |  j	 j | <q´n | |  j	 | <|  j d 7_ |  j ƒ  d S(   s   
        Add a message to the catalog based on the current parser state and
        clear the state ready to process the next message.
        i   i    R   s5   msg has more translations than num_plurals of catalogR   RL   N(   RF   t   sortt   lenRE   t   tupleR   t
   isinstancet   listt   rangeR    t   num_pluralst   _invalid_pofileRB   RL   RK   R   RG   t   setRH   RJ   RI   RN   R@   RA   RD   (	   R"   R   R<   t   _R   t   idxt   translationR>   R   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   _add_message§   s2    +%	!			c         C  s   |  j  r |  j ƒ  n  d  S(   N(   RE   R^   (   R"   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   _finish_current_messageÊ   s    	c         C  s9   | j  d ƒ r" |  j | | ƒ n |  j | | | ƒ d  S(   Nt   "(   R   t!   _process_string_continuation_linet   _process_keyword_line(   R"   R   R!   RN   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   _process_message_lineÎ   s    c         C  s¸  xŒ |  j  D]j } y= | j | ƒ rL | t | ƒ d k rL | t | ƒ } Pn  Wq
 t k
 rs |  j | | d ƒ q
 Xq
 W|  j | | d ƒ d  S| d k r¨ |  j ƒ  n  | |  _ | d k rÉ | |  _ n  | d k r t |  _	 t
 |  _ |  j j t | ƒ ƒ n´ | d k rt |  _ t
 |  _ | j d ƒ rn| d	 j d
 d	 ƒ \ } } |  j j t | ƒ t | ƒ g ƒ q´|  j j d t | ƒ g ƒ n' | d k r´t
 |  _	 t | ƒ |  _ n  d  S(   Nt    t   [s$   Keyword must be followed by a strings0   Start of line didn't match any expected keyword.R<   R>   R?   R=   i   t   ]i    (   Rd   Re   (   R<   R>   (   R<   R?   (   t	   _keywordsR   RS   t
   IndexErrorRY   R_   RN   RB   RM   RQ   t   TrueRO   RE   R(   R&   RP   t   splitRF   t   intRL   (   R"   R   R!   RN   t   keywordR*   R\   t   msg(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyRb   Ô   s8    %					%	c         C  ss   |  j  r |  j d } nI |  j r6 |  j d d } n, |  j rK |  j } n |  j | | d ƒ d  S| j | ƒ d  S(   Niÿÿÿÿi   s<   Got line starting with " but not in msgid, msgstr or msgctxt(   RO   RE   RP   RF   RQ   RL   RY   R(   (   R"   R!   R   R,   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyRa   ý   s    			c         C  sk  |  j  ƒ  | d j d ƒ r¾ xG| d j ƒ  j ƒ  D]ƒ } | j d ƒ } | d k r¡ y t | | d ƒ } Wn t k
 rƒ q4 n X|  j j | |  | f ƒ q4 |  j j | d  f ƒ q4 Wn© | d j d ƒ rx“ | d j ƒ  j d ƒ D] } |  j
 j | j ƒ  ƒ që WnY | d j d ƒ rM| d j ƒ  } | rg|  j j | ƒ qgn |  j j | d j ƒ  ƒ d  S(   Ni   t   :i   i    t   ,t   .(   R_   R   t   lstripRj   t   rfindRk   t
   ValueErrorRG   R(   RK   RH   R+   RJ   RI   (   R"   R!   t   locationt   posR   t   flagt   comment(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   _process_comment	  s&    
 c         C  s3  x¾ t  | ƒ D]° \ } } | j ƒ  } t | t ƒ sL | j |  j j ƒ } n  | sX q n  | j d ƒ r­ | d j d ƒ r |  j | | d j	 ƒ  d t
 ƒq½ |  j | ƒ q |  j | | ƒ q W|  j ƒ  |  j r/|  j sð |  j sð |  j r/|  j j t d ƒ ƒ |  j j d t d ƒ g ƒ |  j ƒ  n  d S(	   s˜   
        Reads from the file-like object `fileobj` and adds any po file
        units found in it to the `Catalog` supplied to the constructor.
        t   #i   t   ~i   RN   u   ""i    N(   t	   enumerateR+   RU   R   t   decodeR    t   charsetR   Rc   Rq   Ri   Rx   R_   RA   RH   RI   RJ   RE   R(   R&   RF   R^   (   R"   t   fileobjR   R!   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   parse$  s     #
%c         C  sO   |  j  r$ t | |  j | | ƒ ‚ n  t d | ƒ t d j | d | ƒ ƒ d  S(   Ns   WARNING:u!   WARNING: Problem on line {0}: {1}i   (   RC   R   R    t   printR   (   R"   R!   R   Rm   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyRY   A  s    	(   R#   R$   R%   Rg   RM   R   RD   R^   R_   Rc   Rb   Ra   Rx   R   RY   (    (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR;   „   s   			#	)			c         C  sA   t  d | d | d | ƒ } t | | d | ƒ} | j |  ƒ | S(   s  Read messages from a ``gettext`` PO (portable object) file from the given
    file-like object and return a `Catalog`.

    >>> from datetime import datetime
    >>> from babel._compat 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 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
    t   localet   domainR}   RC   (   R   R;   R   (   R~   R   R‚   R@   R}   RC   R    t   parser(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   read_poH  s    /sL   (\s+|[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))c         C  sD   d |  j  d d ƒ j  d d ƒ j  d d ƒ j  d d	 ƒ j  d
 d ƒ S(   sõ   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
    s   "%s"s   \s   \\s   	s   \ts   s   \rs   
s   \ns   "s   \"(   t   replace(   R   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   escape„  s
    R   iL   c   
      C  s±  | r-| d k r-t  | ƒ } g  } x|  j t ƒ D]ò } t  t | ƒ ƒ | | k rt j | ƒ } | j ƒ  x´ | rg  } d } xu | rû t  t | d ƒ ƒ d | }	 | |	 | k  rÛ | j | j ƒ  ƒ | |	 7} q‡ | s÷ | j | j ƒ  ƒ n  Pq‡ W| j d j	 | ƒ ƒ qr Wq4 | j | ƒ q4 Wn |  j t ƒ } t  | ƒ d k rXt |  ƒ S| rƒ| d rƒ| d =| d c d 7<n  d d j	 g  | D] } | t | ƒ ^ q“ƒ S(	   s©  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
    i    i   iÿÿÿÿu    i   s   
u   ""
u   
(
   RS   R   Ri   R†   t   WORD_SEPRj   t   reverseR(   t   popR   (
   R   t   prefixt   widtht	   prefixlenR   R!   t   chunkst   buft   sizet   l(    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt	   normalize–  s6    
		
c
      	     sB  d ‡ f d † ‰  ‡ ‡ f d †  ‰ d ‡ ‡ f d † }
 d ‡  ‡ ‡ f d † } d } | rf d } n | ru d } n  x_t ˆ d | ƒD]K} | j s| r£ qˆ n  ˆ j } ˆ r	ˆ d	 k r	g  } x0 | j ƒ  D]" } | t | d
 ˆ d d ƒ7} qÑ Wd j | ƒ } n  ˆ | d ƒ n  x | j D] } |
 | ƒ q$Wx! | j D] } |
 | d d ƒqBW| s g  } y t	 | j
 ƒ } Wn t k
 r—| j
 } n Xxi | D]a \ } } | rà|	 rà| j d | j t j d ƒ | f ƒ qŸ| j d | j t j d ƒ ƒ qŸW|
 d j | ƒ d d ƒn  | j rSˆ d d j d g t	 | j ƒ ƒ ƒ n  | j r¿| r¿|
 d ˆ  | j d	 ƒ d d ƒt | j ƒ d k r¿|
 d ˆ  | j d ƒ d d ƒq¿n  | | ƒ ˆ d ƒ qˆ W| s>x^ t ˆ j j ƒ  d | ƒD]> } x | j D] } |
 | ƒ q	W| | d d ƒˆ d ƒ qùWn  d S(   sØ  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 babel._compat 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
    R   c           s   t  |  d | d ˆ  ƒS(   NRŠ   R‹   (   R‘   (   t   keyRŠ   (   R‹   (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt
   _normalize  s    c           s8   t  |  t ƒ r' |  j ˆ  j d ƒ }  n  ˆ j |  ƒ d  S(   Nt   backslashreplace(   RU   R   t   encodeR}   t   write(   t   text(   R    R~   (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   _write  s    c           sY   ˆ r ˆ d k r ˆ } n d } x1 t  |  | ƒ D]  } ˆ  d | | j ƒ  f ƒ q1 Wd  S(   Ni    iL   s   #%s %s
(   R   R+   (   Rw   RŠ   t   _widthR!   (   R˜   R‹   (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   _write_comment	  s
    	c           sj  t  |  j t t f ƒ rô |  j rD ˆ d | ˆ  |  j | ƒ f ƒ n  ˆ d | ˆ  |  j d | ƒ f ƒ ˆ d | ˆ  |  j d | ƒ f ƒ x× t ˆ j ƒ D]Q } y |  j | } Wn t k
 rÌ d } n Xˆ d | | ˆ  | | ƒ f ƒ qœ Wnr |  j r ˆ d | ˆ  |  j | ƒ f ƒ n  ˆ d | ˆ  |  j | ƒ f ƒ ˆ d | ˆ  |  j pXd | ƒ f ƒ d  S(	   Ns   %smsgctxt %s
s   %smsgid %s
i    s   %smsgid_plural %s
i   R   s   %smsgstr[%d] %s
s   %smsgstr %s
(	   RU   t   idRV   RT   RL   RW   RX   R   Rh   (   R   RŠ   R\   R   (   R“   R˜   R    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   _write_message  s(    		$
!		 R   Rt   t   sort_byi    R‹   t   subsequent_indents   # u   
RŠ   Rp   u   %s:%dt   /u   %sRd   Rn   s   #%s
s   , s   msgid %st   |i   s   msgid_plural %ss   
s   #~ N(   RK   t   _sort_messagesR›   t   header_commentR   R   R   RI   RJ   t   sortedRG   t	   TypeErrorR(   R…   R/   t   sepRH   t   previous_idRS   RN   t   values(   R~   R    R‹   t   no_locationt   omit_headert   sort_outputt   sort_by_fileR@   t   include_previoust   include_linenoRš   Rœ   R   R   t   comment_headerR   R!   Rw   t   locsRG   t   filenameR   (    (   R“   R˜   R    R~   R‹   s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   write_poÓ  sn    .
				)$	*	
c         C  sK   t  |  ƒ }  | d k r% |  j ƒ  n" | d k rG |  j d d „  ƒ n  |  S(   sø   
    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   Rt   R’   c         S  s   |  j  S(   N(   RG   (   R   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   <lambda>~  R   (   RV   RR   (   RE   R   (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyR¡   p  s    
(   R%   t
   __future__R    R/   R   t   babel.messages.catalogR   R   t
   babel.utilR   t   babel._compatR   R   R   R   t	   ExceptionR   t   objectR&   R;   RK   RM   R„   R   R‡   R†   R‘   Ri   R±   R¡   (    (    (    s4   lib/python2.7/site-packages/babel/messages/pofile.pyt   <module>   s&   			/Ä5	=		›