##// END OF EJS Templates
Merge pull request #12009 from kousikmitra/master...
Matthias Bussonnier -
r25332:61a4f1f7 merge
parent child Browse files
Show More
@@ -1,250 +1,233 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Compatibility tricks for Python 3. Mainly to do with unicode.
2 """Compatibility tricks for Python 3. Mainly to do with unicode.
3
3
4 This file is deprecated and will be removed in a future version.
4 This file is deprecated and will be removed in a future version.
5 """
5 """
6 import functools
6 import functools
7 import os
7 import os
8 import sys
8 import sys
9 import re
9 import re
10 import shutil
10 import shutil
11 import types
11 import types
12 import platform
12 import platform
13
13
14 from .encoding import DEFAULT_ENCODING
14 from .encoding import DEFAULT_ENCODING
15
15
16 def no_code(x, encoding=None):
17 return x
18
16
19 def decode(s, encoding=None):
17 def decode(s, encoding=None):
20 encoding = encoding or DEFAULT_ENCODING
18 encoding = encoding or DEFAULT_ENCODING
21 return s.decode(encoding, "replace")
19 return s.decode(encoding, "replace")
22
20
23 def encode(u, encoding=None):
21 def encode(u, encoding=None):
24 encoding = encoding or DEFAULT_ENCODING
22 encoding = encoding or DEFAULT_ENCODING
25 return u.encode(encoding, "replace")
23 return u.encode(encoding, "replace")
26
24
27
25
28 def cast_unicode(s, encoding=None):
26 def cast_unicode(s, encoding=None):
29 if isinstance(s, bytes):
27 if isinstance(s, bytes):
30 return decode(s, encoding)
28 return decode(s, encoding)
31 return s
29 return s
32
30
33 def cast_bytes(s, encoding=None):
31 def cast_bytes(s, encoding=None):
34 if not isinstance(s, bytes):
32 if not isinstance(s, bytes):
35 return encode(s, encoding)
33 return encode(s, encoding)
36 return s
34 return s
37
35
38 def buffer_to_bytes(buf):
36 def buffer_to_bytes(buf):
39 """Cast a buffer object to bytes"""
37 """Cast a buffer object to bytes"""
40 if not isinstance(buf, bytes):
38 if not isinstance(buf, bytes):
41 buf = bytes(buf)
39 buf = bytes(buf)
42 return buf
40 return buf
43
41
44 def _modify_str_or_docstring(str_change_func):
42 def _modify_str_or_docstring(str_change_func):
45 @functools.wraps(str_change_func)
43 @functools.wraps(str_change_func)
46 def wrapper(func_or_str):
44 def wrapper(func_or_str):
47 if isinstance(func_or_str, string_types):
45 if isinstance(func_or_str, (str,)):
48 func = None
46 func = None
49 doc = func_or_str
47 doc = func_or_str
50 else:
48 else:
51 func = func_or_str
49 func = func_or_str
52 doc = func.__doc__
50 doc = func.__doc__
53
51
54 # PYTHONOPTIMIZE=2 strips docstrings, so they can disappear unexpectedly
52 # PYTHONOPTIMIZE=2 strips docstrings, so they can disappear unexpectedly
55 if doc is not None:
53 if doc is not None:
56 doc = str_change_func(doc)
54 doc = str_change_func(doc)
57
55
58 if func:
56 if func:
59 func.__doc__ = doc
57 func.__doc__ = doc
60 return func
58 return func
61 return doc
59 return doc
62 return wrapper
60 return wrapper
63
61
64 def safe_unicode(e):
62 def safe_unicode(e):
65 """unicode(e) with various fallbacks. Used for exceptions, which may not be
63 """unicode(e) with various fallbacks. Used for exceptions, which may not be
66 safe to call unicode() on.
64 safe to call unicode() on.
67 """
65 """
68 try:
66 try:
69 return unicode_type(e)
67 return str(e)
70 except UnicodeError:
68 except UnicodeError:
71 pass
69 pass
72
70
73 try:
71 try:
74 return str_to_unicode(str(e))
72 return repr(e)
75 except UnicodeError:
76 pass
77
78 try:
79 return str_to_unicode(repr(e))
80 except UnicodeError:
73 except UnicodeError:
81 pass
74 pass
82
75
83 return u'Unrecoverably corrupt evalue'
76 return u'Unrecoverably corrupt evalue'
84
77
85 # shutil.which from Python 3.4
78 # shutil.which from Python 3.4
86 def _shutil_which(cmd, mode=os.F_OK | os.X_OK, path=None):
79 def _shutil_which(cmd, mode=os.F_OK | os.X_OK, path=None):
87 """Given a command, mode, and a PATH string, return the path which
80 """Given a command, mode, and a PATH string, return the path which
88 conforms to the given mode on the PATH, or None if there is no such
81 conforms to the given mode on the PATH, or None if there is no such
89 file.
82 file.
90
83
91 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
84 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
92 of os.environ.get("PATH"), or can be overridden with a custom search
85 of os.environ.get("PATH"), or can be overridden with a custom search
93 path.
86 path.
94
87
95 This is a backport of shutil.which from Python 3.4
88 This is a backport of shutil.which from Python 3.4
96 """
89 """
97 # Check that a given file can be accessed with the correct mode.
90 # Check that a given file can be accessed with the correct mode.
98 # Additionally check that `file` is not a directory, as on Windows
91 # Additionally check that `file` is not a directory, as on Windows
99 # directories pass the os.access check.
92 # directories pass the os.access check.
100 def _access_check(fn, mode):
93 def _access_check(fn, mode):
101 return (os.path.exists(fn) and os.access(fn, mode)
94 return (os.path.exists(fn) and os.access(fn, mode)
102 and not os.path.isdir(fn))
95 and not os.path.isdir(fn))
103
96
104 # If we're given a path with a directory part, look it up directly rather
97 # If we're given a path with a directory part, look it up directly rather
105 # than referring to PATH directories. This includes checking relative to the
98 # than referring to PATH directories. This includes checking relative to the
106 # current directory, e.g. ./script
99 # current directory, e.g. ./script
107 if os.path.dirname(cmd):
100 if os.path.dirname(cmd):
108 if _access_check(cmd, mode):
101 if _access_check(cmd, mode):
109 return cmd
102 return cmd
110 return None
103 return None
111
104
112 if path is None:
105 if path is None:
113 path = os.environ.get("PATH", os.defpath)
106 path = os.environ.get("PATH", os.defpath)
114 if not path:
107 if not path:
115 return None
108 return None
116 path = path.split(os.pathsep)
109 path = path.split(os.pathsep)
117
110
118 if sys.platform == "win32":
111 if sys.platform == "win32":
119 # The current directory takes precedence on Windows.
112 # The current directory takes precedence on Windows.
120 if not os.curdir in path:
113 if not os.curdir in path:
121 path.insert(0, os.curdir)
114 path.insert(0, os.curdir)
122
115
123 # PATHEXT is necessary to check on Windows.
116 # PATHEXT is necessary to check on Windows.
124 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
117 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
125 # See if the given file matches any of the expected path extensions.
118 # See if the given file matches any of the expected path extensions.
126 # This will allow us to short circuit when given "python.exe".
119 # This will allow us to short circuit when given "python.exe".
127 # If it does match, only test that one, otherwise we have to try
120 # If it does match, only test that one, otherwise we have to try
128 # others.
121 # others.
129 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
122 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
130 files = [cmd]
123 files = [cmd]
131 else:
124 else:
132 files = [cmd + ext for ext in pathext]
125 files = [cmd + ext for ext in pathext]
133 else:
126 else:
134 # On other platforms you don't have things like PATHEXT to tell you
127 # On other platforms you don't have things like PATHEXT to tell you
135 # what file suffixes are executable, so just pass on cmd as-is.
128 # what file suffixes are executable, so just pass on cmd as-is.
136 files = [cmd]
129 files = [cmd]
137
130
138 seen = set()
131 seen = set()
139 for dir in path:
132 for dir in path:
140 normdir = os.path.normcase(dir)
133 normdir = os.path.normcase(dir)
141 if not normdir in seen:
134 if not normdir in seen:
142 seen.add(normdir)
135 seen.add(normdir)
143 for thefile in files:
136 for thefile in files:
144 name = os.path.join(dir, thefile)
137 name = os.path.join(dir, thefile)
145 if _access_check(name, mode):
138 if _access_check(name, mode):
146 return name
139 return name
147 return None
140 return None
148
141
149 PY3 = True
142 PY3 = True
150
143
151 # keep reference to builtin_mod because the kernel overrides that value
144 # keep reference to builtin_mod because the kernel overrides that value
152 # to forward requests to a frontend.
145 # to forward requests to a frontend.
153 def input(prompt=''):
146 def input(prompt=''):
154 return builtin_mod.input(prompt)
147 return builtin_mod.input(prompt)
155
148
156 builtin_mod_name = "builtins"
149 builtin_mod_name = "builtins"
157 import builtins as builtin_mod
150 import builtins as builtin_mod
158
151
159 str_to_unicode = no_code
160 unicode_to_str = no_code
161 str_to_bytes = encode
162 bytes_to_str = decode
163 cast_bytes_py2 = no_code
164 cast_unicode_py2 = no_code
165 buffer_to_bytes_py2 = no_code
166
167 string_types = (str,)
168 unicode_type = str
169
152
170 which = shutil.which
153 which = shutil.which
171
154
172 def isidentifier(s, dotted=False):
155 def isidentifier(s, dotted=False):
173 if dotted:
156 if dotted:
174 return all(isidentifier(a) for a in s.split("."))
157 return all(isidentifier(a) for a in s.split("."))
175 return s.isidentifier()
158 return s.isidentifier()
176
159
177 xrange = range
160 xrange = range
178 def iteritems(d): return iter(d.items())
161 def iteritems(d): return iter(d.items())
179 def itervalues(d): return iter(d.values())
162 def itervalues(d): return iter(d.values())
180 getcwd = os.getcwd
163 getcwd = os.getcwd
181
164
182 MethodType = types.MethodType
165 MethodType = types.MethodType
183
166
184 def execfile(fname, glob, loc=None, compiler=None):
167 def execfile(fname, glob, loc=None, compiler=None):
185 loc = loc if (loc is not None) else glob
168 loc = loc if (loc is not None) else glob
186 with open(fname, 'rb') as f:
169 with open(fname, 'rb') as f:
187 compiler = compiler or compile
170 compiler = compiler or compile
188 exec(compiler(f.read(), fname, 'exec'), glob, loc)
171 exec(compiler(f.read(), fname, 'exec'), glob, loc)
189
172
190 # Refactor print statements in doctests.
173 # Refactor print statements in doctests.
191 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
174 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
192 def _print_statement_sub(match):
175 def _print_statement_sub(match):
193 expr = match.groups('expr')
176 expr = match.groups('expr')
194 return "print(%s)" % expr
177 return "print(%s)" % expr
195
178
196 # Abstract u'abc' syntax:
179 # Abstract u'abc' syntax:
197 @_modify_str_or_docstring
180 @_modify_str_or_docstring
198 def u_format(s):
181 def u_format(s):
199 """"{u}'abc'" --> "'abc'" (Python 3)
182 """"{u}'abc'" --> "'abc'" (Python 3)
200
183
201 Accepts a string or a function, so it can be used as a decorator."""
184 Accepts a string or a function, so it can be used as a decorator."""
202 return s.format(u='')
185 return s.format(u='')
203
186
204 def get_closure(f):
187 def get_closure(f):
205 """Get a function's closure attribute"""
188 """Get a function's closure attribute"""
206 return f.__closure__
189 return f.__closure__
207
190
208
191
209 PY2 = not PY3
192 PY2 = not PY3
210 PYPY = platform.python_implementation() == "PyPy"
193 PYPY = platform.python_implementation() == "PyPy"
211
194
212
195
213 def annotate(**kwargs):
196 def annotate(**kwargs):
214 """Python 3 compatible function annotation for Python 2."""
197 """Python 3 compatible function annotation for Python 2."""
215 if not kwargs:
198 if not kwargs:
216 raise ValueError('annotations must be provided as keyword arguments')
199 raise ValueError('annotations must be provided as keyword arguments')
217 def dec(f):
200 def dec(f):
218 if hasattr(f, '__annotations__'):
201 if hasattr(f, '__annotations__'):
219 for k, v in kwargs.items():
202 for k, v in kwargs.items():
220 f.__annotations__[k] = v
203 f.__annotations__[k] = v
221 else:
204 else:
222 f.__annotations__ = kwargs
205 f.__annotations__ = kwargs
223 return f
206 return f
224 return dec
207 return dec
225
208
226
209
227 # Parts below taken from six:
210 # Parts below taken from six:
228 # Copyright (c) 2010-2013 Benjamin Peterson
211 # Copyright (c) 2010-2013 Benjamin Peterson
229 #
212 #
230 # Permission is hereby granted, free of charge, to any person obtaining a copy
213 # Permission is hereby granted, free of charge, to any person obtaining a copy
231 # of this software and associated documentation files (the "Software"), to deal
214 # of this software and associated documentation files (the "Software"), to deal
232 # in the Software without restriction, including without limitation the rights
215 # in the Software without restriction, including without limitation the rights
233 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
216 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
234 # copies of the Software, and to permit persons to whom the Software is
217 # copies of the Software, and to permit persons to whom the Software is
235 # furnished to do so, subject to the following conditions:
218 # furnished to do so, subject to the following conditions:
236 #
219 #
237 # The above copyright notice and this permission notice shall be included in all
220 # The above copyright notice and this permission notice shall be included in all
238 # copies or substantial portions of the Software.
221 # copies or substantial portions of the Software.
239 #
222 #
240 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
223 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
241 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
224 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
242 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
225 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
243 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
226 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
244 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
227 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
245 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
228 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
246 # SOFTWARE.
229 # SOFTWARE.
247
230
248 def with_metaclass(meta, *bases):
231 def with_metaclass(meta, *bases):
249 """Create a base class with a metaclass."""
232 """Create a base class with a metaclass."""
250 return meta("_NewBase", bases, {})
233 return meta("_NewBase", bases, {})
General Comments 0
You need to be logged in to leave comments. Login now