Mercurial > babel > old > mirror
annotate babel/util.py @ 527:5e1804d27d65
Cleanup round #1: get rid of the frozenset/set utility code and imports.
This is no longer needed with 2.4 and onward.
author | jruigrok |
---|---|
date | Sat, 05 Mar 2011 14:59:20 +0000 |
parents | f03cc3bed4e1 |
children | 5b62a9699780 |
rev | line source |
---|---|
3 | 1 # -*- coding: utf-8 -*- |
2 # | |
3 # Copyright (C) 2007 Edgewall Software | |
4 # All rights reserved. | |
5 # | |
6 # This software is licensed as described in the file COPYING, which | |
7 # you should have received as part of this distribution. The terms | |
8 # are also available at http://babel.edgewall.org/wiki/License. | |
9 # | |
10 # This software consists of voluntary contributions made by many | |
11 # individuals. For the exact contribution history, see the revision | |
12 # history and logs, available at http://babel.edgewall.org/log/. | |
13 | |
14 """Various utility classes and functions.""" | |
15 | |
166
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
16 import codecs |
32 | 17 from datetime import timedelta, tzinfo |
3 | 18 import os |
19 import re | |
317 | 20 import textwrap |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
21 import time |
339
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
22 from itertools import izip, imap |
416
f03cc3bed4e1
fix Python 2.3 compat: rearrange set/itemgetter/rsplit/sorted/unicode.decode
pjenvey
parents:
356
diff
changeset
|
23 try: |
f03cc3bed4e1
fix Python 2.3 compat: rearrange set/itemgetter/rsplit/sorted/unicode.decode
pjenvey
parents:
356
diff
changeset
|
24 from operator import itemgetter |
f03cc3bed4e1
fix Python 2.3 compat: rearrange set/itemgetter/rsplit/sorted/unicode.decode
pjenvey
parents:
356
diff
changeset
|
25 except ImportError: |
f03cc3bed4e1
fix Python 2.3 compat: rearrange set/itemgetter/rsplit/sorted/unicode.decode
pjenvey
parents:
356
diff
changeset
|
26 def itemgetter(item): |
f03cc3bed4e1
fix Python 2.3 compat: rearrange set/itemgetter/rsplit/sorted/unicode.decode
pjenvey
parents:
356
diff
changeset
|
27 return lambda obj: obj[item] |
f03cc3bed4e1
fix Python 2.3 compat: rearrange set/itemgetter/rsplit/sorted/unicode.decode
pjenvey
parents:
356
diff
changeset
|
28 |
339
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
29 missing = object() |
3 | 30 |
317 | 31 __all__ = ['distinct', 'pathmatch', 'relpath', 'wraptext', 'odict', 'UTC', |
32 'LOCALTZ'] | |
3 | 33 __docformat__ = 'restructuredtext en' |
34 | |
353
cd8702e96f45
Added `validate_format helper function to `babel.support`.
aronacher
parents:
339
diff
changeset
|
35 |
229 | 36 def distinct(iterable): |
37 """Yield all items in an iterable collection that are distinct. | |
38 | |
39 Unlike when using sets for a similar effect, the original ordering of the | |
40 items in the collection is preserved by this function. | |
41 | |
42 >>> print list(distinct([1, 2, 1, 3, 4, 4])) | |
43 [1, 2, 3, 4] | |
44 >>> print list(distinct('foobar')) | |
45 ['f', 'o', 'b', 'a', 'r'] | |
46 | |
47 :param iterable: the iterable collection providing the data | |
48 :return: the distinct items in the collection | |
49 :rtype: ``iterator`` | |
50 """ | |
51 seen = set() | |
52 for item in iter(iterable): | |
53 if item not in seen: | |
54 yield item | |
55 seen.add(item) | |
56 | |
166
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
57 # Regexp to match python magic encoding line |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
58 PYTHON_MAGIC_COMMENT_re = re.compile( |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
59 r'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)', re.VERBOSE) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
60 def parse_encoding(fp): |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
61 """Deduce the encoding of a source file from magic comment. |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
62 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
63 It does this in the same way as the `Python interpreter`__ |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
64 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
65 .. __: http://docs.python.org/ref/encodings.html |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
66 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
67 The ``fp`` argument should be a seekable file object. |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
68 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
69 (From Jeff Dairiki) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
70 """ |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
71 pos = fp.tell() |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
72 fp.seek(0) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
73 try: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
74 line1 = fp.readline() |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
75 has_bom = line1.startswith(codecs.BOM_UTF8) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
76 if has_bom: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
77 line1 = line1[len(codecs.BOM_UTF8):] |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
78 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
79 m = PYTHON_MAGIC_COMMENT_re.match(line1) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
80 if not m: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
81 try: |
330
9809b94b7d88
Reinstate changeset r362, but this time properly wrap the exception list in
jruigrok
parents:
329
diff
changeset
|
82 import parser |
166
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
83 parser.suite(line1) |
330
9809b94b7d88
Reinstate changeset r362, but this time properly wrap the exception list in
jruigrok
parents:
329
diff
changeset
|
84 except (ImportError, SyntaxError): |
166
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
85 # Either it's a real syntax error, in which case the source is |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
86 # not valid python source, or line2 is a continuation of line1, |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
87 # in which case we don't want to scan line2 for a magic |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
88 # comment. |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
89 pass |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
90 else: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
91 line2 = fp.readline() |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
92 m = PYTHON_MAGIC_COMMENT_re.match(line2) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
93 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
94 if has_bom: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
95 if m: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
96 raise SyntaxError( |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
97 "python refuses to compile code with both a UTF8 " |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
98 "byte-order-mark and a magic encoding comment") |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
99 return 'utf_8' |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
100 elif m: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
101 return m.group(1) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
102 else: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
103 return None |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
104 finally: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
105 fp.seek(pos) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
106 |
46 | 107 def pathmatch(pattern, filename): |
108 """Extended pathname pattern matching. | |
3 | 109 |
46 | 110 This function is similar to what is provided by the ``fnmatch`` module in |
111 the Python standard library, but: | |
112 | |
113 * can match complete (relative or absolute) path names, and not just file | |
114 names, and | |
115 * also supports a convenience pattern ("**") to match files at any | |
116 directory level. | |
117 | |
118 Examples: | |
119 | |
120 >>> pathmatch('**.py', 'bar.py') | |
121 True | |
122 >>> pathmatch('**.py', 'foo/bar/baz.py') | |
123 True | |
124 >>> pathmatch('**.py', 'templates/index.html') | |
125 False | |
49
9979a409589e
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
46
diff
changeset
|
126 |
46 | 127 >>> pathmatch('**/templates/*.html', 'templates/index.html') |
128 True | |
129 >>> pathmatch('**/templates/*.html', 'templates/foo/bar.html') | |
130 False | |
3 | 131 |
132 :param pattern: the glob pattern | |
46 | 133 :param filename: the path name of the file to match against |
134 :return: `True` if the path name matches the pattern, `False` otherwise | |
135 :rtype: `bool` | |
3 | 136 """ |
137 symbols = { | |
138 '?': '[^/]', | |
139 '?/': '[^/]/', | |
140 '*': '[^/]+', | |
141 '*/': '[^/]+/', | |
142 '**/': '(?:.+/)*?', | |
46 | 143 '**': '(?:.+/)*?[^/]+', |
3 | 144 } |
145 buf = [] | |
146 for idx, part in enumerate(re.split('([?*]+/?)', pattern)): | |
147 if idx % 2: | |
148 buf.append(symbols[part]) | |
149 elif part: | |
150 buf.append(re.escape(part)) | |
136 | 151 match = re.match(''.join(buf) + '$', filename.replace(os.sep, '/')) |
152 return match is not None | |
3 | 153 |
31 | 154 |
317 | 155 class TextWrapper(textwrap.TextWrapper): |
156 wordsep_re = re.compile( | |
157 r'(\s+|' # any whitespace | |
158 r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))' # em-dash | |
159 ) | |
160 | |
161 | |
162 def wraptext(text, width=70, initial_indent='', subsequent_indent=''): | |
163 """Simple wrapper around the ``textwrap.wrap`` function in the standard | |
164 library. This version does not wrap lines on hyphens in words. | |
165 | |
166 :param text: the text to wrap | |
167 :param width: the maximum line width | |
168 :param initial_indent: string that will be prepended to the first line of | |
169 wrapped output | |
170 :param subsequent_indent: string that will be prepended to all lines save | |
171 the first of wrapped output | |
172 :return: a list of lines | |
173 :rtype: `list` | |
174 """ | |
175 wrapper = TextWrapper(width=width, initial_indent=initial_indent, | |
176 subsequent_indent=subsequent_indent, | |
177 break_long_words=False) | |
178 return wrapper.wrap(text) | |
179 | |
180 | |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
181 class odict(dict): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
182 """Ordered dict implementation. |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
183 |
229 | 184 :see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747 |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
185 """ |
64
7eb6fea17864
The order of extraction methods is now preserved (see #10).
cmlenz
parents:
62
diff
changeset
|
186 def __init__(self, data=None): |
7eb6fea17864
The order of extraction methods is now preserved (see #10).
cmlenz
parents:
62
diff
changeset
|
187 dict.__init__(self, data or {}) |
165
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
136
diff
changeset
|
188 self._keys = dict.keys(self) |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
189 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
190 def __delitem__(self, key): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
191 dict.__delitem__(self, key) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
192 self._keys.remove(key) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
193 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
194 def __setitem__(self, key, item): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
195 dict.__setitem__(self, key, item) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
196 if key not in self._keys: |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
197 self._keys.append(key) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
198 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
199 def __iter__(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
200 return iter(self._keys) |
339
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
201 iterkeys = __iter__ |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
202 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
203 def clear(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
204 dict.clear(self) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
205 self._keys = [] |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
206 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
207 def copy(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
208 d = odict() |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
209 d.update(self) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
210 return d |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
211 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
212 def items(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
213 return zip(self._keys, self.values()) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
214 |
339
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
215 def iteritems(self): |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
216 return izip(self._keys, self.itervalues()) |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
217 |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
218 def keys(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
219 return self._keys[:] |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
220 |
339
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
221 def pop(self, key, default=missing): |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
222 if default is missing: |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
223 return dict.pop(self, key) |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
224 elif key not in self: |
167
533baef258bb
Implement fuzzy matching to catalog updates. No frontend yet.
cmlenz
parents:
166
diff
changeset
|
225 return default |
533baef258bb
Implement fuzzy matching to catalog updates. No frontend yet.
cmlenz
parents:
166
diff
changeset
|
226 self._keys.remove(key) |
339
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
227 return dict.pop(self, key, default) |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
228 |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
229 def popitem(self, key): |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
230 self._keys.remove(key) |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
231 return dict.popitem(key) |
167
533baef258bb
Implement fuzzy matching to catalog updates. No frontend yet.
cmlenz
parents:
166
diff
changeset
|
232 |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
233 def setdefault(self, key, failobj = None): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
234 dict.setdefault(self, key, failobj) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
235 if key not in self._keys: |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
236 self._keys.append(key) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
237 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
238 def update(self, dict): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
239 for (key, val) in dict.items(): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
240 self[key] = val |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
241 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
242 def values(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
243 return map(self.get, self._keys) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
244 |
339
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
245 def itervalues(self): |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
246 return imap(self.get, self._keys) |
6811369cb912
Fix iterkeys/iteritems/itervalues/pop/popitem methods on the `odict` utility class. Thanks to Armin Ronacher for the patch.
cmlenz
parents:
330
diff
changeset
|
247 |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
49
diff
changeset
|
248 |
3 | 249 try: |
250 relpath = os.path.relpath | |
251 except AttributeError: | |
252 def relpath(path, start='.'): | |
31 | 253 """Compute the relative path to one path from another. |
254 | |
132 | 255 >>> relpath('foo/bar.txt', '').replace(os.sep, '/') |
46 | 256 'foo/bar.txt' |
132 | 257 >>> relpath('foo/bar.txt', 'foo').replace(os.sep, '/') |
46 | 258 'bar.txt' |
132 | 259 >>> relpath('foo/bar.txt', 'baz').replace(os.sep, '/') |
46 | 260 '../foo/bar.txt' |
261 | |
31 | 262 :return: the relative path |
263 :rtype: `basestring` | |
264 """ | |
3 | 265 start_list = os.path.abspath(start).split(os.sep) |
266 path_list = os.path.abspath(path).split(os.sep) | |
267 | |
268 # Work out how much of the filepath is shared by start and path. | |
269 i = len(os.path.commonprefix([start_list, path_list])) | |
270 | |
271 rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:] | |
272 return os.path.join(*rel_list) | |
31 | 273 |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
274 ZERO = timedelta(0) |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
275 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
276 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
277 class FixedOffsetTimezone(tzinfo): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
278 """Fixed offset in minutes east from UTC.""" |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
279 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
280 def __init__(self, offset, name=None): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
281 self._offset = timedelta(minutes=offset) |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
282 if name is None: |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
283 name = 'Etc/GMT+%d' % offset |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
284 self.zone = name |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
285 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
286 def __str__(self): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
287 return self.zone |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
288 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
289 def __repr__(self): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
290 return '<FixedOffset "%s" %s>' % (self.zone, self._offset) |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
291 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
292 def utcoffset(self, dt): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
293 return self._offset |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
294 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
295 def tzname(self, dt): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
296 return self.zone |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
297 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
298 def dst(self, dt): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
299 return ZERO |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
300 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
301 |
31 | 302 try: |
303 from pytz import UTC | |
304 except ImportError: | |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
305 UTC = FixedOffsetTimezone(0, 'UTC') |
31 | 306 """`tzinfo` object for UTC (Universal Time). |
307 | |
308 :type: `tzinfo` | |
309 """ | |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
310 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
311 STDOFFSET = timedelta(seconds = -time.timezone) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
312 if time.daylight: |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
313 DSTOFFSET = timedelta(seconds = -time.altzone) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
314 else: |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
315 DSTOFFSET = STDOFFSET |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
316 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
317 DSTDIFF = DSTOFFSET - STDOFFSET |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
318 |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
319 |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
320 class LocalTimezone(tzinfo): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
321 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
322 def utcoffset(self, dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
323 if self._isdst(dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
324 return DSTOFFSET |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
325 else: |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
326 return STDOFFSET |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
327 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
328 def dst(self, dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
329 if self._isdst(dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
330 return DSTDIFF |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
331 else: |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
332 return ZERO |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
333 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
334 def tzname(self, dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
335 return time.tzname[self._isdst(dt)] |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
336 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
337 def _isdst(self, dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
338 tt = (dt.year, dt.month, dt.day, |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
339 dt.hour, dt.minute, dt.second, |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
340 dt.weekday(), 0, -1) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
341 stamp = time.mktime(tt) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
342 tt = time.localtime(stamp) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
343 return tt.tm_isdst > 0 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
344 |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
345 |
99 | 346 LOCALTZ = LocalTimezone() |
347 """`tzinfo` object for local time-zone. | |
348 | |
349 :type: `tzinfo` | |
350 """ |