Mercurial > babel > old > babel-test
annotate babel/plural.py @ 530:85e1beadacb0
Update the copyright line.
author | jruigrok |
---|---|
date | Sat, 05 Mar 2011 15:22:28 +0000 |
parents | eef19ada4296 |
children |
rev | line source |
---|---|
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
1 # -*- coding: utf-8 -*- |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
2 # |
530 | 3 # Copyright (C) 2008-2011 Edgewall Software |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
4 # All rights reserved. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
5 # |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
6 # This software is licensed as described in the file COPYING, which |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
7 # you should have received as part of this distribution. The terms |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
8 # are also available at http://babel.edgewall.org/wiki/License. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
9 # |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
10 # This software consists of voluntary contributions made by many |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
11 # individuals. For the exact contribution history, see the revision |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
12 # history and logs, available at http://babel.edgewall.org/log/. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
13 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
14 """CLDR Plural support. See UTS #35. EXPERIMENTAL""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
15 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
16 import re |
414
ea0da9db79ef
fix Python 2.3 compat: rearrange set/itemgetter/rsplit/sorted/unicode.decode
pjenvey
parents:
411
diff
changeset
|
17 |
411 | 18 __all__ = ['PluralRule', 'RuleError', 'to_gettext', 'to_javascript', |
19 'to_python'] | |
20 __docformat__ = 'restructuredtext en' | |
21 | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
22 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
23 _plural_tags = ('zero', 'one', 'two', 'few', 'many', 'other') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
24 _fallback_tag = 'other' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
25 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
26 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
27 class PluralRule(object): |
411 | 28 """Represents a set of language pluralization rules. The constructor |
29 accepts a list of (tag, expr) tuples or a dict of CLDR rules. The | |
30 resulting object is callable and accepts one parameter with a positive or | |
31 negative number (both integer and float) for the number that indicates the | |
32 plural form for a string and returns the tag for the format: | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
33 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
34 >>> rule = PluralRule({'one': 'n is 1'}) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
35 >>> rule(1) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
36 'one' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
37 >>> rule(2) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
38 'other' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
39 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
40 Currently the CLDR defines these tags: zero, one, two, few, many and |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
41 other where other is an implicit default. Rules should be mutually |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
42 exclusive; for a given numeric value, only one rule should apply (i.e. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
43 the condition should only be true for one of the plural rule elements. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
44 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
45 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
46 __slots__ = ('abstract', '_func') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
47 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
48 def __init__(self, rules): |
411 | 49 """Initialize the rule instance. |
50 | |
51 :param rules: a list of ``(tag, expr)``) tuples with the rules | |
52 conforming to UTS #35 or a dict with the tags as keys | |
53 and expressions as values. | |
54 :raise RuleError: if the expression is malformed | |
55 """ | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
56 if isinstance(rules, dict): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
57 rules = rules.items() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
58 found = set() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
59 self.abstract = [] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
60 for key, expr in rules: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
61 if key not in _plural_tags: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
62 raise ValueError('unknown tag %r' % key) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
63 elif key in found: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
64 raise ValueError('tag %r defined twice' % key) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
65 found.add(key) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
66 self.abstract.append((key, _Parser(expr).ast)) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
67 |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
387
diff
changeset
|
68 def __repr__(self): |
393 | 69 rules = self.rules |
70 return '<%s %r>' % ( | |
71 type(self).__name__, | |
72 ', '.join(['%s: %s' % (tag, rules[tag]) for tag in _plural_tags | |
73 if tag in rules]) | |
74 ) | |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
387
diff
changeset
|
75 |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
76 def parse(cls, rules): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
77 """Create a `PluralRule` instance for the given rules. If the rules |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
78 are a `PluralRule` object, that object is returned. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
79 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
80 :param rules: the rules as list or dict, or a `PluralRule` object |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
81 :return: a corresponding `PluralRule` object |
410 | 82 :raise Ruleerror: if the expression is malformed |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
83 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
84 if isinstance(rules, cls): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
85 return rules |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
86 return cls(rules) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
87 parse = classmethod(parse) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
88 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
89 def rules(self): |
411 | 90 """The `PluralRule` as a dict of unicode plural rules. |
91 | |
92 >>> rule = PluralRule({'one': 'n is 1'}) | |
93 >>> rule.rules | |
94 {'one': 'n is 1'} | |
95 """ | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
96 _compile = _UnicodeCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
97 return dict([(tag, _compile(ast)) for tag, ast in self.abstract]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
98 rules = property(rules, doc=rules.__doc__) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
99 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
100 tags = property(lambda x: frozenset([i[0] for i in x.abstract]), doc=""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
101 A set of explicitly defined tags in this rule. The implicit default |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
102 ``'other'`` rules is not part of this set unless there is an explicit |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
103 rule for it.""") |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
104 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
105 def __getstate__(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
106 return self.abstract |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
107 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
108 def __setstate__(self, abstract): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
109 self.abstract = abstract |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
110 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
111 def __call__(self, n): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
112 if not hasattr(self, '_func'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
113 self._func = to_python(self) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
114 return self._func(n) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
115 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
116 |
387 | 117 def to_javascript(rule): |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
118 """Convert a list/dict of rules or a `PluralRule` object into a JavaScript |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
119 function. This function depends on no external library: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
120 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
121 >>> to_javascript({'one': 'n is 1'}) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
122 "(function(n) { return (n == 1) ? 'one' : 'other'; })" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
123 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
124 Implementation detail: The function generated will probably evaluate |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
125 expressions involved into range operations multiple times. This has the |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
126 advantage that external helper functions are not required and is not a |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
127 big performance hit for these simple calculations. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
128 |
411 | 129 :param rule: the rules as list or dict, or a `PluralRule` object |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
130 :return: a corresponding JavaScript function as `str` |
410 | 131 :raise RuleError: if the expression is malformed |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
132 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
133 to_js = _JavaScriptCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
134 result = ['(function(n) { return '] |
387 | 135 for tag, ast in PluralRule.parse(rule).abstract: |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
136 result.append('%s ? %r : ' % (to_js(ast), tag)) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
137 result.append('%r; })' % _fallback_tag) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
138 return ''.join(result) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
139 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
140 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
141 def to_python(rule): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
142 """Convert a list/dict of rules or a `PluralRule` object into a regular |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
143 Python function. This is useful in situations where you need a real |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
144 function and don't are about the actual rule object: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
145 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
146 >>> func = to_python({'one': 'n is 1', 'few': 'n in 2..4'}) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
147 >>> func(1) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
148 'one' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
149 >>> func(3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
150 'few' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
151 |
411 | 152 :param rule: the rules as list or dict, or a `PluralRule` object |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
153 :return: a corresponding Python function |
410 | 154 :raise RuleError: if the expression is malformed |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
155 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
156 namespace = { |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
157 'IN': in_range, |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
158 'WITHIN': within_range, |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
159 'MOD': cldr_modulo |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
160 } |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
161 to_python = _PythonCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
162 result = ['def evaluate(n):'] |
411 | 163 for tag, ast in PluralRule.parse(rule).abstract: |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
164 result.append(' if (%s): return %r' % (to_python(ast), tag)) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
165 result.append(' return %r' % _fallback_tag) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
166 exec '\n'.join(result) in namespace |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
167 return namespace['evaluate'] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
168 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
169 |
387 | 170 def to_gettext(rule): |
171 """The plural rule as gettext expression. The gettext expression is | |
172 technically limited to integers and returns indices rather than tags. | |
173 | |
174 >>> to_gettext({'one': 'n is 1', 'two': 'n is 2'}) | |
175 'nplurals=3; plural=((n == 2) ? 1 : (n == 1) ? 0 : 2)' | |
411 | 176 |
177 :param rule: the rules as list or dict, or a `PluralRule` object | |
178 :return: an equivalent gettext-style plural expression | |
179 :raise RuleError: if the expression is malformed | |
387 | 180 """ |
411 | 181 rule = PluralRule.parse(rule) |
182 | |
183 used_tags = rule.tags | set([_fallback_tag]) | |
184 _compile = _GettextCompiler().compile | |
185 _get_index = [tag for tag in _plural_tags if tag in used_tags].index | |
186 | |
187 result = ['nplurals=%d; plural=(' % len(used_tags)] | |
188 for tag, ast in rule.abstract: | |
189 result.append('%s ? %d : ' % (_compile(ast), _get_index(tag))) | |
190 result.append('%d)' % _get_index(_fallback_tag)) | |
191 return ''.join(result) | |
387 | 192 |
193 | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
194 def in_range(num, min, max): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
195 """Integer range test. This is the callback for the "in" operator |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
196 of the UTS #35 pluralization rule language: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
197 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
198 >>> in_range(1, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
199 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
200 >>> in_range(3, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
201 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
202 >>> in_range(1.2, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
203 False |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
204 >>> in_range(10, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
205 False |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
206 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
207 return num == int(num) and within_range(num, min, max) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
208 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
209 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
210 def within_range(num, min, max): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
211 """Float range test. This is the callback for the "within" operator |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
212 of the UTS #35 pluralization rule language: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
213 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
214 >>> within_range(1, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
215 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
216 >>> within_range(1.0, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
217 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
218 >>> within_range(1.2, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
219 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
220 >>> within_range(10, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
221 False |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
222 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
223 return num >= min and num <= max |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
224 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
225 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
226 def cldr_modulo(a, b): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
227 """Javaish modulo. This modulo operator returns the value with the sign |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
228 of the dividend rather than the divisor like Python does: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
229 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
230 >>> cldr_modulo(-3, 5) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
231 -3 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
232 >>> cldr_modulo(-3, -5) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
233 -3 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
234 >>> cldr_modulo(3, 5) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
235 3 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
236 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
237 reverse = 0 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
238 if a < 0: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
239 a *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
240 reverse = 1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
241 if b < 0: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
242 b *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
243 rv = a % b |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
244 if reverse: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
245 rv *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
246 return rv |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
247 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
248 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
249 class RuleError(Exception): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
250 """Raised if a rule is malformed.""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
251 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
252 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
253 class _Parser(object): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
254 """Internal parser. This class can translate a single rule into an abstract |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
255 tree of tuples. It implements the following grammar:: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
256 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
257 condition = and_condition ('or' and_condition)* |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
258 and_condition = relation ('and' relation)* |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
259 relation = is_relation | in_relation | within_relation | 'n' <EOL> |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
260 is_relation = expr 'is' ('not')? value |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
261 in_relation = expr ('not')? 'in' range |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
262 within_relation = expr ('not')? 'within' range |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
263 expr = 'n' ('mod' value)? |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
264 value = digit+ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
265 digit = 0|1|2|3|4|5|6|7|8|9 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
266 range = value'..'value |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
267 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
268 - Whitespace can occur between or around any of the above tokens. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
269 - Rules should be mutually exclusive; for a given numeric value, only one |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
270 rule should apply (i.e. the condition should only be true for one of |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
271 the plural rule elements. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
272 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
273 The translator parses the expression on instanciation into an attribute |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
274 called `ast`. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
275 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
276 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
277 _rules = [ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
278 (None, re.compile(r'\s+(?u)')), |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
279 ('word', re.compile(r'\b(and|or|is|(?:with)?in|not|mod|n)\b')), |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
280 ('value', re.compile(r'\d+')), |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
281 ('ellipsis', re.compile(r'\.\.')) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
282 ] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
283 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
284 def __init__(self, string): |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
387
diff
changeset
|
285 string = string.lower() |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
286 result = [] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
287 pos = 0 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
288 end = len(string) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
289 while pos < end: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
290 for tok, rule in self._rules: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
291 match = rule.match(string, pos) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
292 if match is not None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
293 pos = match.end() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
294 if tok: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
295 result.append((tok, match.group())) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
296 break |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
297 else: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
298 raise RuleError('malformed CLDR pluralization rule. ' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
299 'Got unexpected %r' % string[pos]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
300 self.tokens = result[::-1] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
301 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
302 self.ast = self.condition() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
303 if self.tokens: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
304 raise RuleError('Expected end of rule, got %r' % |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
305 self.tokens[-1][1]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
306 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
307 def test(self, type, value=None): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
308 return self.tokens and self.tokens[-1][0] == type and \ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
309 (value is None or self.tokens[-1][1] == value) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
310 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
311 def skip(self, type, value=None): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
312 if self.test(type, value): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
313 return self.tokens.pop() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
314 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
315 def expect(self, type, value=None, term=None): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
316 token = self.skip(type, value) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
317 if token is not None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
318 return token |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
319 if term is None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
320 term = repr(value is None and type or value) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
321 if not self.tokens: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
322 raise RuleError('expected %s but end of rule reached' % term) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
323 raise RuleError('expected %s but got %r' % (term, self.tokens[-1][1])) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
324 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
325 def condition(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
326 op = self.and_condition() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
327 while self.skip('word', 'or'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
328 op = 'or', (op, self.and_condition()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
329 return op |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
330 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
331 def and_condition(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
332 op = self.relation() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
333 while self.skip('word', 'and'): |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
387
diff
changeset
|
334 op = 'and', (op, self.relation()) |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
335 return op |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
336 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
337 def relation(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
338 left = self.expr() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
339 if self.skip('word', 'is'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
340 return self.skip('word', 'not') and 'isnot' or 'is', \ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
341 (left, self.value()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
342 negated = self.skip('word', 'not') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
343 method = 'in' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
344 if self.skip('word', 'within'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
345 method = 'within' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
346 else: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
347 self.expect('word', 'in', term="'within' or 'in'") |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
348 rv = 'relation', (method, left, self.range()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
349 if negated: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
350 rv = 'not', (rv,) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
351 return rv |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
352 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
353 def range(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
354 left = self.value() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
355 self.expect('ellipsis') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
356 return 'range', (left, self.value()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
357 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
358 def expr(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
359 self.expect('word', 'n') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
360 if self.skip('word', 'mod'): |
391
3eb859adc5de
Fixed a bug in plural.py that caused a traceback for some locales, changed the `__mod__` DateTimePattern to not raise exceptions but return NotImplemented.
aronacher
parents:
390
diff
changeset
|
361 return 'mod', (('n', ()), self.value()) |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
362 return 'n', () |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
363 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
364 def value(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
365 return 'value', (int(self.expect('value')[1]),) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
366 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
367 |
387 | 368 def _binary_compiler(tmpl): |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
369 """Compiler factory for the `_Compiler`.""" |
387 | 370 return lambda self, l, r: tmpl % (self.compile(l), self.compile(r)) |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
371 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
372 |
392 | 373 def _unary_compiler(tmpl): |
374 """Compiler factory for the `_Compiler`.""" | |
375 return lambda self, x: tmpl % self.compile(x) | |
376 | |
377 | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
378 class _Compiler(object): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
379 """The compilers are able to transform the expressions into multiple |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
380 output formats. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
381 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
382 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
383 def compile(self, (op, args)): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
384 return getattr(self, 'compile_' + op)(*args) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
385 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
386 compile_n = lambda x: 'n' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
387 compile_value = lambda x, v: str(v) |
387 | 388 compile_and = _binary_compiler('(%s && %s)') |
389 compile_or = _binary_compiler('(%s || %s)') | |
392 | 390 compile_not = _unary_compiler('(!%s)') |
387 | 391 compile_mod = _binary_compiler('(%s %% %s)') |
392 compile_is = _binary_compiler('(%s == %s)') | |
393 compile_isnot = _binary_compiler('(%s != %s)') | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
394 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
395 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
396 range = '%s, %s' % tuple(map(self.compile, range[1])) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
397 return '%s(%s, %s)' % (method.upper(), self.compile(expr), range) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
398 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
399 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
400 class _PythonCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
401 """Compiles an expression to Python.""" |
387 | 402 |
403 compile_and = _binary_compiler('(%s and %s)') | |
404 compile_or = _binary_compiler('(%s or %s)') | |
392 | 405 compile_not = _unary_compiler('(not %s)') |
387 | 406 compile_mod = _binary_compiler('MOD(%s, %s)') |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
407 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
408 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
409 class _GettextCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
410 """Compile into a gettext plural expression.""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
411 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
412 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
413 expr = self.compile(expr) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
414 min, max = map(self.compile, range[1]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
415 return '(%s >= %s && %s <= %s)' % (expr, min, expr, max) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
416 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
417 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
418 class _JavaScriptCompiler(_GettextCompiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
419 """Compiles the expression to plain of JavaScript.""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
420 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
421 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
422 code = _GettextCompiler.compile_relation(self, method, expr, range) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
423 if method == 'in': |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
424 expr = self.compile(expr) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
425 code = '(parseInt(%s) == %s && %s)' % (expr, expr, code) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
426 return code |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
427 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
428 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
429 class _UnicodeCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
430 """Returns a unicode pluralization rule again.""" |
387 | 431 |
432 compile_is = _binary_compiler('%s is %s') | |
433 compile_isnot = _binary_compiler('%s is not %s') | |
434 compile_and = _binary_compiler('%s and %s') | |
435 compile_or = _binary_compiler('%s or %s') | |
436 compile_mod = _binary_compiler('%s mod %s') | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
437 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
438 def compile_not(self, relation): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
439 return self.compile_relation(negated=True, *relation[1]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
440 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
441 def compile_relation(self, method, expr, range, negated=False): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
442 return '%s%s %s %s' % ( |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
443 self.compile(expr), negated and ' not' or '', |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
444 method, '%s..%s' % tuple(map(self.compile, range[1])) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
445 ) |