Mercurial > babel > old > babel-test
annotate babel/plural.py @ 392:2e77d72516d7
Fixed not in plural rules
author | aronacher |
---|---|
date | Tue, 15 Jul 2008 10:13:55 +0000 |
parents | 3eb859adc5de |
children | d85b5a78ee9c |
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 # |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
3 # Copyright (C) 2008 Edgewall Software |
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 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
17 try: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
18 set |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
19 except NameError: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
20 from sets import ImmutableSet as frozenset, Set as set |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
21 |
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): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
28 """Represents a CLDR language pluralization rules. The constructors |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
29 accepts a list of (tag, expr) tuples or a dict of CLDR rules. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
30 The resulting object is callable and accepts one parameter with a |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
31 positive or negative number (both integer and float) for the number |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
32 that indicates the plural form for a string and returns the tag for |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
33 the format: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
34 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
35 >>> rule = PluralRule({'one': 'n is 1'}) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
36 >>> rule(1) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
37 'one' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
38 >>> rule(2) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
39 'other' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
40 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
41 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
|
42 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
|
43 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
|
44 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
|
45 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
46 :param rules: a list of ``(tag, expr)``) tuples with the rules conforming |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
47 to UTS #35 or a dict with the tags as keys and expressions |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
48 as values. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
49 :raise: a `RuleError` if the expression is malformed |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
50 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
51 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
52 __slots__ = ('abstract', '_func') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
53 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
54 def __init__(self, rules): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
55 if isinstance(rules, dict): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
56 rules = rules.items() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
57 found = set() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
58 self.abstract = [] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
59 for key, expr in rules: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
60 if key not in _plural_tags: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
61 raise ValueError('unknown tag %r' % key) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
62 elif key in found: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
63 raise ValueError('tag %r defined twice' % key) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
64 found.add(key) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
65 self.abstract.append((key, _Parser(expr).ast)) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
66 |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
387
diff
changeset
|
67 def __repr__(self): |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
387
diff
changeset
|
68 return '<%s %r>' % (type(self).__name__, self.abstract) |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
387
diff
changeset
|
69 |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
70 def parse(cls, rules): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
71 """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
|
72 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
|
73 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
74 :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
|
75 :return: a corresponding `PluralRule` object |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
76 :raise: a `RuleError` if the expression is malformed |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
77 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
78 if isinstance(rules, cls): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
79 return rules |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
80 return cls(rules) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
81 parse = classmethod(parse) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
82 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
83 def rules(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
84 """The `PluralRule` as a dict of unicode plural rules.""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
85 _compile = _UnicodeCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
86 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
|
87 rules = property(rules, doc=rules.__doc__) |
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 gettext_expr(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
90 """The plural rule as gettext expression. The gettext expression is |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
91 technically limited to integers and returns indices rather than tags. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
92 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
93 >>> PluralRule({'one': 'n is 1', 'two': 'n is 2'}).gettext_expr |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
94 'nplurals=3; plural=((n == 2) ? 1 : (n == 1) ? 0 : 2)' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
95 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
96 used_tags = self.tags | set([_fallback_tag]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
97 _compile = _GettextCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
98 _get_index = [tag for tag in _plural_tags if tag in used_tags].index |
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 result = ['nplurals=%d; plural=(' % len(used_tags)] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
101 for tag, ast in self.abstract: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
102 result.append('%s ? %d : ' % (_compile(ast), _get_index(tag))) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
103 result.append('%d)' % _get_index(_fallback_tag)) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
104 return ''.join(result) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
105 gettext_expr = property(gettext_expr, doc=gettext_expr.__doc__) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
106 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
107 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
|
108 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
|
109 ``'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
|
110 rule for it.""") |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
111 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
112 def __getstate__(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
113 return self.abstract |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
114 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
115 def __setstate__(self, abstract): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
116 self.abstract = abstract |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
117 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
118 def __call__(self, n): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
119 if not hasattr(self, '_func'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
120 self._func = to_python(self) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
121 return self._func(n) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
122 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
123 |
387 | 124 def to_javascript(rule): |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
125 """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
|
126 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
|
127 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
128 >>> to_javascript({'one': 'n is 1'}) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
129 "(function(n) { return (n == 1) ? 'one' : 'other'; })" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
130 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
131 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
|
132 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
|
133 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
|
134 big performance hit for these simple calculations. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
135 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
136 :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
|
137 :return: a corresponding JavaScript function as `str` |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
138 :raise: a `RuleError` if the expression is malformed |
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 to_js = _JavaScriptCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
141 result = ['(function(n) { return '] |
387 | 142 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
|
143 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
|
144 result.append('%r; })' % _fallback_tag) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
145 return ''.join(result) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
146 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
147 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
148 def to_python(rule): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
149 """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
|
150 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
|
151 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
|
152 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
153 >>> 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
|
154 >>> func(1) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
155 'one' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
156 >>> func(3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
157 'few' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
158 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
159 :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
|
160 :return: a corresponding Python function |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
161 :raise: a `RuleError` if the expression is malformed |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
162 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
163 namespace = { |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
164 'IN': in_range, |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
165 'WITHIN': within_range, |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
166 'MOD': cldr_modulo |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
167 } |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
168 to_python = _PythonCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
169 result = ['def evaluate(n):'] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
170 for tag, ast in rule.abstract: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
171 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
|
172 result.append(' return %r' % _fallback_tag) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
173 exec '\n'.join(result) in namespace |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
174 return namespace['evaluate'] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
175 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
176 |
387 | 177 def to_gettext(rule): |
178 """The plural rule as gettext expression. The gettext expression is | |
179 technically limited to integers and returns indices rather than tags. | |
180 | |
181 >>> to_gettext({'one': 'n is 1', 'two': 'n is 2'}) | |
182 'nplurals=3; plural=((n == 2) ? 1 : (n == 1) ? 0 : 2)' | |
183 """ | |
184 return PluralRule.parse(rule).gettext_expr | |
185 | |
186 | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
187 def in_range(num, min, max): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
188 """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
|
189 of the UTS #35 pluralization rule language: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
190 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
191 >>> in_range(1, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
192 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
193 >>> in_range(3, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
194 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
195 >>> in_range(1.2, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
196 False |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
197 >>> in_range(10, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
198 False |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
199 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
200 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
|
201 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
202 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
203 def within_range(num, min, max): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
204 """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
|
205 of the UTS #35 pluralization rule language: |
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 >>> within_range(1, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
208 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
209 >>> within_range(1.0, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
210 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
211 >>> within_range(1.2, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
212 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
213 >>> within_range(10, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
214 False |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
215 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
216 return num >= min and num <= max |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
217 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
218 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
219 def cldr_modulo(a, b): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
220 """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
|
221 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
|
222 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
223 >>> cldr_modulo(-3, 5) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
224 -3 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
225 >>> cldr_modulo(-3, -5) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
226 -3 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
227 >>> cldr_modulo(3, 5) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
228 3 |
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 reverse = 0 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
231 if a < 0: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
232 a *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
233 reverse = 1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
234 if b < 0: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
235 b *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
236 rv = a % b |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
237 if reverse: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
238 rv *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
239 return rv |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
240 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
241 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
242 class RuleError(Exception): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
243 """Raised if a rule is malformed.""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
244 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
245 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
246 class _Parser(object): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
247 """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
|
248 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
|
249 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
250 condition = and_condition ('or' and_condition)* |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
251 and_condition = relation ('and' relation)* |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
252 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
|
253 is_relation = expr 'is' ('not')? value |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
254 in_relation = expr ('not')? 'in' range |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
255 within_relation = expr ('not')? 'within' range |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
256 expr = 'n' ('mod' value)? |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
257 value = digit+ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
258 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
|
259 range = value'..'value |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
260 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
261 - 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
|
262 - 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
|
263 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
|
264 the plural rule elements. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
265 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
266 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
|
267 called `ast`. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
268 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
269 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
270 _rules = [ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
271 (None, re.compile(r'\s+(?u)')), |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
272 ('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
|
273 ('value', re.compile(r'\d+')), |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
274 ('ellipsis', re.compile(r'\.\.')) |
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 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
|
278 string = string.lower() |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
279 result = [] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
280 pos = 0 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
281 end = len(string) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
282 while pos < end: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
283 for tok, rule in self._rules: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
284 match = rule.match(string, pos) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
285 if match is not None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
286 pos = match.end() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
287 if tok: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
288 result.append((tok, match.group())) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
289 break |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
290 else: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
291 raise RuleError('malformed CLDR pluralization rule. ' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
292 'Got unexpected %r' % string[pos]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
293 self.tokens = result[::-1] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
294 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
295 self.ast = self.condition() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
296 if self.tokens: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
297 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
|
298 self.tokens[-1][1]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
299 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
300 def test(self, type, value=None): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
301 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
|
302 (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
|
303 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
304 def skip(self, type, value=None): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
305 if self.test(type, value): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
306 return self.tokens.pop() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
307 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
308 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
|
309 token = self.skip(type, value) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
310 if token is not None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
311 return token |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
312 if term is None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
313 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
|
314 if not self.tokens: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
315 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
|
316 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
|
317 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
318 def condition(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
319 op = self.and_condition() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
320 while self.skip('word', 'or'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
321 op = 'or', (op, self.and_condition()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
322 return op |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
323 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
324 def and_condition(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
325 op = self.relation() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
326 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
|
327 op = 'and', (op, self.relation()) |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
328 return op |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
329 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
330 def relation(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
331 left = self.expr() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
332 if self.skip('word', 'is'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
333 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
|
334 (left, self.value()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
335 negated = self.skip('word', 'not') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
336 method = 'in' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
337 if self.skip('word', 'within'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
338 method = 'within' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
339 else: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
340 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
|
341 rv = 'relation', (method, left, self.range()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
342 if negated: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
343 rv = 'not', (rv,) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
344 return rv |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
345 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
346 def range(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
347 left = self.value() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
348 self.expect('ellipsis') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
349 return 'range', (left, self.value()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
350 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
351 def expr(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
352 self.expect('word', 'n') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
353 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
|
354 return 'mod', (('n', ()), self.value()) |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
355 return 'n', () |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
356 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
357 def value(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
358 return 'value', (int(self.expect('value')[1]),) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
359 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
360 |
387 | 361 def _binary_compiler(tmpl): |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
362 """Compiler factory for the `_Compiler`.""" |
387 | 363 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
|
364 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
365 |
392 | 366 def _unary_compiler(tmpl): |
367 """Compiler factory for the `_Compiler`.""" | |
368 return lambda self, x: tmpl % self.compile(x) | |
369 | |
370 | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
371 class _Compiler(object): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
372 """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
|
373 output formats. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
374 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
375 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
376 def compile(self, (op, args)): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
377 return getattr(self, 'compile_' + op)(*args) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
378 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
379 compile_n = lambda x: 'n' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
380 compile_value = lambda x, v: str(v) |
387 | 381 compile_and = _binary_compiler('(%s && %s)') |
382 compile_or = _binary_compiler('(%s || %s)') | |
392 | 383 compile_not = _unary_compiler('(!%s)') |
387 | 384 compile_mod = _binary_compiler('(%s %% %s)') |
385 compile_is = _binary_compiler('(%s == %s)') | |
386 compile_isnot = _binary_compiler('(%s != %s)') | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
387 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
388 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
389 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
|
390 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
|
391 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
392 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
393 class _PythonCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
394 """Compiles an expression to Python.""" |
387 | 395 |
396 compile_and = _binary_compiler('(%s and %s)') | |
397 compile_or = _binary_compiler('(%s or %s)') | |
392 | 398 compile_not = _unary_compiler('(not %s)') |
387 | 399 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
|
400 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
401 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
402 class _GettextCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
403 """Compile into a gettext plural expression.""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
404 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
405 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
406 expr = self.compile(expr) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
407 min, max = map(self.compile, range[1]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
408 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
|
409 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
410 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
411 class _JavaScriptCompiler(_GettextCompiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
412 """Compiles the expression to plain of JavaScript.""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
413 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
414 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
415 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
|
416 if method == 'in': |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
417 expr = self.compile(expr) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
418 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
|
419 return code |
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 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
422 class _UnicodeCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
423 """Returns a unicode pluralization rule again.""" |
387 | 424 |
425 compile_is = _binary_compiler('%s is %s') | |
426 compile_isnot = _binary_compiler('%s is not %s') | |
427 compile_and = _binary_compiler('%s and %s') | |
428 compile_or = _binary_compiler('%s or %s') | |
429 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
|
430 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
431 def compile_not(self, relation): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
432 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
|
433 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
434 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
|
435 return '%s%s %s %s' % ( |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
436 self.compile(expr), negated and ' not' or '', |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
437 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
|
438 ) |