Files
intellecton/venv/lib/python3.12/site-packages/babel/__pycache__/plural.cpython-312.pyc
T

260 lines
32 KiB
Plaintext
Raw Normal View History

Ë
jZã óèUdZddlmZddlZddlZddlmZmZddlm Z m
Z
m Z dZ dZ
d7dZGd „d
«Zd8d Z d9d Zd8d
Z d:dZ d:dZd;dZGdde«Zhd£Zdej2dej4«fdej2ddj7e«d«fdej2d«fdej2d«fdej2dej4«fgZded <d<d!„Z d= d>d"„Zd=d?d#„Z d@d$„Z!dAd%„Z" dBd&„Z#dCd'„Z$Gd(„d)«Z%d*„Z&d+„Z'd,„Z(Gd-„d.«Z)Gd/„d0e)«Z*Gd1„d2e)«Z+Gd3„d4e+«Z,Gd5„d6e)«Z-y)Dzœ
babel.numbers
~~~~~~~~~~~~~
CLDR Plural support. See UTS #35.
:copyright: (c) 2013-2026 by the Babel Team.
:license: BSD, see LICENSE for more details.
é)Ú annotationsN)ÚIterableÚMapping)ÚAnyÚCallableÚLiteral)ÚzeroÚoneÚtwoÚfewÚmanyÚotherrcót|«}t|«}t|t«r&||k(r|}nt j
t
|««}t|tj
«r|j«}|j}|dkr|j|dnd}djd|D««}|jd«}t|«}t|«} t|xsd«}
t|xsd«} ndx}x} x}
} dx} }
|||| |
| | |
fS)Extract operands from a decimal, a float or an int, according to `CLDR rules`_.
The result is an 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]
rÚc3ó2K|]}t|«Œy­w©Ústr)Ú.0Úds úO/home/antigravity/intellecton/venv/lib/python3.12/site-packages/babel/plural.pyú <genexpr>z#extract_operands.<locals>.<genexpr>Gsèø€Ò; aœ3˜qŸ6Ñ;ùsÚ0)
ÚabsÚintÚ
isinstanceÚfloatÚdecimalÚDecimalrÚas_tupleÚexponentÚdigitsÚjoinÚrstripÚlen)ÚsourceÚiÚ dec_tupleÚexpÚfraction_digitsÚtrailingÚ no_trailingÚes rÚextract_operandsr5sô6 ˆF‹ €AÜ ˆA‹€AÜ!”UÔØ Š6؉Aô¤ A£Ó'ˆAä!”W—_‘_Ô—J‘J“Lˆ Ø× Ñ ˆØ47¸!²G˜)×*¨3¨4шؗ7‘7Ñ;¨?ÔØ—o‘o cÓ Ü ‹MˆÜ  Ó ˆÜ 
˜AÓ ˆÜ  Ò ˜qÓ !‰àЈЈAÐ
€I€AˆØ ˆaAq˜!˜Q Ð cózeZdZdZdZd dZd
dZe dd«Ze dd«Z
e dd«Z ddZ dd „Z
dd
Zy )Ú
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Ú_funccójt|t«r|j«}t«}g|_t |«D]t\}}|t vrtd|«||vrtd|d«|j|«t|«j}|sŒX|jj||f«Œvy)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 ztag z defined twiceN) rrÚitemsÚsetr9ÚsortedÚ _plural_tagsÚ
ValueErrorÚaddÚ_ParserÚastÚappend)ÚselfÚrulesÚfoundÚkeyÚexprrCs rÚ__init__zPluralRule.__init__jô eœWÔ —K‘K“MˆE܈Ø/1ˆŒ
Ü ò 1‰IˆCØœ,Ñ  ¨wÐ!7Ó˜Ü   w¨nÐ!=Ó I‰IcŒNܘ$“-×#ˆCÚØ
×$ c¨3  1r6có|jŠdjˆfdtD««}dt|«jd|dS), c3ó<K|]}|vsŒ|d|Œy­w)z: Nr)rÚtagrFs €rrz&PluralRule.__repr__.<locals>.<genexpr>s'øèø€ÒX°CÈ3ÐRWÊ<˜C˜5  ¡: Xùsƒ ú ú>)rFr$r?ÚtypeÚ__name__)rEÚargsrFs @rÚ__repr__zPluralRule.__repr__€s@ø€Ø
ˆØy‰yÓX¼<ÔXˆØ”4˜“:×' ¨°Ð2r6có6t|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
)rr8)ÚclsrFs rÚparsezPluralRule.parse…sô eœZÔ ˆLÙ5r6có‚t«j}|jDcic]\}}|||«Œc}}Scc}}w)zŸThe `PluralRule` as a dict of unicode plural rules.
>>> rule = PluralRule({'one': 'n is 1'})
>>> rule.rules
{'one': 'n is 1'}
)Ú_UnicodeCompilerÚcompiler9)rEÚ_compilerNrCs rrFzPluralRule.rules”s7ô%×-ˆØ37·=±=×A¡x s¨CX˜c“]ÑAùÓAs¤;có:td|jD««S)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.
c3ó&K|] }|dŒ y­w)rNr)rr)s rrz"PluralRule.tags.<locals>.<genexpr>¥sèø€Ò5 !˜˜1Ñ5ùs)Ú frozensetr9©rEs rÚtagszPluralRule.tagsŸsô Ñ5 t§}¡}Ô5r6có|jSr©r9r`s rÚ __getstate__zPluralRule.__getstate__§s Ø}‰}Ðr6có||_yrrc)rEr9s rÚ __setstate__zPluralRule.__setstate__ªs Ø ˆ
r6có\t|d«st|«|_|j|«S)Nr:)ÚhasattrÚ to_pythonr:)rEr(s rÚ__call__zPluralRule.__call__­s%Üt˜" 4ˆDŒJØz‰z˜!r6N)rFz-Mapping[str, str] | Iterable[tuple[str, str]]ÚreturnÚNone)rkr)rFú:Mapping[str, str] | Iterable[tuple[str, str]] | PluralRulerkr8)rkzMapping[str, str])rkzfrozenset[str])rkúlist[tuple[str, Any]])r9rnrkrl)r(úfloat | decimal.Decimalrkr)rSÚ
__module__Ú __qualname__Ú__doc__Ú __slots__rJrUÚ classmethodrXÚpropertyrFrardrfrjrr6rr8r8Sswñð(&€Ió1ó,
ð à ð
ò óð ðòBóðBðòðór6r8có
t«j}dg}tj|«jD]"\}}|j ||«d|d«Œ$|j dt z«dj|«S)aConvert 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%r; })r)Ú_JavaScriptCompilerr[r8rXr9rDÚ
_fallback_tagr$)ÚruleÚto_jsÚresultrNrCs rÚ
to_javascriptr~³szô
Ó !× )€EØ
'€FÜ×$ *×4‰ˆˆSØ
˜s›˜  C¨ w¨cÐ
‡MM(œ]Ñ
7‰76r6c ó„ttttdœ}t «j
}ddg}t j|«jD]+\}}|jd||«dt|««Œ-|jdt«t dj|«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
)ÚINÚWITHINÚMODr5zdef evaluate(n):z- n, i, v, w, f, t, c, e = extract_operands(n)z if (z
): return z return ú
z<rule>ÚexecÚevaluate)Ú
in_range_listÚwithin_range_listÚ cldr_modulor5Ú_PythonCompilerr[r8rXr9rDrrzr$Úeval)r{Ú namespaceÚto_python_funcr}rNrCÚcodes rririÊô,ÜÜ€Iô &×.€NàØ€Fô×$ TÓKˆˆSð 
˜™n¨SÓ2°*¼SÀ»X¸LÐKð ‡MMHœ]Ð 4—9‘9˜VÓ$ h°Ó 7€D܈ˆyÔØ  Ð r6có¸tj|«}|jthz}t «j
}t Dcgc] }||vsŒ|Œ c}j}dt|«dg}|jD](\}}|j||«d||«d«Œ*|j|t«d«dj|«Scc}w)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
z nplurals=z
; plural=(rwrxz);r) r8rXrarzÚ_GettextCompilerr[r?Úindexr&r9rDr$)r{Ú used_tagsr\rNÚ
_get_indexr}rCs rÚ
to_gettextr“ôô × Ñ ˜DÓ !€Dà— ‘ œ]˜OÑ+€IÜÓ)€HÜ!-ÖB˜#°¸ Ò1A’#ÒH€Jàœ#˜i›.ÐÐ
5€FØ—M‘MòAˆˆSØ
 #›˜ s©:°c«?Ð*;¸3ÐAà
‡MM
Ó/¨rÐ
7‰76ùò
Cs Á CÁCcó:|t|«k(xr 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
)rr‡©ÚnumÚ
range_lists rr†r† sð( ”#c“(‰?Ò °jÓAr6có,tˆfd|D««S)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
c3óDK|]\}}|cxkxr|kncŒy­wrr)rÚmin_Úmax_rs €rrz$within_range_list.<locals>.<genexpr>6s"øèø€Ò@¡z t¨Tˆt"˜d×@ùsƒ )Úanyr•s` rr‡r‡"sø€ô( Ó@°ZÔ @r6cóNd}|dkr|dz}d}|dkr|dz}||z}|r|dz}|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éÿÿÿÿér)ÚreverseÚrvs rrˆrˆ9sHð€G؈1‚uØ ˆR‰ˆØˆØˆ1‚uØ ˆR‰ˆØ
ˆQ‰€BÙØ
ˆb‰ˆØ
€Ir6cóeZdZdZy)Ú RuleErrorzRaised if a rule is malformed.N)rSrprqrrrr6rPsÚ(r6>r3r4r1r)r(r2r/r0z\s+Úwordz"\b(and|or|is|(?:with)?in|not|mod|[rz])\bÚvaluez\d+Úsymbolz%|,|!=|=Úellipsisz\.{2,3}|\u2026z(list[tuple[str | None, re.Pattern[str]]]Ú_RULEScó>|jd«d}g}d}t|«}||krntD]N\}}|j||«}|Œ|j «}|r!|j ||j
«f«ntd||«||krŒn|dddS)@rz3malformed CLDR pluralization rule. Got unexpected rž)Úsplitr&ÚmatchÚendrDÚgroupr¥)Úsr}Úposr¯Útokr{s rÚ
tokenize_ruler´hØ  Q‰€AØ$&€FØ
€CÜ
ˆa&€CØ
Š)Üò ^‰IˆCØ—JJ˜q &ˆEØÑ Ø—i‘i“kÙØ—M‘M 3¨¯ © «
Ð"6Ôð
 ^ôÐQÐRSÐTWÑRXÐQ[Ð   $B$‰<Ðr6cóF|xr|dd|k(xr|duxs |dd|k(S)Nržrr©ÚtokensÚtype_r§s rÚtest_next_tokenr¹zs8ð
Ò Zf˜Rj m  Z°%¸4°-Ò2YÀ6È"Á:ÈaÁ=ÐTYÑCYÐZr6có>t|||«r|j«Syr)Úpopr¶s rÚ
skip_tokenr¼sÜv˜u eÔz‰zð-r6có d|ffS)Nr§r)s rÚ
value_noder¾sØ U Ðr6có
|dfS)Nrr)Únames rÚ
ident_noderÁs Ø ˆ8€Or6có
d|fS)Nr—r)r—s rÚrange_list_noderÃsð ˜Ð #r6có d|ffS)notr)s rÚnegaterÆsØ 2%ˆr6cóNeZdZdZdZd
dZdZdZdZdZ d „Z
d
Z d Z d Z
y)rBInternal 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 instantiation into an attribute
called `ast`.