annotate babel/plural.py @ 579:99d51589c822 trunk

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