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