Mercurial > babel > old > babel-test
annotate babel/plural.py @ 393:d85b5a78ee9c
alternative repr for plural rules
author | aronacher |
---|---|
date | Tue, 15 Jul 2008 10:22:33 +0000 |
parents | 2e77d72516d7 |
children | be5e0f69137b |
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): |
393 | 68 rules = self.rules |
69 return '<%s %r>' % ( | |
70 type(self).__name__, | |
71 ', '.join(['%s: %s' % (tag, rules[tag]) for tag in _plural_tags | |
72 if tag in rules]) | |
73 ) | |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
387
diff
changeset
|
74 |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
75 def parse(cls, rules): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
76 """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
|
77 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
|
78 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
79 :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
|
80 :return: a corresponding `PluralRule` object |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
81 :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
|
82 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
83 if isinstance(rules, cls): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
84 return rules |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
85 return cls(rules) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
86 parse = classmethod(parse) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
87 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
88 def rules(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
89 """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
|
90 _compile = _UnicodeCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
91 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
|
92 rules = property(rules, doc=rules.__doc__) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
93 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
94 def gettext_expr(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
95 """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
|
96 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
|
97 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
98 >>> 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
|
99 '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
|
100 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
101 used_tags = self.tags | set([_fallback_tag]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
102 _compile = _GettextCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
103 _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
|
104 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
105 result = ['nplurals=%d; plural=(' % len(used_tags)] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
106 for tag, ast in self.abstract: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
107 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
|
108 result.append('%d)' % _get_index(_fallback_tag)) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
109 return ''.join(result) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
110 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
|
111 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
112 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
|
113 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
|
114 ``'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
|
115 rule for it.""") |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
116 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
117 def __getstate__(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
118 return self.abstract |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
119 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
120 def __setstate__(self, abstract): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
121 self.abstract = abstract |
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 def __call__(self, n): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
124 if not hasattr(self, '_func'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
125 self._func = to_python(self) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
126 return self._func(n) |
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 |
387 | 129 def to_javascript(rule): |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
130 """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
|
131 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
|
132 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
133 >>> to_javascript({'one': 'n is 1'}) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
134 "(function(n) { return (n == 1) ? 'one' : 'other'; })" |
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 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
|
137 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
|
138 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
|
139 big performance hit for these simple calculations. |
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 :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
|
142 :return: a corresponding JavaScript function as `str` |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
143 :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
|
144 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
145 to_js = _JavaScriptCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
146 result = ['(function(n) { return '] |
387 | 147 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
|
148 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
|
149 result.append('%r; })' % _fallback_tag) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
150 return ''.join(result) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
151 |
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 def to_python(rule): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
154 """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
|
155 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
|
156 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
|
157 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
158 >>> 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
|
159 >>> func(1) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
160 'one' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
161 >>> func(3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
162 'few' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
163 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
164 :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
|
165 :return: a corresponding Python function |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
166 :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
|
167 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
168 namespace = { |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
169 'IN': in_range, |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
170 'WITHIN': within_range, |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
171 'MOD': cldr_modulo |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
172 } |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
173 to_python = _PythonCompiler().compile |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
174 result = ['def evaluate(n):'] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
175 for tag, ast in rule.abstract: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
176 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
|
177 result.append(' return %r' % _fallback_tag) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
178 exec '\n'.join(result) in namespace |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
179 return namespace['evaluate'] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
180 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
181 |
387 | 182 def to_gettext(rule): |
183 """The plural rule as gettext expression. The gettext expression is | |
184 technically limited to integers and returns indices rather than tags. | |
185 | |
186 >>> to_gettext({'one': 'n is 1', 'two': 'n is 2'}) | |
187 'nplurals=3; plural=((n == 2) ? 1 : (n == 1) ? 0 : 2)' | |
188 """ | |
189 return PluralRule.parse(rule).gettext_expr | |
190 | |
191 | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
192 def in_range(num, min, max): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
193 """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
|
194 of the UTS #35 pluralization rule language: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
195 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
196 >>> in_range(1, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
197 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
198 >>> in_range(3, 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(1.2, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
201 False |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
202 >>> in_range(10, 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 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
205 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
|
206 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
207 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
208 def within_range(num, min, max): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
209 """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
|
210 of the UTS #35 pluralization rule language: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
211 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
212 >>> within_range(1, 1, 3) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
213 True |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
214 >>> within_range(1.0, 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.2, 1, 4) |
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(10, 1, 4) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
219 False |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
220 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
221 return num >= min and num <= max |
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 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
224 def cldr_modulo(a, b): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
225 """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
|
226 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
|
227 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
228 >>> cldr_modulo(-3, 5) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
229 -3 |
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 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
235 reverse = 0 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
236 if a < 0: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
237 a *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
238 reverse = 1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
239 if b < 0: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
240 b *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
241 rv = a % b |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
242 if reverse: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
243 rv *= -1 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
244 return rv |
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 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
247 class RuleError(Exception): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
248 """Raised if a rule is malformed.""" |
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 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
251 class _Parser(object): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
252 """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
|
253 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
|
254 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
255 condition = and_condition ('or' and_condition)* |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
256 and_condition = relation ('and' relation)* |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
257 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
|
258 is_relation = expr 'is' ('not')? value |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
259 in_relation = expr ('not')? 'in' range |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
260 within_relation = expr ('not')? 'within' range |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
261 expr = 'n' ('mod' value)? |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
262 value = digit+ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
263 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
|
264 range = value'..'value |
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 - 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
|
267 - 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
|
268 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
|
269 the plural rule elements. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
270 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
271 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
|
272 called `ast`. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
273 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
274 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
275 _rules = [ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
276 (None, re.compile(r'\s+(?u)')), |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
277 ('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
|
278 ('value', re.compile(r'\d+')), |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
279 ('ellipsis', re.compile(r'\.\.')) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
280 ] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
281 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
282 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
|
283 string = string.lower() |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
284 result = [] |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
285 pos = 0 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
286 end = len(string) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
287 while pos < end: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
288 for tok, rule in self._rules: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
289 match = rule.match(string, pos) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
290 if match is not None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
291 pos = match.end() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
292 if tok: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
293 result.append((tok, match.group())) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
294 break |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
295 else: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
296 raise RuleError('malformed CLDR pluralization rule. ' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
297 'Got unexpected %r' % string[pos]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
298 self.tokens = result[::-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 self.ast = self.condition() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
301 if self.tokens: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
302 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
|
303 self.tokens[-1][1]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
304 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
305 def test(self, type, value=None): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
306 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
|
307 (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
|
308 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
309 def skip(self, type, value=None): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
310 if self.test(type, value): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
311 return self.tokens.pop() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
312 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
313 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
|
314 token = self.skip(type, value) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
315 if token is not None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
316 return token |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
317 if term is None: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
318 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
|
319 if not self.tokens: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
320 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
|
321 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
|
322 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
323 def condition(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
324 op = self.and_condition() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
325 while self.skip('word', 'or'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
326 op = 'or', (op, self.and_condition()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
327 return op |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
328 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
329 def and_condition(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
330 op = self.relation() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
331 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
|
332 op = 'and', (op, self.relation()) |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
333 return op |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
334 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
335 def relation(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
336 left = self.expr() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
337 if self.skip('word', 'is'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
338 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
|
339 (left, self.value()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
340 negated = self.skip('word', 'not') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
341 method = 'in' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
342 if self.skip('word', 'within'): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
343 method = 'within' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
344 else: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
345 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
|
346 rv = 'relation', (method, left, self.range()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
347 if negated: |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
348 rv = 'not', (rv,) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
349 return rv |
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 range(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
352 left = self.value() |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
353 self.expect('ellipsis') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
354 return 'range', (left, self.value()) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
355 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
356 def expr(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
357 self.expect('word', 'n') |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
358 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
|
359 return 'mod', (('n', ()), self.value()) |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
360 return 'n', () |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
361 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
362 def value(self): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
363 return 'value', (int(self.expect('value')[1]),) |
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 |
387 | 366 def _binary_compiler(tmpl): |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
367 """Compiler factory for the `_Compiler`.""" |
387 | 368 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
|
369 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
370 |
392 | 371 def _unary_compiler(tmpl): |
372 """Compiler factory for the `_Compiler`.""" | |
373 return lambda self, x: tmpl % self.compile(x) | |
374 | |
375 | |
386
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
376 class _Compiler(object): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
377 """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
|
378 output formats. |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
379 """ |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
380 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
381 def compile(self, (op, args)): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
382 return getattr(self, 'compile_' + op)(*args) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
383 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
384 compile_n = lambda x: 'n' |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
385 compile_value = lambda x, v: str(v) |
387 | 386 compile_and = _binary_compiler('(%s && %s)') |
387 compile_or = _binary_compiler('(%s || %s)') | |
392 | 388 compile_not = _unary_compiler('(!%s)') |
387 | 389 compile_mod = _binary_compiler('(%s %% %s)') |
390 compile_is = _binary_compiler('(%s == %s)') | |
391 compile_isnot = _binary_compiler('(%s != %s)') | |
386
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 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
394 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
|
395 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
|
396 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
397 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
398 class _PythonCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
399 """Compiles an expression to Python.""" |
387 | 400 |
401 compile_and = _binary_compiler('(%s and %s)') | |
402 compile_or = _binary_compiler('(%s or %s)') | |
392 | 403 compile_not = _unary_compiler('(not %s)') |
387 | 404 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
|
405 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
406 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
407 class _GettextCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
408 """Compile into a gettext plural expression.""" |
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 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
411 expr = self.compile(expr) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
412 min, max = map(self.compile, range[1]) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
413 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
|
414 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
415 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
416 class _JavaScriptCompiler(_GettextCompiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
417 """Compiles the expression to plain of JavaScript.""" |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
418 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
419 def compile_relation(self, method, expr, range): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
420 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
|
421 if method == 'in': |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
422 expr = self.compile(expr) |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
423 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
|
424 return code |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
425 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
426 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
427 class _UnicodeCompiler(_Compiler): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
428 """Returns a unicode pluralization rule again.""" |
387 | 429 |
430 compile_is = _binary_compiler('%s is %s') | |
431 compile_isnot = _binary_compiler('%s is not %s') | |
432 compile_and = _binary_compiler('%s and %s') | |
433 compile_or = _binary_compiler('%s or %s') | |
434 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
|
435 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
436 def compile_not(self, relation): |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
437 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
|
438 |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
439 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
|
440 return '%s%s %s %s' % ( |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
441 self.compile(expr), negated and ' not' or '', |
4d345ad621c2
Added pluralization support module for the plural definitions from the latest CLDR
aronacher
parents:
diff
changeset
|
442 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
|
443 ) |