Statistics
| Branch: | Tag: | Revision:

root / lib / compat.py @ b459a848

History | View | Annotate | Download (3.8 kB)

1
#
2
#
3

    
4
# Copyright (C) 2010, 2011 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""Module containing backported language/library functionality.
23

24
"""
25

    
26
import itertools
27
import operator
28

    
29
try:
30
  # pylint: disable=F0401
31
  import functools
32
except ImportError:
33
  functools = None
34

    
35
try:
36
  # pylint: disable=F0401
37
  import roman
38
except ImportError:
39
  roman = None
40

    
41

    
42
# compat.md5_hash and compat.sha1_hash can be called to generate and md5 and a
43
# sha1 hashing modules, under python 2.4, 2.5 and 2.6, even though some changes
44
# went on. compat.sha1 is python-version specific and is used for python
45
# modules (hmac, for example) which have changed their behavior as well from
46
# one version to the other.
47
try:
48
  # pylint: disable=F0401
49
  # Yes, we're not using the imports in this module.
50
  # pylint: disable=W0611
51
  from hashlib import md5 as md5_hash
52
  from hashlib import sha1 as sha1_hash
53
  # this additional version is needed for compatibility with the hmac module
54
  sha1 = sha1_hash
55
except ImportError:
56
  from md5 import new as md5_hash
57
  import sha
58
  sha1 = sha
59
  sha1_hash = sha.new
60

    
61

    
62
def _all(seq):
63
  """Returns True if all elements in the iterable are True.
64

65
  """
66
  for _ in itertools.ifilterfalse(bool, seq):
67
    return False
68
  return True
69

    
70

    
71
def _any(seq):
72
  """Returns True if any element of the iterable are True.
73

74
  """
75
  for _ in itertools.ifilter(bool, seq):
76
    return True
77
  return False
78

    
79

    
80
try:
81
  # pylint: disable=E0601
82
  # pylint: disable=W0622
83
  all = all
84
except NameError:
85
  all = _all
86

    
87
try:
88
  # pylint: disable=E0601
89
  # pylint: disable=W0622
90
  any = any
91
except NameError:
92
  any = _any
93

    
94

    
95
def partition(seq, pred=bool): # pylint: disable=W0622
96
  """Partition a list in two, based on the given predicate.
97

98
  """
99
  return (list(itertools.ifilter(pred, seq)),
100
          list(itertools.ifilterfalse(pred, seq)))
101

    
102

    
103
# Even though we're using Python's built-in "partial" function if available,
104
# this one is always defined for testing.
105
def _partial(func, *args, **keywords): # pylint: disable=W0622
106
  """Decorator with partial application of arguments and keywords.
107

108
  This function was copied from Python's documentation.
109

110
  """
111
  def newfunc(*fargs, **fkeywords):
112
    newkeywords = keywords.copy()
113
    newkeywords.update(fkeywords)
114
    return func(*(args + fargs), **newkeywords) # pylint: disable=W0142
115

    
116
  newfunc.func = func
117
  newfunc.args = args
118
  newfunc.keywords = keywords
119
  return newfunc
120

    
121

    
122
if functools is None:
123
  partial = _partial
124
else:
125
  partial = functools.partial
126

    
127

    
128
def TryToRoman(val, convert=True):
129
  """Try to convert a value to roman numerals
130

131
  If the roman module could be loaded convert the given value to a roman
132
  numeral. Gracefully fail back to leaving the value untouched.
133

134
  @type val: integer
135
  @param val: value to convert
136
  @type convert: boolean
137
  @param convert: if False, don't try conversion at all
138
  @rtype: string or typeof(val)
139
  @return: roman numeral for val, or val if conversion didn't succeed
140

141
  """
142
  if roman is not None and convert:
143
    try:
144
      return roman.toRoman(val)
145
    except roman.RomanError:
146
      return val
147
  else:
148
    return val
149

    
150
#: returns the first element of a list-like value
151
fst = operator.itemgetter(0)
152

    
153
#: returns the second element of a list-like value
154
snd = operator.itemgetter(1)