| Index: third_party/logilab/common/compat.py
|
| diff --git a/third_party/logilab/common/compat.py b/third_party/logilab/common/compat.py
|
| index f2eb5905601add2c30207278883b69d67934c3e1..8983ece98915f29254296326d2e127fc8adc9e24 100644
|
| --- a/third_party/logilab/common/compat.py
|
| +++ b/third_party/logilab/common/compat.py
|
| @@ -26,6 +26,7 @@ See another compatibility snippets from other projects:
|
| :mod:`unittest2.compatibility`
|
| """
|
|
|
| +from __future__ import generators
|
|
|
| __docformat__ = "restructuredtext en"
|
|
|
| @@ -34,8 +35,7 @@ import sys
|
| import types
|
| from warnings import warn
|
|
|
| -# not used here, but imported to preserve API
|
| -from six.moves import builtins
|
| +import __builtin__ as builtins # 2to3 will tranform '__builtin__' to 'builtins'
|
|
|
| if sys.version_info < (3, 0):
|
| str_to_bytes = str
|
| @@ -51,6 +51,15 @@ else:
|
| def str_encode(string, encoding):
|
| return str(string)
|
|
|
| +# XXX callable built-in seems back in all python versions
|
| +try:
|
| + callable = builtins.callable
|
| +except AttributeError:
|
| + from collections import Callable
|
| + def callable(something):
|
| + return isinstance(something, Callable)
|
| + del Callable
|
| +
|
| # See also http://bugs.python.org/issue11776
|
| if sys.version_info[0] == 3:
|
| def method_type(callable, instance, klass):
|
| @@ -60,6 +69,11 @@ else:
|
| # alias types otherwise
|
| method_type = types.MethodType
|
|
|
| +if sys.version_info < (3, 0):
|
| + raw_input = raw_input
|
| +else:
|
| + raw_input = input
|
| +
|
| # Pythons 2 and 3 differ on where to get StringIO
|
| if sys.version_info < (3, 0):
|
| from cStringIO import StringIO
|
| @@ -70,9 +84,160 @@ else:
|
| from io import FileIO, BytesIO, StringIO
|
| from imp import reload
|
|
|
| +# Where do pickles come from?
|
| +try:
|
| + import cPickle as pickle
|
| +except ImportError:
|
| + import pickle
|
| +
|
| from logilab.common.deprecation import deprecated
|
|
|
| -# Other projects import these from here, keep providing them for
|
| -# backwards compat
|
| -any = deprecated('use builtin "any"')(any)
|
| -all = deprecated('use builtin "all"')(all)
|
| +from itertools import izip, chain, imap
|
| +if sys.version_info < (3, 0):# 2to3 will remove the imports
|
| + izip = deprecated('izip exists in itertools since py2.3')(izip)
|
| + imap = deprecated('imap exists in itertools since py2.3')(imap)
|
| +chain = deprecated('chain exists in itertools since py2.3')(chain)
|
| +
|
| +sum = deprecated('sum exists in builtins since py2.3')(sum)
|
| +enumerate = deprecated('enumerate exists in builtins since py2.3')(enumerate)
|
| +frozenset = deprecated('frozenset exists in builtins since py2.4')(frozenset)
|
| +reversed = deprecated('reversed exists in builtins since py2.4')(reversed)
|
| +sorted = deprecated('sorted exists in builtins since py2.4')(sorted)
|
| +max = deprecated('max exists in builtins since py2.4')(max)
|
| +
|
| +
|
| +# Python2.5 builtins
|
| +try:
|
| + any = any
|
| + all = all
|
| +except NameError:
|
| + def any(iterable):
|
| + """any(iterable) -> bool
|
| +
|
| + Return True if bool(x) is True for any x in the iterable.
|
| + """
|
| + for elt in iterable:
|
| + if elt:
|
| + return True
|
| + return False
|
| +
|
| + def all(iterable):
|
| + """all(iterable) -> bool
|
| +
|
| + Return True if bool(x) is True for all values x in the iterable.
|
| + """
|
| + for elt in iterable:
|
| + if not elt:
|
| + return False
|
| + return True
|
| +
|
| +
|
| +# Python2.5 subprocess added functions and exceptions
|
| +try:
|
| + from subprocess import Popen
|
| +except ImportError:
|
| + # gae or python < 2.3
|
| +
|
| + class CalledProcessError(Exception):
|
| + """This exception is raised when a process run by check_call() returns
|
| + a non-zero exit status. The exit status will be stored in the
|
| + returncode attribute."""
|
| + def __init__(self, returncode, cmd):
|
| + self.returncode = returncode
|
| + self.cmd = cmd
|
| + def __str__(self):
|
| + return "Command '%s' returned non-zero exit status %d" % (self.cmd,
|
| + self.returncode)
|
| +
|
| + def call(*popenargs, **kwargs):
|
| + """Run command with arguments. Wait for command to complete, then
|
| + return the returncode attribute.
|
| +
|
| + The arguments are the same as for the Popen constructor. Example:
|
| +
|
| + retcode = call(["ls", "-l"])
|
| + """
|
| + # workaround: subprocess.Popen(cmd, stdout=sys.stdout) fails
|
| + # see http://bugs.python.org/issue1531862
|
| + if "stdout" in kwargs:
|
| + fileno = kwargs.get("stdout").fileno()
|
| + del kwargs['stdout']
|
| + return Popen(stdout=os.dup(fileno), *popenargs, **kwargs).wait()
|
| + return Popen(*popenargs, **kwargs).wait()
|
| +
|
| + def check_call(*popenargs, **kwargs):
|
| + """Run command with arguments. Wait for command to complete. If
|
| + the exit code was zero then return, otherwise raise
|
| + CalledProcessError. The CalledProcessError object will have the
|
| + return code in the returncode attribute.
|
| +
|
| + The arguments are the same as for the Popen constructor. Example:
|
| +
|
| + check_call(["ls", "-l"])
|
| + """
|
| + retcode = call(*popenargs, **kwargs)
|
| + cmd = kwargs.get("args")
|
| + if cmd is None:
|
| + cmd = popenargs[0]
|
| + if retcode:
|
| + raise CalledProcessError(retcode, cmd)
|
| + return retcode
|
| +
|
| +try:
|
| + from os.path import relpath
|
| +except ImportError: # python < 2.6
|
| + from os.path import curdir, abspath, sep, commonprefix, pardir, join
|
| + def relpath(path, start=curdir):
|
| + """Return a relative version of a path"""
|
| +
|
| + if not path:
|
| + raise ValueError("no path specified")
|
| +
|
| + start_list = abspath(start).split(sep)
|
| + path_list = abspath(path).split(sep)
|
| +
|
| + # Work out how much of the filepath is shared by start and path.
|
| + i = len(commonprefix([start_list, path_list]))
|
| +
|
| + rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
|
| + if not rel_list:
|
| + return curdir
|
| + return join(*rel_list)
|
| +
|
| +
|
| +# XXX don't know why tests don't pass if I don't do that :
|
| +_real_set, set = set, deprecated('set exists in builtins since py2.4')(set)
|
| +if (2, 5) <= sys.version_info[:2]:
|
| + InheritableSet = _real_set
|
| +else:
|
| + class InheritableSet(_real_set):
|
| + """hacked resolving inheritancy issue from old style class in 2.4"""
|
| + def __new__(cls, *args, **kwargs):
|
| + if args:
|
| + new_args = (args[0], )
|
| + else:
|
| + new_args = ()
|
| + obj = _real_set.__new__(cls, *new_args)
|
| + obj.__init__(*args, **kwargs)
|
| + return obj
|
| +
|
| +# XXX shouldn't we remove this and just let 2to3 do his job ?
|
| +# range or xrange?
|
| +try:
|
| + range = xrange
|
| +except NameError:
|
| + range = range
|
| +
|
| +# ConfigParser was renamed to the more-standard configparser
|
| +try:
|
| + import configparser
|
| +except ImportError:
|
| + import ConfigParser as configparser
|
| +
|
| +try:
|
| + import json
|
| +except ImportError:
|
| + try:
|
| + import simplejson as json
|
| + except ImportError:
|
| + json = None
|
|
|