root/galaxy-central/eggs/Babel-0.9.4-py2.6.egg/babel/util.py

リビジョン 3, 9.5 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
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
16import codecs
17from datetime import timedelta, tzinfo
18import os
19import re
20try:
21    set
22except NameError:
23    from sets import Set as set
24import textwrap
25import time
26from itertools import izip, imap
27missing = object()
28
29__all__ = ['distinct', 'pathmatch', 'relpath', 'wraptext', 'odict', 'UTC',
30           'LOCALTZ']
31__docformat__ = 'restructuredtext en'
32
33
34def 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
55# Regexp to match python magic encoding line
56PYTHON_MAGIC_COMMENT_re = re.compile(
57    r'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)', re.VERBOSE)
58def parse_encoding(fp):
59    """Deduce the encoding of a source file from magic comment.
60
61    It does this in the same way as the `Python interpreter`__
62
63    .. __: http://docs.python.org/ref/encodings.html
64
65    The ``fp`` argument should be a seekable file object.
66
67    (From Jeff Dairiki)
68    """
69    pos = fp.tell()
70    fp.seek(0)
71    try:
72        line1 = fp.readline()
73        has_bom = line1.startswith(codecs.BOM_UTF8)
74        if has_bom:
75            line1 = line1[len(codecs.BOM_UTF8):]
76
77        m = PYTHON_MAGIC_COMMENT_re.match(line1)
78        if not m:
79            try:
80                import parser
81                parser.suite(line1)
82            except (ImportError, SyntaxError):
83                # Either it's a real syntax error, in which case the source is
84                # not valid python source, or line2 is a continuation of line1,
85                # in which case we don't want to scan line2 for a magic
86                # comment.
87                pass
88            else:
89                line2 = fp.readline()
90                m = PYTHON_MAGIC_COMMENT_re.match(line2)
91
92        if has_bom:
93            if m:
94                raise SyntaxError(
95                    "python refuses to compile code with both a UTF8 "
96                    "byte-order-mark and a magic encoding comment")
97            return 'utf_8'
98        elif m:
99            return m.group(1)
100        else:
101            return None
102    finally:
103        fp.seek(pos)
104
105def pathmatch(pattern, filename):
106    """Extended pathname pattern matching.
107   
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
124   
125    >>> pathmatch('**/templates/*.html', 'templates/index.html')
126    True
127    >>> pathmatch('**/templates/*.html', 'templates/foo/bar.html')
128    False
129   
130    :param pattern: the glob pattern
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`
134    """
135    symbols = {
136        '?':   '[^/]',
137        '?/':  '[^/]/',
138        '*':   '[^/]+',
139        '*/':  '[^/]+/',
140        '**/': '(?:.+/)*?',
141        '**':  '(?:.+/)*?[^/]+',
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))
149    match = re.match(''.join(buf) + '$', filename.replace(os.sep, '/'))
150    return match is not None
151
152
153class TextWrapper(textwrap.TextWrapper):
154    wordsep_re = re.compile(
155        r'(\s+|'                                  # any whitespace
156        r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))'    # em-dash
157    )
158
159
160def 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
179class odict(dict):
180    """Ordered dict implementation.
181   
182    :see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747
183    """
184    def __init__(self, data=None):
185        dict.__init__(self, data or {})
186        self._keys = dict.keys(self)
187
188    def __delitem__(self, key):
189        dict.__delitem__(self, key)
190        self._keys.remove(key)
191
192    def __setitem__(self, key, item):
193        dict.__setitem__(self, key, item)
194        if key not in self._keys:
195            self._keys.append(key)
196
197    def __iter__(self):
198        return iter(self._keys)
199    iterkeys = __iter__
200
201    def clear(self):
202        dict.clear(self)
203        self._keys = []
204
205    def copy(self):
206        d = odict()
207        d.update(self)
208        return d
209
210    def items(self):
211        return zip(self._keys, self.values())
212
213    def iteritems(self):
214        return izip(self._keys, self.itervalues())
215
216    def keys(self):
217        return self._keys[:]
218
219    def pop(self, key, default=missing):
220        if default is missing:
221            return dict.pop(self, key)
222        elif key not in self:
223            return default
224        self._keys.remove(key)
225        return dict.pop(self, key, default)
226
227    def popitem(self, key):
228        self._keys.remove(key)
229        return dict.popitem(key)
230
231    def setdefault(self, key, failobj = None):
232        dict.setdefault(self, key, failobj)
233        if key not in self._keys:
234            self._keys.append(key)
235
236    def update(self, dict):
237        for (key, val) in dict.items():
238            self[key] = val
239
240    def values(self):
241        return map(self.get, self._keys)
242
243    def itervalues(self):
244        return imap(self.get, self._keys)
245
246
247try:
248    relpath = os.path.relpath
249except AttributeError:
250    def relpath(path, start='.'):
251        """Compute the relative path to one path from another.
252       
253        >>> relpath('foo/bar.txt', '').replace(os.sep, '/')
254        'foo/bar.txt'
255        >>> relpath('foo/bar.txt', 'foo').replace(os.sep, '/')
256        'bar.txt'
257        >>> relpath('foo/bar.txt', 'baz').replace(os.sep, '/')
258        '../foo/bar.txt'
259       
260        :return: the relative path
261        :rtype: `basestring`
262        """
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)
271
272ZERO = timedelta(0)
273
274
275class FixedOffsetTimezone(tzinfo):
276    """Fixed offset in minutes east from UTC."""
277
278    def __init__(self, offset, name=None):
279        self._offset = timedelta(minutes=offset)
280        if name is None:
281            name = 'Etc/GMT+%d' % offset
282        self.zone = name
283
284    def __str__(self):
285        return self.zone
286
287    def __repr__(self):
288        return '<FixedOffset "%s" %s>' % (self.zone, self._offset)
289
290    def utcoffset(self, dt):
291        return self._offset
292
293    def tzname(self, dt):
294        return self.zone
295
296    def dst(self, dt):
297        return ZERO
298
299
300try:
301    from pytz import UTC
302except ImportError:
303    UTC = FixedOffsetTimezone(0, 'UTC')
304    """`tzinfo` object for UTC (Universal Time).
305   
306    :type: `tzinfo`
307    """
308
309STDOFFSET = timedelta(seconds = -time.timezone)
310if time.daylight:
311    DSTOFFSET = timedelta(seconds = -time.altzone)
312else:
313    DSTOFFSET = STDOFFSET
314
315DSTDIFF = DSTOFFSET - STDOFFSET
316
317
318class LocalTimezone(tzinfo):
319
320    def utcoffset(self, dt):
321        if self._isdst(dt):
322            return DSTOFFSET
323        else:
324            return STDOFFSET
325
326    def dst(self, dt):
327        if self._isdst(dt):
328            return DSTDIFF
329        else:
330            return ZERO
331
332    def tzname(self, dt):
333        return time.tzname[self._isdst(dt)]
334
335    def _isdst(self, dt):
336        tt = (dt.year, dt.month, dt.day,
337              dt.hour, dt.minute, dt.second,
338              dt.weekday(), 0, -1)
339        stamp = time.mktime(tt)
340        tt = time.localtime(stamp)
341        return tt.tm_isdst > 0
342
343
344LOCALTZ = LocalTimezone()
345"""`tzinfo` object for local time-zone.
346
347:type: `tzinfo`
348"""
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。