Statistics
| Branch: | Tag: | Revision:

root / lib / compat.py @ 6b9b18a2

History | View | Annotate | Download (3.7 kB)

1
#
2
#
3

    
4
# Copyright (C) 2010 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

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

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

    
40

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

    
60

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

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

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

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

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

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

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

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

    
98

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

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

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

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

    
117

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

    
123

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

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

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

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