Mercurial > babel > old > mirror
annotate babel/util.py @ 529:5b62a9699780
Get rid of the utility code for itemgetter(), we now simply import this
from operator.
author | jruigrok |
---|---|
date | Sat, 05 Mar 2011 15:06:28 +0000 |
parents | 5e1804d27d65 |
children | e93f68837913 |
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 |
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
|
24 missing = object() |
3 | 25 |
317 | 26 __all__ = ['distinct', 'pathmatch', 'relpath', 'wraptext', 'odict', 'UTC', |
27 'LOCALTZ'] | |
3 | 28 __docformat__ = 'restructuredtext en' |
29 | |
353
cd8702e96f45
Added `validate_format helper function to `babel.support`.
aronacher
parents:
339
diff
changeset
|
30 |
229 | 31 def distinct(iterable): |
32 """Yield all items in an iterable collection that are distinct. | |
33 | |
34 Unlike when using sets for a similar effect, the original ordering of the | |
35 items in the collection is preserved by this function. | |
36 | |
37 >>> print list(distinct([1, 2, 1, 3, 4, 4])) | |
38 [1, 2, 3, 4] | |
39 >>> print list(distinct('foobar')) | |
40 ['f', 'o', 'b', 'a', 'r'] | |
41 | |
42 :param iterable: the iterable collection providing the data | |
43 :return: the distinct items in the collection | |
44 :rtype: ``iterator`` | |
45 """ | |
46 seen = set() | |
47 for item in iter(iterable): | |
48 if item not in seen: | |
49 yield item | |
50 seen.add(item) | |
51 | |
166
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
52 # 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
|
53 PYTHON_MAGIC_COMMENT_re = re.compile( |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
54 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
|
55 def parse_encoding(fp): |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
56 """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
|
57 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
58 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
|
59 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
60 .. __: 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
|
61 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
62 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
|
63 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
64 (From Jeff Dairiki) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
65 """ |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
66 pos = fp.tell() |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
67 fp.seek(0) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
68 try: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
69 line1 = fp.readline() |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
70 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
|
71 if has_bom: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
72 line1 = line1[len(codecs.BOM_UTF8):] |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
73 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
74 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
|
75 if not m: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
76 try: |
330
9809b94b7d88
Reinstate changeset r362, but this time properly wrap the exception list in
jruigrok
parents:
329
diff
changeset
|
77 import parser |
166
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
78 parser.suite(line1) |
330
9809b94b7d88
Reinstate changeset r362, but this time properly wrap the exception list in
jruigrok
parents:
329
diff
changeset
|
79 except (ImportError, SyntaxError): |
166
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
80 # 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
|
81 # 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
|
82 # 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
|
83 # comment. |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
84 pass |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
85 else: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
86 line2 = fp.readline() |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
87 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
|
88 |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
89 if has_bom: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
90 if m: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
91 raise SyntaxError( |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
92 "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
|
93 "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
|
94 return 'utf_8' |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
95 elif m: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
96 return m.group(1) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
97 else: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
98 return None |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
99 finally: |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
100 fp.seek(pos) |
0eccbe635dba
made the python extractor detect source file encodings from the magic encoding
pjenvey
parents:
165
diff
changeset
|
101 |
46 | 102 def pathmatch(pattern, filename): |
103 """Extended pathname pattern matching. | |
3 | 104 |
46 | 105 This function is similar to what is provided by the ``fnmatch`` module in |
106 the Python standard library, but: | |
107 | |
108 * can match complete (relative or absolute) path names, and not just file | |
109 names, and | |
110 * also supports a convenience pattern ("**") to match files at any | |
111 directory level. | |
112 | |
113 Examples: | |
114 | |
115 >>> pathmatch('**.py', 'bar.py') | |
116 True | |
117 >>> pathmatch('**.py', 'foo/bar/baz.py') | |
118 True | |
119 >>> pathmatch('**.py', 'templates/index.html') | |
120 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
|
121 |
46 | 122 >>> pathmatch('**/templates/*.html', 'templates/index.html') |
123 True | |
124 >>> pathmatch('**/templates/*.html', 'templates/foo/bar.html') | |
125 False | |
3 | 126 |
127 :param pattern: the glob pattern | |
46 | 128 :param filename: the path name of the file to match against |
129 :return: `True` if the path name matches the pattern, `False` otherwise | |
130 :rtype: `bool` | |
3 | 131 """ |
132 symbols = { | |
133 '?': '[^/]', | |
134 '?/': '[^/]/', | |
135 '*': '[^/]+', | |
136 '*/': '[^/]+/', | |
137 '**/': '(?:.+/)*?', | |
46 | 138 '**': '(?:.+/)*?[^/]+', |
3 | 139 } |
140 buf = [] | |
141 for idx, part in enumerate(re.split('([?*]+/?)', pattern)): | |
142 if idx % 2: | |
143 buf.append(symbols[part]) | |
144 elif part: | |
145 buf.append(re.escape(part)) | |
136 | 146 match = re.match(''.join(buf) + '$', filename.replace(os.sep, '/')) |
147 return match is not None | |
3 | 148 |
31 | 149 |
317 | 150 class TextWrapper(textwrap.TextWrapper): |
151 wordsep_re = re.compile( | |
152 r'(\s+|' # any whitespace | |
153 r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))' # em-dash | |
154 ) | |
155 | |
156 | |
157 def wraptext(text, width=70, initial_indent='', subsequent_indent=''): | |
158 """Simple wrapper around the ``textwrap.wrap`` function in the standard | |
159 library. This version does not wrap lines on hyphens in words. | |
160 | |
161 :param text: the text to wrap | |
162 :param width: the maximum line width | |
163 :param initial_indent: string that will be prepended to the first line of | |
164 wrapped output | |
165 :param subsequent_indent: string that will be prepended to all lines save | |
166 the first of wrapped output | |
167 :return: a list of lines | |
168 :rtype: `list` | |
169 """ | |
170 wrapper = TextWrapper(width=width, initial_indent=initial_indent, | |
171 subsequent_indent=subsequent_indent, | |
172 break_long_words=False) | |
173 return wrapper.wrap(text) | |
174 | |
175 | |
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
|
176 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
|
177 """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
|
178 |
229 | 179 :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
|
180 """ |
64
7eb6fea17864
The order of extraction methods is now preserved (see #10).
cmlenz
parents:
62
diff
changeset
|
181 def __init__(self, data=None): |
7eb6fea17864
The order of extraction methods is now preserved (see #10).
cmlenz
parents:
62
diff
changeset
|
182 dict.__init__(self, data or {}) |
165
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
136
diff
changeset
|
183 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
|
184 |
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 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
|
186 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
|
187 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
|
188 |
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 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
|
190 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
|
191 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
|
192 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
|
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 __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
|
195 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
|
196 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
|
197 |
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 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
|
199 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
|
200 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
|
201 |
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 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
|
203 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
|
204 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
|
205 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
|
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 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
|
208 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
|
209 |
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
|
210 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
|
211 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
|
212 |
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
|
213 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
|
214 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
|
215 |
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
|
216 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
|
217 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
|
218 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
|
219 elif key not in self: |
167
533baef258bb
Implement fuzzy matching to catalog updates. No frontend yet.
cmlenz
parents:
166
diff
changeset
|
220 return default |
533baef258bb
Implement fuzzy matching to catalog updates. No frontend yet.
cmlenz
parents:
166
diff
changeset
|
221 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
|
222 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
|
223 |
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 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
|
225 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
|
226 return dict.popitem(key) |
167
533baef258bb
Implement fuzzy matching to catalog updates. No frontend yet.
cmlenz
parents:
166
diff
changeset
|
227 |
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
|
228 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
|
229 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
|
230 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
|
231 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
|
232 |
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 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
|
234 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
|
235 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
|
236 |
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 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
|
238 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
|
239 |
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
|
240 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
|
241 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
|
242 |
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
|
243 |
3 | 244 try: |
245 relpath = os.path.relpath | |
246 except AttributeError: | |
247 def relpath(path, start='.'): | |
31 | 248 """Compute the relative path to one path from another. |
249 | |
132 | 250 >>> relpath('foo/bar.txt', '').replace(os.sep, '/') |
46 | 251 'foo/bar.txt' |
132 | 252 >>> relpath('foo/bar.txt', 'foo').replace(os.sep, '/') |
46 | 253 'bar.txt' |
132 | 254 >>> relpath('foo/bar.txt', 'baz').replace(os.sep, '/') |
46 | 255 '../foo/bar.txt' |
256 | |
31 | 257 :return: the relative path |
258 :rtype: `basestring` | |
259 """ | |
3 | 260 start_list = os.path.abspath(start).split(os.sep) |
261 path_list = os.path.abspath(path).split(os.sep) | |
262 | |
263 # Work out how much of the filepath is shared by start and path. | |
264 i = len(os.path.commonprefix([start_list, path_list])) | |
265 | |
266 rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:] | |
267 return os.path.join(*rel_list) | |
31 | 268 |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
269 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
|
270 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
271 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
272 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
|
273 """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
|
274 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
275 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
|
276 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
|
277 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
|
278 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
|
279 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
|
280 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
281 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
|
282 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
|
283 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
284 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
|
285 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
|
286 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
287 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
|
288 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
|
289 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
290 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
|
291 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
|
292 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
293 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
|
294 return ZERO |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
295 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
296 |
31 | 297 try: |
298 from pytz import UTC | |
299 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
|
300 UTC = FixedOffsetTimezone(0, 'UTC') |
31 | 301 """`tzinfo` object for UTC (Universal Time). |
302 | |
303 :type: `tzinfo` | |
304 """ | |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
305 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
306 STDOFFSET = timedelta(seconds = -time.timezone) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
307 if time.daylight: |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
308 DSTOFFSET = timedelta(seconds = -time.altzone) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
309 else: |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
310 DSTOFFSET = STDOFFSET |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
311 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
312 DSTDIFF = DSTOFFSET - STDOFFSET |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
313 |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
314 |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
315 class LocalTimezone(tzinfo): |
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 def utcoffset(self, dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
318 if self._isdst(dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
319 return DSTOFFSET |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
320 else: |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
321 return STDOFFSET |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
322 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
323 def dst(self, dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
324 if self._isdst(dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
325 return DSTDIFF |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
326 else: |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
327 return ZERO |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
328 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
329 def tzname(self, dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
330 return time.tzname[self._isdst(dt)] |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
331 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
332 def _isdst(self, dt): |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
333 tt = (dt.year, dt.month, dt.day, |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
334 dt.hour, dt.minute, dt.second, |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
335 dt.weekday(), 0, -1) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
336 stamp = time.mktime(tt) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
337 tt = time.localtime(stamp) |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
338 return tt.tm_isdst > 0 |
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
64
diff
changeset
|
339 |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
99
diff
changeset
|
340 |
99 | 341 LOCALTZ = LocalTimezone() |
342 """`tzinfo` object for local time-zone. | |
343 | |
344 :type: `tzinfo` | |
345 """ |