o
    V\BS                  	   @   s  d Z ddlZddlmZ dZdZdd ZG dd	 d	eZd
d Z	dd Z
dd Zdd Zdd Zdd ZG dd deZdZdedejfdedefdedfdedfd ed!ejfgZd"d# ZdBd$d%ZdBd&d'Zd(d) Zd*d+ Zd,d- Zd.d/ ZG d0d1 d1eZd2d3 Zd4d5 Zd6d7 Z G d8d9 d9eZ!G d:d; d;e!Z"G d<d= d=e!Z#G d>d? d?e#Z$G d@dA dAe!Z%dS )Cz
    babel.numbers
    ~~~~~~~~~~~~~

    CLDR Plural support.  See UTS #35.

    :copyright: (c) 2013-2019 by the Babel Team.
    :license: BSD, see LICENSE for more details.
    N)decimal)zeroonetwofewmanyotherr   c                 C   s   t | }t|}t|tr||kr|}ntt|}t|tjrY| }|j}|dk r3|j	|d nd}d
dd |D }|d}t|}t|}	t|pPd}
t|pVd}nd } }	 }
}||||	|
|fS )a#  Extract operands from a decimal, a float or an int, according to `CLDR rules`_.

    The result is a 6-tuple (n, i, v, w, f, t), where those symbols are as follows:

    ====== ===============================================================
    Symbol Value
    ------ ---------------------------------------------------------------
    n      absolute value of the source number (integer and decimals).
    i      integer digits of n.
    v      number of visible fraction digits in n, with trailing zeros.
    w      number of visible fraction digits in n, without trailing zeros.
    f      visible fractional digits in n, with trailing zeros.
    t      visible fractional digits in n, without trailing zeros.
    ====== ===============================================================

    .. _`CLDR rules`: https://www.unicode.org/reports/tr35/tr35-33/tr35-numbers.html#Operands

    :param source: A real number
    :type source: int|float|decimal.Decimal
    :return: A n-i-v-w-f-t tuple
    :rtype: tuple[decimal.Decimal, int, int, int, int, int]
    r   N  c                 s   s    | ]}t |V  qd S Nstr).0dr	   r	   ./usr/lib/python3/dist-packages/babel/plural.py	<genexpr>A   s    z#extract_operands.<locals>.<genexpr>0)absint
isinstancefloatr   Decimalr   as_tupleexponentdigitsjoinrstriplen)sourceni	dec_tupleexpfraction_digitstrailingno_trailingvwftr	   r	   r   extract_operands   s$   

r*   c                   @   sd   e Zd ZdZdZdd Zdd Zedd Ze	d	d
 Z
e	dd ddZdd Zdd Zdd ZdS )
PluralRuleaf  Represents a set of language pluralization rules.  The constructor
    accepts a list of (tag, expr) tuples or a dict of `CLDR rules`_. The
    resulting object is callable and accepts one parameter with a positive or
    negative number (both integer and float) for the number that indicates the
    plural form for a string and returns the tag for the format:

    >>> rule = PluralRule({'one': 'n is 1'})
    >>> rule(1)
    'one'
    >>> rule(2)
    'other'

    Currently the CLDR defines these tags: zero, one, two, few, many and
    other where other is an implicit default.  Rules should be mutually
    exclusive; for a given numeric value, only one rule should apply (i.e.
    the condition should only be true for one of the plural rule elements.

    .. _`CLDR rules`: https://www.unicode.org/reports/tr35/tr35-33/tr35-numbers.html#Language_Plural_Rules
    )abstract_funcc                 C   s   t |tr	| }t }g | _tt|D ],\}}|tvr#td| ||v r-td| |	| t
|j}|rA| j||f qdS )a$  Initialize the rule instance.

        :param rules: a list of ``(tag, expr)``) tuples with the rules
                      conforming to UTS #35 or a dict with the tags as keys
                      and expressions as values.
        :raise RuleError: if the expression is malformed
        zunknown tag %rztag %r defined twiceN)r   dictitemssetr,   sortedlist_plural_tags
ValueErroradd_Parserastappend)selfrulesfoundkeyexprr7   r	   r	   r   __init__c   s   


zPluralRule.__init__c                    s,   | j  dt| jd fddtD f S )Nz<%s %r>z, c                    s$   g | ]}| v rd | | f qS )z%s: %sr	   r   tagr:   r	   r   
<listcomp>}   s    z'PluralRule.__repr__.<locals>.<listcomp>)r:   type__name__r   r3   r9   r	   rA   r   __repr__y   s
   zPluralRule.__repr__c                 C   s   t || r|S | |S )a
  Create a `PluralRule` instance for the given rules.  If the rules
        are a `PluralRule` object, that object is returned.

        :param rules: the rules as list or dict, or a `PluralRule` object
        :raise RuleError: if the expression is malformed
        )r   )clsr:   r	   r	   r   parse   s   
zPluralRule.parsec                    s    t  j t fdd| jD S )zThe `PluralRule` as a dict of unicode plural rules.

        >>> rule = PluralRule({'one': 'n is 1'})
        >>> rule.rules
        {'one': 'n is 1'}
        c                    s   g | ]
\}}| |fqS r	   r	   )r   r@   r7   _compiler	   r   rB      s    z$PluralRule.rules.<locals>.<listcomp>)_UnicodeCompilercompiler.   r,   rE   r	   rI   r   r:      s   zPluralRule.rulesc                 C   s   t dd | jD S )Nc                 S   s   g | ]}|d  qS )r   r	   )r   r    r	   r	   r   rB          z'PluralRule.<lambda>.<locals>.<listcomp>)	frozensetr,   xr	   r	   r   <lambda>   rM   zPluralRule.<lambda>z
        A set of explicitly defined tags in this rule.  The implicit default
        ``'other'`` rules is not part of this set unless there is an explicit
        rule for it.)docc                 C   s   | j S r   r,   rE   r	   r	   r   __getstate__      zPluralRule.__getstate__c                 C   s
   || _ d S r   rS   )r9   r,   r	   r	   r   __setstate__      
zPluralRule.__setstate__c                 C   s   t | ds
t| | _| |S )Nr-   )hasattr	to_pythonr-   )r9   r   r	   r	   r   __call__   s   


zPluralRule.__call__N)rD   
__module____qualname____doc__	__slots__r>   rF   classmethodrH   propertyr:   tagsrT   rV   rZ   r	   r	   r	   r   r+   L   s    


r+   c                 C   sR   t  j}dg}t| jD ]\}}|d|||f  q|dt  d|S )a  Convert a list/dict of rules or a `PluralRule` object into a JavaScript
    function.  This function depends on no external library:

    >>> to_javascript({'one': 'n is 1'})
    "(function(n) { return (n == 1) ? 'one' : 'other'; })"

    Implementation detail: The function generated will probably evaluate
    expressions involved into range operations multiple times.  This has the
    advantage that external helper functions are not required and is not a
    big performance hit for these simple calculations.

    :param rule: the rules as list or dict, or a `PluralRule` object
    :raise RuleError: if the expression is malformed
    z(function(n) { return z
%s ? %r : z%r; })r
   )_JavaScriptCompilerrL   r+   rH   r,   r8   _fallback_tagr   )ruleto_jsresultr@   r7   r	   r	   r   to_javascript   s   
rg   c                 C   s   t tttd}t j}ddg}t| jD ]\}}|	d||t
|f  q|	dt  td|dd}t|| |d	 S )
a<  Convert a list/dict of rules or a `PluralRule` object into a regular
    Python function.  This is useful in situations where you need a real
    function and don't are about the actual rule object:

    >>> func = to_python({'one': 'n is 1', 'few': 'n in 2..4'})
    >>> func(1)
    'one'
    >>> func(3)
    'few'
    >>> func = to_python({'one': 'n in 1,11', 'few': 'n in 3..10,13..19'})
    >>> func(11)
    'one'
    >>> func(15)
    'few'

    :param rule: the rules as list or dict, or a `PluralRule` object
    :raise RuleError: if the expression is malformed
    )INWITHINMODr*   zdef evaluate(n):z' n, i, v, w, f, t = extract_operands(n)z if (%s): return %rz
 return %r
z<rule>execevaluate)in_range_listwithin_range_listcldr_modulor*   _PythonCompilerrL   r+   rH   r,   r8   r   rc   r   eval)rd   	namespaceto_python_funcrf   r@   r7   coder	   r	   r   rY      s   
rY   c                    s   t | } | jthB  t j} fddtD j}dt  g}| j	D ]\}}|
d||||f  q#|
d|t  d|S )a~  The plural rule as gettext expression.  The gettext expression is
    technically limited to integers and returns indices rather than tags.

    >>> to_gettext({'one': 'n is 1', 'two': 'n is 2'})
    'nplurals=3; plural=((n == 1) ? 0 : (n == 2) ? 1 : 2)'

    :param rule: the rules as list or dict, or a `PluralRule` object
    :raise RuleError: if the expression is malformed
    c                    s   g | ]}| v r|qS r	   r	   r?   	used_tagsr	   r   rB          zto_gettext.<locals>.<listcomp>znplurals=%d; plural=(z
%s ? %d : z%d)r
   )r+   rH   ra   rc   _GettextCompilerrL   r3   indexr   r,   r8   r   )rd   rJ   
_get_indexrf   r@   r7   r	   rv   r   
to_gettext   s   


r|   c                 C   s   | t | ko
t| |S )a  Integer range list test.  This is the callback for the "in" operator
    of the UTS #35 pluralization rule language:

    >>> in_range_list(1, [(1, 3)])
    True
    >>> in_range_list(3, [(1, 3)])
    True
    >>> in_range_list(3, [(1, 3), (5, 8)])
    True
    >>> in_range_list(1.2, [(1, 4)])
    False
    >>> in_range_list(10, [(1, 4)])
    False
    >>> in_range_list(10, [(1, 4), (6, 8)])
    False
    )r   ro   num
range_listr	   r	   r   rn         rn   c                    s   t  fdd|D S )a  Float range test.  This is the callback for the "within" operator
    of the UTS #35 pluralization rule language:

    >>> within_range_list(1, [(1, 3)])
    True
    >>> within_range_list(1.0, [(1, 3)])
    True
    >>> within_range_list(1.2, [(1, 4)])
    True
    >>> within_range_list(8.8, [(1, 4), (7, 15)])
    True
    >>> within_range_list(10, [(1, 4)])
    False
    >>> within_range_list(10.5, [(1, 4), (20, 30)])
    False
    c                 3   s$    | ]\}} |ko |kV  qd S r   r	   )r   min_max_r~   r	   r   r   $  s   " z$within_range_list.<locals>.<genexpr>)anyr}   r	   r   r   ro     r   ro   c                 C   s@   d}| dk r| d9 } d}|dk r|d9 }| | }|r|d9 }|S )zJavaish modulo.  This modulo operator returns the value with the sign
    of the dividend rather than the divisor like Python does:

    >>> cldr_modulo(-3, 5)
    -3
    >>> cldr_modulo(-3, -5)
    -3
    >>> cldr_modulo(3, 5)
    3
    r      r	   )abreverservr	   r	   r   rp   '  s   rp   c                   @   s   e Zd ZdZdS )	RuleErrorzRaised if a rule is malformed.N)rD   r[   r\   r]   r	   r	   r	   r   r   >  s    r   nivwftz\s+wordz)\b(and|or|is|(?:with)?in|not|mod|[{0}])\bvaluez\d+symbolz%|,|!=|=ellipsisz\.{2,3}|\u2026c                 C   s   |  dd } g }d}t| }||k rAtD ]\}}|| |}|d ur4| }|r2||| f  n	qtd| |  ||k s|d d d S )N@r   z5malformed CLDR pluralization rule.  Got unexpected %rr   )splitr   _RULESmatchendr8   groupr   )srf   posr   tokrd   r   r	   r	   r   tokenize_ruleM  s$   r   c                 C   s,   | o| d d |ko|d u p| d d |kS )Nr   r   r   r	   tokenstype_r   r	   r	   r   test_next_token`  s   r   c                 C   s   t | ||r
|  S d S r   )r   popr   r	   r	   r   
skip_tokene  s   r   c                 C   
   d| ffS )Nr   r	   )r   r	   r	   r   
value_nodej  rW   r   c                 C   s   | dfS )Nr	   r	   )namer	   r	   r   
ident_noden     r   c                 C   s   d| fS )Nr   r	   )r   r	   r	   r   range_list_noder  r   r   c                 C   r   )Nnotr	   )r   r	   r	   r   negatev  rW   r   c                   @   sb   e Zd ZdZd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S )r6   u  Internal parser.  This class can translate a single rule into an abstract
    tree of tuples. It implements the following grammar::

        condition     = and_condition ('or' and_condition)*
                        ('@integer' samples)?
                        ('@decimal' samples)?
        and_condition = relation ('and' relation)*
        relation      = is_relation | in_relation | within_relation
        is_relation   = expr 'is' ('not')? value
        in_relation   = expr (('not')? 'in' | '=' | '!=') range_list
        within_relation = expr ('not')? 'within' range_list
        expr          = operand (('mod' | '%') value)?
        operand       = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
        range_list    = (range | value) (',' range_list)*
        value         = digit+
        digit         = 0|1|2|3|4|5|6|7|8|9
        range         = value'..'value
        samples       = sampleRange (',' sampleRange)* (',' ('…'|'...'))?
        sampleRange   = decimalValue '~' decimalValue
        decimalValue  = value ('.' value)?

    - Whitespace can occur between or around any of the above tokens.
    - Rules should be mutually exclusive; for a given numeric value, only one
      rule should apply (i.e. the condition should only be true for one of
      the plural rule elements).
    - The in and within relations can take comma-separated lists, such as:
      'n in 3,5,7..15'.
    - Samples are ignored.

    The translator parses the expression on instanciation into an attribute
    called `ast`.
    c                 C   sD   t || _| jsd | _d S |  | _| jr td| jd d  d S )NzExpected end of rule, got %rr   r   )r   r   r7   	conditionr   )r9   stringr	   r	   r   r>     s   

z_Parser.__init__Nc                 C   sb   t | j||}|d ur|S |d u rt|d u r|p|}| js$td| td|| jd d f )Nz#expected %s but end of rule reachedzexpected %s but got %rr   r   )r   r   reprr   )r9   r   r   termtokenr	   r	   r   expect  s   z_Parser.expectc                 C   8   |   }t| jddrd||   ff}t| jdds|S )Nr   or)and_conditionr   r   r9   opr	   r	   r   r     
   z_Parser.conditionc                 C   r   )Nr   and)relationr   r   r   r	   r	   r   r     r   z_Parser.and_conditionc                 C   s   |   }t| jddrt| jddrdpd||  ffS t| jdd}d}t| jddr/d}nt| jddsA|r<td| |S d|||  ff}|rPt|S |S )	Nr   isr   isnotinwithinz#Cannot negate operator based rules.r   )r=   r   r   r   r   newfangled_relationr   r   )r9   leftnegatedmethodr   r	   r	   r   r     s   

z_Parser.relationc                 C   sR   t | jddr
d}nt | jddrd}ntddd||  ff}|r't|S |S )	Nr   =Fz!=Tz'Expected "=" or "!=" or legacy relationr   r   )r   r   r   r   r   )r9   r   r   r   r	   r	   r   r     s   z_Parser.newfangled_relationc                 C   s(   |   }t| jdr||   fS ||fS )Nr   )r   r   r   )r9   r   r	   r	   r   range_or_value  s   z_Parser.range_or_valuec                 C   s<   |   g}t| jddr||    t| jddst|S )Nr   ,)r   r   r   r8   r   )r9   r   r	   r	   r   r     s
   
z_Parser.range_listc                 C   s|   t | jd}|d u s|d tvrtd|d }t | jddr)d|df|  ffS t | jddr:d|df|  ffS t|S )Nr   r   zExpected identifier variablemodr	   r   %)r   r   _VARSr   r   r   )r9   r   r   r	   r	   r   r=     s   z_Parser.exprc                 C   s   t t| dd S )Nr   r   )r   r   r   rE   r	   r	   r   r     s   z_Parser.value)NN)rD   r[   r\   r]   r>   r   r   r   r   r   r   r   r=   r   r	   r	   r	   r   r6   z  s    !


r6   c                        fddS )%Compiler factory for the `_Compiler`.c                    s    |  ||  |f S r   rL   )r9   lrtmplr	   r   rQ     rx   z"_binary_compiler.<locals>.<lambda>r	   r   r	   r   r   _binary_compiler     r   c                    r   )r   c                    s    |  | S r   r   )r9   rP   r   r	   r   rQ     s    z!_unary_compiler.<locals>.<lambda>r	   r   r	   r   r   _unary_compiler  r   r   c                 C      dS )Nr   r	   rO   r	   r	   r   rQ         rQ   c                   @   s   e Zd Z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edZedZedZedZedZedZdd ZdS )	_CompilerzZThe compilers are able to transform the expressions into multiple
    output formats.
    c                 C   s   |\}}t | d| | S )Ncompile_)getattr)r9   argr   argsr	   r	   r   rL     s   z_Compiler.compilec                 C   r   )Nr   r	   rO   r	   r	   r   rQ     r   z_Compiler.<lambda>c                 C   r   )Nr    r	   rO   r	   r	   r   rQ     r   c                 C   r   )Nr&   r	   rO   r	   r	   r   rQ     r   c                 C   r   )Nr'   r	   rO   r	   r	   r   rQ     r   c                 C   r   )Nr(   r	   rO   r	   r	   r   rQ     r   c                 C   r   )Nr)   r	   rO   r	   r	   r   rQ     r   c                 C   s   t |S r   r   )rP   r&   r	   r	   r   rQ     s    z
(%s && %s)z
(%s || %s)z(!%s)z
(%s %% %s)
(%s == %s)z
(%s != %s)c                 C   s   t  r   )NotImplementedError)r9   r   r=   r   r	   r	   r   compile_relation  rU   z_Compiler.compile_relationN)rD   r[   r\   r]   rL   	compile_n	compile_i	compile_v	compile_w	compile_f	compile_tcompile_valuer   compile_and
compile_orr   compile_notcompile_mod
compile_iscompile_isnotr   r	   r	   r	   r   r     s"    r   c                   @   s8   e Zd ZdZedZedZedZedZ	dd Z
dS )	rq   z!Compiles an expression to Python.z(%s and %s)z
(%s or %s)z(not %s)zMOD(%s, %s)c                    s8   dd  fdd|d D  }d|  ||f S )Nz[%s]r   c                    s    g | ]}d t t j| qS )z(%s, %s))tuplemaprL   )r   range_rE   r	   r   rB   '  s    z4_PythonCompiler.compile_relation.<locals>.<listcomp>r   z
%s(%s, %s))r   upperrL   )r9   r   r=   r   compile_range_listr	   rE   r   r   %  s   
z _PythonCompiler.compile_relationN)rD   r[   r\   r]   r   r   r   r   r   r   r   r	   r	   r	   r   rq     s    rq   c                   @   s.   e Zd ZdZejZeZeZ	eZ
eZdd ZdS )ry   z)Compile into a gettext plural expression.c              	   C   s~   g }|  |}|d D ],}|d |d kr$|d||  |d f  qt| j |\}}|d||||f  qdd| S )Nr   r   r   z(%s >= %s && %s <= %s)z(%s)z || )rL   r8   r   r   )r9   r   r=   r   r   itemminmaxr	   r	   r   r   6  s    


z!_GettextCompiler.compile_relationN)rD   r[   r\   r]   r   r   r   compile_zeror   r   r   r   r   r	   r	   r	   r   ry   -  s    ry   c                   @   s0   e Zd ZdZdd ZeZeZeZeZ	dd Z
dS )rb   z/Compiles the expression to plain of JavaScript.c                 C   r   )NzparseInt(n, 10)r	   rO   r	   r	   r   rQ   O  r   z_JavaScriptCompiler.<lambda>c                 C   s4   t | |||}|dkr| |}d|||f }|S )Nr   z(parseInt(%s, 10) == %s && %s))ry   r   rL   )r9   r   r=   r   ru   r	   r	   r   r   U  s   
z$_JavaScriptCompiler.compile_relationN)rD   r[   r\   r]   r   r   r   r   r   r   r   r	   r	   r	   r   rb   J  s    rb   c                   @   sJ   e Zd ZdZedZedZedZedZedZ	dd Z
dd
dZdS )rK   z+Returns a unicode pluralization rule again.z%s is %sz%s is not %sz	%s and %sz%s or %sz	%s mod %sc                 C   s   | j |d ddiS )Nr   r   T)r   )r9   r   r	   r	   r   r   k  s   z_UnicodeCompiler.compile_notFc                 C   sv   g }|d D ]"}|d |d kr| | |d  q| dtt| j|  qd| ||r2dp3d|d|f S )Nr   r   z%s..%sz
%s%s %s %sz notr
   r   )r8   rL   r   r   r   )r9   r   r=   r   r   rangesr   r	   r	   r   r   n  s   
z!_UnicodeCompiler.compile_relationN)F)rD   r[   r\   r]   r   r   r   r   r   r   r   r   r	   r	   r	   r   rK   ^  s    rK   r   )&r]   rebabel._compatr   r3   rc   r*   objectr+   rg   rY   r|   rn   ro   rp   	Exceptionr   r   rL   UNICODEformatr   r   r   r   r   r   r   r   r6   r   r   r   r   rq   ry   rb   rK   r	   r	   r	   r   <module>   sN   	8](


{