Statistics
| Branch: | Tag: | Revision:

root / lib / compat.py @ eb62069e

History | View | Annotate | Download (3.9 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-msg=F0401
31
  import functools
32
except ImportError:
33
  functools = None
34

    
35
try:
36
  # pylint: disable-msg=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-msg=F0401
49
  # Yes, we're not using the imports in this module.
50
  # pylint: disable-msg=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
def _any(seq):
71
  """Returns True if any element of the iterable are True.
72

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

    
78
try:
79
  # pylint: disable-msg=E0601
80
  # pylint: disable-msg=W0622
81
  all = all
82
except NameError:
83
  all = _all
84

    
85
try:
86
  # pylint: disable-msg=E0601
87
  # pylint: disable-msg=W0622
88
  any = any
89
except NameError:
90
  any = _any
91

    
92
def partition(seq, pred=bool): # pylint: disable-msg=W0622
93
  """Partition a list in two, based on the given predicate.
94

95
  """
96
  return (list(itertools.ifilter(pred, seq)),
97
          list(itertools.ifilterfalse(pred, seq)))
98

    
99

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

105
  This function was copied from Python's documentation.
106

107
  """
108
  def newfunc(*fargs, **fkeywords):
109
    newkeywords = keywords.copy()
110
    newkeywords.update(fkeywords)
111
    return func(*(args + fargs), **newkeywords) # pylint: disable-msg=W0142
112

    
113
  newfunc.func = func
114
  newfunc.args = args
115
  newfunc.keywords = keywords
116
  return newfunc
117

    
118

    
119
if functools is None:
120
  partial = _partial
121
else:
122
  partial = functools.partial
123

    
124

    
125
def TryToRoman(val, convert=True):
126
  """Try to convert a value to roman numerals
127

128
  If the roman module could be loaded convert the given value to a roman
129
  numeral. Gracefully fail back to leaving the value untouched.
130

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

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

    
147
#: returns the first element of a list-like value
148
fst = operator.itemgetter(0)
149

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