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
d85b5a78ee9c alternative repr for plural rules
aronacher
parents: 392
diff changeset
68 rules = self.rules
d85b5a78ee9c alternative repr for plural rules
aronacher
parents: 392
diff changeset
69 return '<%s %r>' % (
d85b5a78ee9c alternative repr for plural rules
aronacher
parents: 392
diff changeset
70 type(self).__name__,
d85b5a78ee9c alternative repr for plural rules
aronacher
parents: 392
diff changeset
71 ', '.join(['%s: %s' % (tag, rules[tag]) for tag in _plural_tags
d85b5a78ee9c alternative repr for plural rules
aronacher
parents: 392
diff changeset
72 if tag in rules])
d85b5a78ee9c alternative repr for plural rules
aronacher
parents: 392
diff changeset
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
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
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
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
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
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
182 def to_gettext(rule):
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
183 """The plural rule as gettext expression. The gettext expression is
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
184 technically limited to integers and returns indices rather than tags.
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
185
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
186 >>> to_gettext({'one': 'n is 1', 'two': 'n is 2'})
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
187 'nplurals=3; plural=((n == 2) ? 1 : (n == 1) ? 0 : 2)'
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
188 """
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
189 return PluralRule.parse(rule).gettext_expr
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
190
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
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
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
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
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
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
2e77d72516d7 Fixed not in plural rules
aronacher
parents: 391
diff changeset
371 def _unary_compiler(tmpl):
2e77d72516d7 Fixed not in plural rules
aronacher
parents: 391
diff changeset
372 """Compiler factory for the `_Compiler`."""
2e77d72516d7 Fixed not in plural rules
aronacher
parents: 391
diff changeset
373 return lambda self, x: tmpl % self.compile(x)
2e77d72516d7 Fixed not in plural rules
aronacher
parents: 391
diff changeset
374
2e77d72516d7 Fixed not in plural rules
aronacher
parents: 391
diff changeset
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
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
386 compile_and = _binary_compiler('(%s && %s)')
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
387 compile_or = _binary_compiler('(%s || %s)')
392
2e77d72516d7 Fixed not in plural rules
aronacher
parents: 391
diff changeset
388 compile_not = _unary_compiler('(!%s)')
387
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
389 compile_mod = _binary_compiler('(%s %% %s)')
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
390 compile_is = _binary_compiler('(%s == %s)')
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
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
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
400
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
401 compile_and = _binary_compiler('(%s and %s)')
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
402 compile_or = _binary_compiler('(%s or %s)')
392
2e77d72516d7 Fixed not in plural rules
aronacher
parents: 391
diff changeset
403 compile_not = _unary_compiler('(not %s)')
387
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
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
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
429
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
430 compile_is = _binary_compiler('%s is %s')
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
431 compile_isnot = _binary_compiler('%s is not %s')
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
432 compile_and = _binary_compiler('%s and %s')
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
433 compile_or = _binary_compiler('%s or %s')
2edbea56d2bd Some refactoring in plural.py
aronacher
parents: 386
diff changeset
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 )
Copyright (C) 2012-2017 Edgewall Software