Package logilab-common-0 :: Package 39 :: Package 0 :: Module compat
[frames] | no frames]

Source Code for Module logilab-common-0.39.0.compat

  1  # pylint: disable-msg=E0601,W0622,W0611 
  2  """Wrappers around some builtins introduced in python 2.3, 2.4 and 
  3  2.5, making them available in for earlier versions of python. 
  4   
  5  :copyright: 2000-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 
  6  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr 
  7  :license: General Public License version 2 - http://www.gnu.org/licenses 
  8  """ 
  9  from __future__ import generators 
 10  __docformat__ = "restructuredtext en" 
 11   
 12  import os 
 13  from warnings import warn 
 14   
 15  import __builtin__ 
 16   
 17  from logilab.common.deprecation import class_renamed 
 18   
 19  try: 
 20      set = set 
 21      frozenset = frozenset 
 22  except NameError: 
 23      try: 
 24          from sets import Set as set, ImmutableSet as frozenset 
 25      except ImportError: 
26 - class _baseset(object):
27 - def __init__(self, values=()):
28 self._data = {} 29 warn("This implementation of Set is not complete !", 30 stacklevel=2) 31 for v in values: 32 self._data[v] = 1
33
34 - def __or__(self, other):
35 result = self.__class__(self._data.keys()) 36 for val in other: 37 result.add(val) 38 return result
39 __add__ = __or__ 40
41 - def __and__(self, other):
42 result = self.__class__() 43 for val in other: 44 if val in self._data: 45 result.add(val) 46 return result
47
48 - def __sub__(self, other):
49 result = self.__class__(self._data.keys()) 50 for val in other: 51 if val in self._data: 52 result.remove(val) 53 return result
54
55 - def __cmp__(self, other):
56 keys = self._data.keys() 57 okeys = other._data.keys() 58 keys.sort() 59 okeys.sort() 60 return cmp(keys, okeys)
61
62 - def __len__(self):
63 return len(self._data)
64
65 - def __repr__(self):
66 elements = self._data.keys() 67 return 'lcc.%s(%r)' % (self.__class__.__name__, elements)
68 __str__ = __repr__ 69
70 - def __iter__(self):
71 return iter(self._data)
72
73 - class frozenset(_baseset):
74 """immutable set (can be set in dictionnaries)"""
75 - def __init__(self, values=()):
76 super(frozenset, self).__init__(values) 77 self._hashcode = None
78
79 - def _compute_hash(self):
80 """taken from python stdlib (sets.py)""" 81 # Calculate hash code for a set by xor'ing the hash codes of 82 # the elements. This ensures that the hash code does not depend 83 # on the order in which elements are added to the set. This is 84 # not called __hash__ because a BaseSet should not be hashable; 85 # only an ImmutableSet is hashable. 86 result = 0 87 for elt in self: 88 result ^= hash(elt) 89 return result
90
91 - def __hash__(self):
92 """taken from python stdlib (sets.py)""" 93 if self._hashcode is None: 94 self._hashcode = self._compute_hash() 95 return self._hashcode
96 97
98 - class set(_baseset):
99 """mutable set"""
100 - def add(self, value):
101 self._data[value] = 1
102
103 - def remove(self, element):
104 """removes <element> from set""" 105 del self._data[element]
106
107 - def pop(self):
108 """pops an arbitrary element from set""" 109 return self._data.popitem()[0]
110
111 - def __hash__(self):
112 """mutable et cannot be hashed.""" 113 raise TypeError("set objects are not hashable")
114 115 del _baseset # don't explicity provide this class 116 117 Set = class_renamed('Set', set, 'logilab.common.compat.Set is deprecated, ' 118 'use logilab.common.compat.set instead') 119 120 try: 121 from itertools import izip, chain, imap 122 except ImportError: 123 # from itertools documentation ###
124 - def izip(*iterables):
125 iterables = map(iter, iterables) 126 while iterables: 127 result = [i.next() for i in iterables] 128 yield tuple(result)
129
130 - def chain(*iterables):
131 for it in iterables: 132 for element in it: 133 yield element
134
135 - def imap(function, *iterables):
136 iterables = map(iter, iterables) 137 while True: 138 args = [i.next() for i in iterables] 139 if function is None: 140 yield tuple(args) 141 else: 142 yield function(*args)
143 try: 144 sum = sum 145 enumerate = enumerate 146 except NameError: 147 # define the sum and enumerate functions (builtins introduced in py 2.3) 148 import operator
149 - def sum(seq, start=0):
150 """Returns the sum of all elements in the sequence""" 151 return reduce(operator.add, seq, start)
152
153 - def enumerate(iterable):
154 """emulates the python2.3 enumerate() function""" 155 i = 0 156 for val in iterable: 157 yield i, val 158 i += 1
159 #return zip(range(len(iterable)), iterable) 160 try: 161 sorted = sorted 162 reversed = reversed 163 except NameError: 164
165 - def sorted(iterable, cmp=None, key=None, reverse=False):
166 original = list(iterable) 167 if key: 168 l2 = [(key(elt), index) for index, elt in enumerate(original)] 169 else: 170 l2 = original 171 l2.sort(cmp) 172 if reverse: 173 l2.reverse() 174 if key: 175 return [original[index] for elt, index in l2] 176 return l2
177
178 - def reversed(l):
179 l2 = list(l) 180 l2.reverse() 181 return l2
182 183 try: # 184 max = max 185 max(("ab","cde"),key=len) 186 except TypeError:
187 - def max( *args, **kargs):
188 if len(args) == 0: 189 raise TypeError("max expected at least 1 arguments, got 0") 190 key= kargs.pop("key", None) 191 #default implementation 192 if key is None: 193 return __builtin__.max(*args,**kargs) 194 195 for karg in kargs: 196 raise TypeError("unexpected keyword argument %s for function max") % karg 197 198 if len(args) == 1: 199 items = iter(args[0]) 200 else: 201 items = iter(args) 202 203 try: 204 best_item = items.next() 205 best_value = key(best_item) 206 except StopIteration: 207 raise ValueError("max() arg is an empty sequence") 208 209 for item in items: 210 value = key(item) 211 if value > best_value: 212 best_item = item 213 best_value = value 214 215 return best_item
216 217 218 219 220 221 # Python2.5 builtins 222 try: 223 any = any 224 all = all 225 except NameError:
226 - def any(iterable):
227 """any(iterable) -> bool 228 229 Return True if bool(x) is True for any x in the iterable. 230 """ 231 for elt in iterable: 232 if elt: 233 return True 234 return False
235
236 - def all(iterable):
237 """all(iterable) -> bool 238 239 Return True if bool(x) is True for all values x in the iterable. 240 """ 241 for elt in iterable: 242 if not elt: 243 return False 244 return True
245 246 # Python2.5 subprocess added functions and exceptions 247 from subprocess import Popen
248 -class CalledProcessError(Exception):
249 """This exception is raised when a process run by check_call() returns 250 a non-zero exit status. The exit status will be stored in the 251 returncode attribute."""
252 - def __init__(self, returncode, cmd):
253 self.returncode = returncode 254 self.cmd = cmd
255 - def __str__(self):
256 return "Command '%s' returned non-zero exit status %d" % (self.cmd, 257 self.returncode)
258
259 -def call(*popenargs, **kwargs):
260 """Run command with arguments. Wait for command to complete, then 261 return the returncode attribute. 262 263 The arguments are the same as for the Popen constructor. Example: 264 265 retcode = call(["ls", "-l"]) 266 """ 267 # workaround: subprocess.Popen(cmd, stdout=sys.stdout) fails 268 # see http://bugs.python.org/issue1531862 269 if "stdout" in kwargs: 270 fileno = kwargs.get("stdout").fileno() 271 del kwargs['stdout'] 272 return Popen(stdout=os.dup(fileno), *popenargs, **kwargs).wait() 273 return Popen(*popenargs, **kwargs).wait()
274
275 -def check_call(*popenargs, **kwargs):
276 """Run command with arguments. Wait for command to complete. If 277 the exit code was zero then return, otherwise raise 278 CalledProcessError. The CalledProcessError object will have the 279 return code in the returncode attribute. 280 281 The arguments are the same as for the Popen constructor. Example: 282 283 check_call(["ls", "-l"]) 284 """ 285 retcode = call(*popenargs, **kwargs) 286 cmd = kwargs.get("args") 287 if cmd is None: 288 cmd = popenargs[0] 289 if retcode: 290 raise CalledProcessError(retcode, cmd) 291 return retcode
292