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