| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- # pylint: disable=E0601,W0622,W0611
- # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
- # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
- #
- # This file is part of logilab-common.
- #
- # logilab-common is free software: you can redistribute it and/or modify it under
- # the terms of the GNU Lesser General Public License as published by the Free
- # Software Foundation, either version 2.1 of the License, or (at your option) any
- # later version.
- #
- # logilab-common is distributed in the hope that it will be useful, but WITHOUT
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- # details.
- #
- # You should have received a copy of the GNU Lesser General Public License along
- # with logilab-common. If not, see <http://www.gnu.org/licenses/>.
- """Wrappers around some builtins introduced in python 2.3, 2.4 and
- 2.5, making them available in for earlier versions of python.
- See another compatibility snippets from other projects:
- :mod:`lib2to3.fixes`
- :mod:`coverage.backward`
- :mod:`unittest2.compatibility`
- """
- from __future__ import generators
- __docformat__ = "restructuredtext en"
- import os
- import sys
- import types
- from warnings import warn
- import __builtin__ as builtins # 2to3 will tranform '__builtin__' to 'builtins'
- if sys.version_info < (3, 0):
- str_to_bytes = str
- def str_encode(string, encoding):
- if isinstance(string, unicode):
- return string.encode(encoding)
- return str(string)
- else:
- def str_to_bytes(string):
- return str.encode(string)
- # we have to ignore the encoding in py3k to be able to write a string into a
- # TextIOWrapper or like object (which expect an unicode string)
- 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):
- # api change. klass is no more considered
- return types.MethodType(callable, instance)
- 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
- FileIO = file
- BytesIO = StringIO
- reload = reload
- 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
- 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
|