OLD | NEW |
1 # pylint: disable=E0601,W0622,W0611 | 1 # pylint: disable=E0601,W0622,W0611 |
2 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 2 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
3 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 3 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
4 # | 4 # |
5 # This file is part of logilab-common. | 5 # This file is part of logilab-common. |
6 # | 6 # |
7 # logilab-common is free software: you can redistribute it and/or modify it unde
r | 7 # logilab-common is free software: you can redistribute it and/or modify it unde
r |
8 # the terms of the GNU Lesser General Public License as published by the Free | 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) an
y | 9 # Software Foundation, either version 2.1 of the License, or (at your option) an
y |
10 # later version. | 10 # later version. |
11 # | 11 # |
12 # logilab-common is distributed in the hope that it will be useful, but WITHOUT | 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 | 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 | 14 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
15 # details. | 15 # details. |
16 # | 16 # |
17 # You should have received a copy of the GNU Lesser General Public License along | 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/>. | 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 | 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. | 20 2.5, making them available in for earlier versions of python. |
21 | 21 |
22 See another compatibility snippets from other projects: | 22 See another compatibility snippets from other projects: |
23 | 23 |
24 :mod:`lib2to3.fixes` | 24 :mod:`lib2to3.fixes` |
25 :mod:`coverage.backward` | 25 :mod:`coverage.backward` |
26 :mod:`unittest2.compatibility` | 26 :mod:`unittest2.compatibility` |
27 """ | 27 """ |
28 | 28 |
29 from __future__ import generators | |
30 | 29 |
31 __docformat__ = "restructuredtext en" | 30 __docformat__ = "restructuredtext en" |
32 | 31 |
33 import os | 32 import os |
34 import sys | 33 import sys |
35 import types | 34 import types |
36 from warnings import warn | 35 from warnings import warn |
37 | 36 |
38 import __builtin__ as builtins # 2to3 will tranform '__builtin__' to 'builtins' | 37 # not used here, but imported to preserve API |
| 38 from six.moves import builtins |
39 | 39 |
40 if sys.version_info < (3, 0): | 40 if sys.version_info < (3, 0): |
41 str_to_bytes = str | 41 str_to_bytes = str |
42 def str_encode(string, encoding): | 42 def str_encode(string, encoding): |
43 if isinstance(string, unicode): | 43 if isinstance(string, unicode): |
44 return string.encode(encoding) | 44 return string.encode(encoding) |
45 return str(string) | 45 return str(string) |
46 else: | 46 else: |
47 def str_to_bytes(string): | 47 def str_to_bytes(string): |
48 return str.encode(string) | 48 return str.encode(string) |
49 # we have to ignore the encoding in py3k to be able to write a string into a | 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) | 50 # TextIOWrapper or like object (which expect an unicode string) |
51 def str_encode(string, encoding): | 51 def str_encode(string, encoding): |
52 return str(string) | 52 return str(string) |
53 | 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 | 54 # See also http://bugs.python.org/issue11776 |
64 if sys.version_info[0] == 3: | 55 if sys.version_info[0] == 3: |
65 def method_type(callable, instance, klass): | 56 def method_type(callable, instance, klass): |
66 # api change. klass is no more considered | 57 # api change. klass is no more considered |
67 return types.MethodType(callable, instance) | 58 return types.MethodType(callable, instance) |
68 else: | 59 else: |
69 # alias types otherwise | 60 # alias types otherwise |
70 method_type = types.MethodType | 61 method_type = types.MethodType |
71 | 62 |
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 | 63 # Pythons 2 and 3 differ on where to get StringIO |
78 if sys.version_info < (3, 0): | 64 if sys.version_info < (3, 0): |
79 from cStringIO import StringIO | 65 from cStringIO import StringIO |
80 FileIO = file | 66 FileIO = file |
81 BytesIO = StringIO | 67 BytesIO = StringIO |
82 reload = reload | 68 reload = reload |
83 else: | 69 else: |
84 from io import FileIO, BytesIO, StringIO | 70 from io import FileIO, BytesIO, StringIO |
85 from imp import reload | 71 from imp import reload |
86 | 72 |
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 | 73 from logilab.common.deprecation import deprecated |
94 | 74 |
95 from itertools import izip, chain, imap | 75 # Other projects import these from here, keep providing them for |
96 if sys.version_info < (3, 0):# 2to3 will remove the imports | 76 # backwards compat |
97 izip = deprecated('izip exists in itertools since py2.3')(izip) | 77 any = deprecated('use builtin "any"')(any) |
98 imap = deprecated('imap exists in itertools since py2.3')(imap) | 78 all = deprecated('use builtin "all"')(all) |
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 | |
OLD | NEW |