Package logilab :: Package common :: Module compat
[frames] | no frames]

Source Code for Module logilab.common.compat

  1  # pylint: disable=E0601,W0622,W0611 
  2  # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 
  3  # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 
  4  # 
  5  # This file is part of logilab-common. 
  6  # 
  7  # logilab-common is free software: you can redistribute it and/or modify it under 
  8  # the terms of the GNU Lesser General Public License as published by the Free 
  9  # Software Foundation, either version 2.1 of the License, or (at your option) any 
 10  # later version. 
 11  # 
 12  # logilab-common is distributed in the hope that it will be useful, but WITHOUT 
 13  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 14  # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 15  # details. 
 16  # 
 17  # You should have received a copy of the GNU Lesser General Public License along 
 18  # with logilab-common.  If not, see <http://www.gnu.org/licenses/>. 
 19  """Wrappers around some builtins introduced in python 2.3, 2.4 and 
 20  2.5, making them available in for earlier versions of python. 
 21   
 22  See another compatibility snippets from other projects: 
 23   
 24      :mod:`lib2to3.fixes` 
 25      :mod:`coverage.backward` 
 26      :mod:`unittest2.compatibility` 
 27  """ 
 28   
 29  from __future__ import generators 
 30   
 31  __docformat__ = "restructuredtext en" 
 32   
 33  import os 
 34  import sys 
 35  import types 
 36  from warnings import warn 
 37   
 38  import __builtin__ as builtins # 2to3 will tranform '__builtin__' to 'builtins' 
 39   
 40  if sys.version_info < (3, 0): 
 41      str_to_bytes = str 
42 - def str_encode(string, encoding):
43 if isinstance(string, unicode): 44 return string.encode(encoding) 45 return str(string)
46 else:
47 - def str_to_bytes(string):
48 return str.encode(string)
49 # we have to ignore the encoding in py3k to be able to write a string into a 50 # TextIOWrapper or like object (which expect an unicode string)
51 - def str_encode(string, encoding):
52 return str(string)
53 54 # XXX callable built-in seems back in all python versions 55 try: 56 callable = builtins.callable 57 except AttributeError: 58 from collections import Callable
59 - def callable(something):
60 return isinstance(something, Callable)
61 del Callable 62 63 # See also http://bugs.python.org/issue11776 64 if sys.version_info[0] == 3:
65 - def method_type(callable, instance, klass):
66 # api change. klass is no more considered 67 return types.MethodType(callable, instance)
68 else: 69 # alias types otherwise 70 method_type = types.MethodType 71 72 if sys.version_info < (3, 0): 73 raw_input = raw_input 74 else: 75 raw_input = input 76 77 # Pythons 2 and 3 differ on where to get StringIO 78 if sys.version_info < (3, 0): 79 from cStringIO import StringIO 80 FileIO = file 81 BytesIO = StringIO 82 reload = reload 83 else: 84 from io import FileIO, BytesIO, StringIO 85 from imp import reload 86 87 # Where do pickles come from? 88 try: 89 import cPickle as pickle 90 except ImportError: 91 import pickle 92 93 from logilab.common.deprecation import deprecated 94 95 from itertools import izip, chain, imap 96 if sys.version_info < (3, 0):# 2to3 will remove the imports 97 izip = deprecated('izip exists in itertools since py2.3')(izip) 98 imap = deprecated('imap exists in itertools since py2.3')(imap) 99 chain = deprecated('chain exists in itertools since py2.3')(chain) 100 101 sum = deprecated('sum exists in builtins since py2.3')(sum) 102 enumerate = deprecated('enumerate exists in builtins since py2.3')(enumerate) 103 frozenset = deprecated('frozenset exists in builtins since py2.4')(frozenset) 104 reversed = deprecated('reversed exists in builtins since py2.4')(reversed) 105 sorted = deprecated('sorted exists in builtins since py2.4')(sorted) 106 max = deprecated('max exists in builtins since py2.4')(max) 107 108 109 # Python2.5 builtins 110 try: 111 any = any 112 all = all 113 except NameError:
114 - def any(iterable):
115 """any(iterable) -> bool 116 117 Return True if bool(x) is True for any x in the iterable. 118 """ 119 for elt in iterable: 120 if elt: 121 return True 122 return False
123
124 - def all(iterable):
125 """all(iterable) -> bool 126 127 Return True if bool(x) is True for all values x in the iterable. 128 """ 129 for elt in iterable: 130 if not elt: 131 return False 132 return True
133 134 135 # Python2.5 subprocess added functions and exceptions 136 try: 137 from subprocess import Popen 138 except ImportError: 139 # gae or python < 2.3 140
141 - class CalledProcessError(Exception):
142 """This exception is raised when a process run by check_call() returns 143 a non-zero exit status. The exit status will be stored in the 144 returncode attribute."""
145 - def __init__(self, returncode, cmd):
146 self.returncode = returncode 147 self.cmd = cmd
148 - def __str__(self):
149 return "Command '%s' returned non-zero exit status %d" % (self.cmd, 150 self.returncode)
151
152 - def call(*popenargs, **kwargs):
153 """Run command with arguments. Wait for command to complete, then 154 return the returncode attribute. 155 156 The arguments are the same as for the Popen constructor. Example: 157 158 retcode = call(["ls", "-l"]) 159 """ 160 # workaround: subprocess.Popen(cmd, stdout=sys.stdout) fails 161 # see http://bugs.python.org/issue1531862 162 if "stdout" in kwargs: 163 fileno = kwargs.get("stdout").fileno() 164 del kwargs['stdout'] 165 return Popen(stdout=os.dup(fileno), *popenargs, **kwargs).wait() 166 return Popen(*popenargs, **kwargs).wait()
167
168 - def check_call(*popenargs, **kwargs):
169 """Run command with arguments. Wait for command to complete. If 170 the exit code was zero then return, otherwise raise 171 CalledProcessError. The CalledProcessError object will have the 172 return code in the returncode attribute. 173 174 The arguments are the same as for the Popen constructor. Example: 175 176 check_call(["ls", "-l"]) 177 """ 178 retcode = call(*popenargs, **kwargs) 179 cmd = kwargs.get("args") 180 if cmd is None: 181 cmd = popenargs[0] 182 if retcode: 183 raise CalledProcessError(retcode, cmd) 184 return retcode
185 186 try: 187 from os.path import relpath 188 except ImportError: # python < 2.6 189 from os.path import curdir, abspath, sep, commonprefix, pardir, join
190 - def relpath(path, start=curdir):
191 """Return a relative version of a path""" 192 193 if not path: 194 raise ValueError("no path specified") 195 196 start_list = abspath(start).split(sep) 197 path_list = abspath(path).split(sep) 198 199 # Work out how much of the filepath is shared by start and path. 200 i = len(commonprefix([start_list, path_list])) 201 202 rel_list = [pardir] * (len(start_list)-i) + path_list[i:] 203 if not rel_list: 204 return curdir 205 return join(*rel_list)
206 207 208 # XXX don't know why tests don't pass if I don't do that : 209 _real_set, set = set, deprecated('set exists in builtins since py2.4')(set) 210 if (2, 5) <= sys.version_info[:2]: 211 InheritableSet = _real_set 212 else:
213 - class InheritableSet(_real_set):
214 """hacked resolving inheritancy issue from old style class in 2.4"""
215 - def __new__(cls, *args, **kwargs):
216 if args: 217 new_args = (args[0], ) 218 else: 219 new_args = () 220 obj = _real_set.__new__(cls, *new_args) 221 obj.__init__(*args, **kwargs) 222 return obj
223 224 # XXX shouldn't we remove this and just let 2to3 do his job ? 225 # range or xrange? 226 try: 227 range = xrange 228 except NameError: 229 range = range 230 231 # ConfigParser was renamed to the more-standard configparser 232 try: 233 import configparser 234 except ImportError: 235 import ConfigParser as configparser 236 237 try: 238 import json 239 except ImportError: 240 try: 241 import simplejson as json 242 except ImportError: 243 json = None 244