3

X'ícQVã@sdZddlZddlZdNZdZd	d
„ZGdd„dƒZd
d„Zdd„Zdd„Z	dd„Z
dd„Zdd„ZGdd„de
ƒZdddddd d!d"hZdejd#ejƒfd$ejd%d&jeƒ›d'ƒfd(ejd)ƒfd*ejd+ƒfd,ejd-ejƒfgZd.d/„ZdOd0d1„ZdPd2d3„Zd4d5„Zd6d7„Zd8d9„Zd:d;„ZGd<d=„d=ƒZd>d?„Zd@dA„ZdBdC„ZGdDdE„dEƒZGdFdG„dGeƒZ GdHdI„dIeƒZ!GdJdK„dKe!ƒZ"GdLdM„dMeƒZ#dS)Qz°
    babel.numbers
    ~~~~~~~~~~~~~

    CLDR Plural support.  See UTS #35.

    :copyright: (c) 2013-2022 by the Babel Team.
    :license: BSD, see LICENSE for more details.
éNÚzeroÚoneÚtwoÚfewÚmanyÚothercCsÞt|ƒ}t|ƒ}t|tƒr6||kr(|}ntjt|ƒƒ}t|tjƒr²|jƒ}|j}|dkrf|j	|d…nf}dj
dd„|Dƒƒ}|jdƒ}t|ƒ}t|ƒ}	t|p dƒ}
t|p¬dƒ}nd}}	}
}d}}
||||	|
|||
fS)uöExtract operands from a decimal, a float or an int, according to `CLDR rules`_.

    The result is a 8-tuple (n, i, v, w, f, t, c, e), 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.
    c      compact decimal exponent value: exponent of the power of 10 used in compact decimal formatting.
    e      currently, synonym for ‘c’. however, may be redefined in the future.
    ====== ===============================================================

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

    :param source: A real number
    :type source: int|float|decimal.Decimal
    :return: A n-i-v-w-f-t-c-e tuple
    :rtype: tuple[decimal.Decimal, int, int, int, int, int, int, int]
    rNÚcss|]}t|ƒVqdS)N)Ústr)Ú.0Úd©rú-/tmp/pip-build-gk9425m9/babel/babel/plural.pyú	<genexpr>Asz#extract_operands.<locals>.<genexpr>Ú0)
ÚabsÚintÚ
isinstanceÚfloatÚdecimalÚDecimalr	Úas_tupleÚexponentÚdigitsÚjoinÚrstripÚlen)ÚsourceÚnÚiZ	dec_tupleÚexpZfraction_digitsZtrailingZno_trailingÚvÚwÚfÚtÚcÚerrr
Úextract_operandss&

r&c@sdeZdZdZdZdd„Zdd„Zedd	„ƒZe	d
d„ƒZ
e	dd
„ddZdd„Zdd„Z
dd„ZdS)Ú
PluralRuleafRepresents 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Ú_funccCsŽt|tƒr|jƒ}tƒ}g|_xjtt|ƒƒD]Z\}}|tkrJtd|ƒ‚n||kr^td|ƒ‚|j	|ƒt
|ƒj}|r,|jj||fƒq,WdS)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
        zunknown tag %rztag %r defined twiceN)
rÚdictÚitemsÚsetr(ÚsortedÚlistÚ_plural_tagsÚ
ValueErrorÚaddÚ_ParserÚastÚappend)ÚselfÚrulesÚfoundÚkeyÚexprr3rrr
Ú__init__ds


zPluralRule.__init__cs,|j‰dt|ƒjdj‡fdd„tDƒƒfS)Nz<%s %r>z, cs$g|]}|ˆkrd|ˆ|f‘qS)z%s: %sr)r
Útag)r6rr
ú
<listcomp>~sz'PluralRule.__repr__.<locals>.<listcomp>)r6ÚtypeÚ__name__rr/)r5r)r6r
Ú__repr__zszPluralRule.__repr__cCst||ƒ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)Úclsr6rrr
Úparse‚s
zPluralRule.parsecstƒj‰‡fdd„|jDƒS)zŸThe `PluralRule` as a dict of unicode plural rules.

        >>> rule = PluralRule({'one': 'n is 1'})
        >>> rule.rules
        {'one': 'n is 1'}
        csi|]\}}ˆ|ƒ|“qSrr)r
r;r3)Ú_compilerr
ú
<dictcomp>—sz$PluralRule.rules.<locals>.<dictcomp>)Ú_UnicodeCompilerÚcompiler()r5r)rBr
r6ŽszPluralRule.rulescCstdd„|jDƒƒS)Ncss|]}|dVqdS)rNr)r
rrrr
r™sz&PluralRule.<lambda>.<locals>.<genexpr>)Ú	frozensetr()Úxrrr
Ú<lambda>™szPluralRule.<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.)ÚdoccCs|jS)N)r()r5rrr
Ú__getstate__žszPluralRule.__getstate__cCs
||_dS)N)r()r5r(rrr
Ú__setstate__¡szPluralRule.__setstate__cCst|dƒst|ƒ|_|j|ƒS)Nr))ÚhasattrÚ	to_pythonr))r5rrrr
Ú__call__¤s

zPluralRule.__call__N)r(r))r>Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r:r?ÚclassmethodrAÚpropertyr6ÚtagsrJrKrNrrrr
r'Msr'cCsVtƒj}dg}x.tj|ƒjD]\}}|jd||ƒ|fƒqW|jdtƒdj|ƒ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)Ú_JavaScriptCompilerrEr'rAr(r4Ú
_fallback_tagr)ÚruleZto_jsÚresultr;r3rrr
Ú
to_javascriptªsrZcCs„ttttdœ}tƒj}ddg}x2tj|ƒjD]"\}}|j	d||ƒt
|ƒfƒq,W|j	dtƒtdj|ƒddƒ}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
    )ÚINZWITHINZMODr&zdef evaluate(n):z- n, i, v, w, f, t, c, e = extract_operands(n)z if (%s): return %rz
 return %rÚ
z<rule>ÚexecÚevaluate)Ú
in_range_listÚwithin_range_listÚcldr_modulor&Ú_PythonCompilerrEr'rAr(r4r	rWrÚeval)rXÚ	namespaceZto_python_funcrYr;r3Úcoderrr
rMÁs
rMcsŠtj|ƒ}|jthB‰tƒj}‡fdd„tDƒj}dtˆƒg}x,|j	D]"\}}|j
d||ƒ||ƒfƒqHW|j
d|tƒƒdj|ƒS)aThe 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
    csg|]}|ˆkr|‘qSrr)r
r;)Ú	used_tagsrr
r<÷szto_gettext.<locals>.<listcomp>znplurals=%d; plural=(z
%s ? %d : z%d);r)r'rArUrWÚ_GettextCompilerrEr/Úindexrr(r4r)rXrBZ
_get_indexrYr;r3r)rfr
Ú
to_gettextés

ricCs|t|ƒkot||ƒ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
    )rr`)ÚnumÚ
range_listrrr
r_sr_cst‡fdd„|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
    c3s"|]\}}ˆ|koˆ|kVqdS)Nr)r
Zmin_Zmax_)rjrr
r%sz$within_range_list.<locals>.<genexpr>)Úany)rjrkr)rjr
r`sr`cCs@d}|dkr|d9}d}|dkr(|d9}||}|r<|d9}|S)zîJavaish 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ééÿÿÿÿrnrnr)ÚaÚbÚreverseÚrvrrr
ra(srac@seZdZdZdS)Ú	RuleErrorzRaised if a rule is malformed.N)r>rOrPrQrrrr
rs?srsrrr r!r"r#r$r%z\s+Úwordz"\b(and|or|is|(?:with)?in|not|mod|[rz])\bÚvaluez\d+Úsymbolz%|,|!=|=Úellipsisz\.{2,3}|\u2026cCs|jdƒd}g}d}t|ƒ}xb||kr€xTtD]<\}}|j||ƒ}|dk	r.|jƒ}|rh|j||jƒfƒPq.Wtd||ƒ‚q W|ddd…S)Nú@rz5malformed CLDR pluralization rule.  Got unexpected %rrmrn)ÚsplitrÚ_RULESÚmatchÚendr4Úgrouprs)ÚsrYÚposr|ÚtokrXr{rrr
Ú
tokenize_ruleVs
rcCs,|o*|dd|ko*|dkp*|dd|kS)Nrmrrnrnr)ÚtokensÚtype_rurrr
Útest_next_tokenisr„cCst|||ƒr|jƒSdS)N)r„Úpop)r‚rƒrurrr
Ú
skip_tokennsr†cCs
d|ffS)Nrur)rurrr
Ú
value_nodessr‡cCs|ffS)Nr)Únamerrr
Ú
ident_nodewsr‰cCsd|fS)Nrkr)rkrrr
Úrange_list_node{srŠcCs
d|ffS)NÚnotr)rrrrr
ÚnegatesrŒc@sbeZdZdZdd„Zddd„Zdd„Zd	d
„Zdd„Zd
d„Z	dd„Z
dd„Zdd„Zdd„Z
dS)r2uò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`.
    cCsDt|ƒ|_|jsd|_dS|jƒ|_|jr@td|jddƒ‚dS)NzExpected end of rule, got %rrmrn)rr‚r3Ú	conditionrs)r5Ústringrrr
r:¥s

z_Parser.__init__NcCsft|j||ƒ}|dk	r|S|dkr6t|dkr0|p2|ƒ}|jsHtd|ƒ‚td||jddfƒ‚dS)Nz#expected %s but end of rule reachedzexpected %s but got %rrmrn)r†r‚Úreprrs)r5rƒruZtermÚtokenrrr
Úexpect±sz_Parser.expectcCs0|jƒ}x"t|jddƒr*d||jƒff}q
W|S)NrtÚor)Ú
and_conditionr†r‚)r5Úoprrr
r»sz_Parser.conditioncCs0|jƒ}x"t|jddƒr*d||jƒff}q
W|S)NrtÚand)Úrelationr†r‚)r5r”rrr
r“Ász_Parser.and_conditioncCs¤|jƒ}t|jddƒr8t|jddƒr(dp*d||jƒffSt|jddƒ}d}t|jddƒr^d}n$t|jddƒs‚|rxtdƒ‚|j|ƒSd|||jƒff}|r t|ƒS|S)	NrtÚisr‹ZisnotÚinZwithinz#Cannot negate operator based rules.r–)r9r†r‚rursÚnewfangled_relationrkrŒ)r5ÚleftÚnegatedÚmethodrrrrr
r–Çs
z_Parser.relationcCsRt|jddƒrd}nt|jddƒr(d}ntdƒ‚dd||jƒff}|rNt|ƒS|S)	Nrvú=Fz!=Tz'Expected "=" or "!=" or legacy relationr–r˜)r†r‚rsrkrŒ)r5ršr›rrrrr
r™Øsz_Parser.newfangled_relationcCs,|jƒ}t|jdƒr ||jƒfS||fSdS)Nrw)rur†r‚)r5ršrrr
Úrange_or_valueâsz_Parser.range_or_valuecCs4|jƒg}x t|jddƒr*|j|jƒƒqWt|ƒS)Nrvú,)ržr†r‚r4rŠ)r5rkrrr
rkés
z_Parser.range_listcCs|t|jdƒ}|dks |dtkr(tdƒ‚|d}t|jddƒrRd|ff|jƒffSt|jddƒrtd|ff|jƒffSt|ƒS)NrtrmzExpected identifier variableÚmodrvú%)r†r‚Ú_VARSrsrur‰)r5rtrˆrrr
r9ïsz_Parser.exprcCstt|jdƒdƒƒS)Nrurm)r‡rr‘)r5rrr
ruúsz
_Parser.value)NN)r>rOrPrQr:r‘rr“r–r™ržrkr9rurrrr
r2ƒs 


r2cs‡fdd„S)z%Compiler factory for the `_Compiler`.csˆ|j|ƒ|j|ƒfS)N)rE)r5ÚlÚr)Útmplrr
rHsz"_binary_compiler.<locals>.<lambda>r)r¥r)r¥r
Ú_binary_compilerþsr¦cs‡fdd„S)z%Compiler factory for the `_Compiler`.csˆ|j|ƒS)N)rE)r5rG)r¥rr
rHsz!_unary_compiler.<locals>.<lambda>r)r¥r)r¥r
Ú_unary_compilersr§cCsdS)Nrr)rGrrr
rHsrHc@s˜eZdZdZdd„Zdd„Zdd„Zdd„Zdd„Zd	d„Z	d
d„Z
dd„Zdd„Zd
d„Z
edƒZedƒZedƒZedƒZedƒZedƒZdd„ZdS)Ú	_CompilerzZThe compilers are able to transform the expressions into multiple
    output formats.
    cCs|\}}t|d|ƒ|ŽS)NZcompile_)Úgetattr)r5Úargr”Úargsrrr
rEsz_Compiler.compilecCsdS)Nrr)rGrrr
rHsz_Compiler.<lambda>cCsdS)Nrr)rGrrr
rHscCsdS)Nr r)rGrrr
rHscCsdS)Nr!r)rGrrr
rHscCsdS)Nr"r)rGrrr
rHscCsdS)Nr#r)rGrrr
rHscCsdS)Nr$r)rGrrr
rHscCsdS)Nr%r)rGrrr
rHscCst|ƒS)N)r	)rGr rrr
rHsz
(%s && %s)z
(%s || %s)z(!%s)z
(%s %% %s)z
(%s == %s)z
(%s != %s)cCs
tƒ‚dS)N)ÚNotImplementedError)r5rœr9rkrrr
Úcompile_relation$sz_Compiler.compile_relationN)r>rOrPrQrEÚ	compile_nÚ	compile_iÚ	compile_vÚ	compile_wÚ	compile_fÚ	compile_tZ	compile_cZ	compile_eZ
compile_valuer¦Úcompile_andÚ
compile_orr§Úcompile_notÚcompile_modÚ
compile_isÚ
compile_isnotr­rrrr
r¨s$r¨c@s8eZdZdZedƒZedƒZedƒZedƒZ	dd„Z
dS)	rbz!Compiles an expression to Python.z(%s and %s)z
(%s or %s)z(not %s)zMOD(%s, %s)cs8ddj‡fdd„|dDƒƒ}d|jƒˆj|ƒ|fS)Nz[%s]rŸcs g|]}dttˆj|ƒƒ‘qS)z(%s, %s))ÚtupleÚmaprE)r
Zrange_)r5rr
r<2sz4_PythonCompiler.compile_relation.<locals>.<listcomp>rmz
%s(%s, %s))rÚupperrE)r5rœr9rkZcompile_range_listr)r5r
r­0s

z _PythonCompiler.compile_relationN)r>rOrPrQr¦r´rµr§r¶r·r­rrrr
rb(srbc@s.eZdZdZejZeZeZ	eZ
eZdd„ZdS)rgz)Compile into a gettext plural expression.cCs‚g}|j|ƒ}xd|dD]X}|d|dkrJ|jd||j|dƒfƒqt|j|ƒ\}}|jd||||fƒqWddj|ƒS)Nrmrz
(%s == %s)z(%s >= %s && %s <= %s)z(%s)z || )rEr4r»r)r5rœr9rkrrÚitemÚminÚmaxrrr
r­As
z!_GettextCompiler.compile_relationN)
r>rOrPrQr¨r®r¯Úcompile_zeror°r±r²r³r­rrrr
rg8srgc@s0eZdZdZdd„ZeZeZeZeZ	dd„Z
dS)rVz/Compiles the expression to plain of JavaScript.cCsdS)NzparseInt(n, 10)r)rGrrr
rHZsz_JavaScriptCompiler.<lambda>cCs4tj||||ƒ}|dkr0|j|ƒ}d|||f}|S)Nr˜z(parseInt(%s, 10) == %s && %s))rgr­rE)r5rœr9rkrerrr
r­`s
z$_JavaScriptCompiler.compile_relationN)r>rOrPrQr¯rÀr°r±r²r³r­rrrr
rVUsrVc@sJeZdZdZedƒZedƒZedƒZedƒZedƒZ	dd„Z
d
d
d„ZdS)rDz+Returns a unicode pluralization rule again.z%s is %sz%s is not %sz	%s and %sz%s or %sz	%s mod %scCs|j|dddiŽS)Nrmr›T)r­)r5r–rrr
r¶vsz_UnicodeCompiler.compile_notFcCszg}xP|dD]D}|d|dkr8|j|j|dƒƒq|jdtt|j|ƒƒƒqWd|j|ƒ|rhdpjd|dj|ƒfS)Nrmrz%s..%sz
%s%s %s %sz notrrŸ)r4rErºr»r)r5rœr9rkr›Úrangesr½rrr
r­ysz!_UnicodeCompiler.compile_relationN)F)r>rOrPrQr¦r¸r¹r´rµr·r¶r­rrrr
rDisrD)rrrrrr)N)N)$rQrÚrer/rWr&r'rZrMrir_r`raÚ	Exceptionrsr¢rEÚUNICODErrzrr„r†r‡r‰rŠrŒr2r¦r§rÀr¨rbrgrVrDrrrr
Ú<module>	sT;](

{