##// END OF EJS Templates
add py3compat.buffer_to_bytes_py2...
Min RK -
Show More
@@ -1,252 +1,260 b''
1 1 # coding: utf-8
2 2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
3 3 import functools
4 4 import os
5 5 import sys
6 6 import re
7 7 import types
8 8
9 9 from .encoding import DEFAULT_ENCODING
10 10
11 11 def no_code(x, encoding=None):
12 12 return x
13 13
14 14 def decode(s, encoding=None):
15 15 encoding = encoding or DEFAULT_ENCODING
16 16 return s.decode(encoding, "replace")
17 17
18 18 def encode(u, encoding=None):
19 19 encoding = encoding or DEFAULT_ENCODING
20 20 return u.encode(encoding, "replace")
21 21
22 22
23 23 def cast_unicode(s, encoding=None):
24 24 if isinstance(s, bytes):
25 25 return decode(s, encoding)
26 26 return s
27 27
28 28 def cast_bytes(s, encoding=None):
29 29 if not isinstance(s, bytes):
30 30 return encode(s, encoding)
31 31 return s
32 32
33 def buffer_to_bytes(buf):
34 """Cast a buffer object to bytes"""
35 if not isinstance(buf, bytes):
36 buf = bytes(buf)
37 return buf
38
33 39 def _modify_str_or_docstring(str_change_func):
34 40 @functools.wraps(str_change_func)
35 41 def wrapper(func_or_str):
36 42 if isinstance(func_or_str, string_types):
37 43 func = None
38 44 doc = func_or_str
39 45 else:
40 46 func = func_or_str
41 47 doc = func.__doc__
42 48
43 49 doc = str_change_func(doc)
44 50
45 51 if func:
46 52 func.__doc__ = doc
47 53 return func
48 54 return doc
49 55 return wrapper
50 56
51 57 def safe_unicode(e):
52 58 """unicode(e) with various fallbacks. Used for exceptions, which may not be
53 59 safe to call unicode() on.
54 60 """
55 61 try:
56 62 return unicode_type(e)
57 63 except UnicodeError:
58 64 pass
59 65
60 66 try:
61 67 return str_to_unicode(str(e))
62 68 except UnicodeError:
63 69 pass
64 70
65 71 try:
66 72 return str_to_unicode(repr(e))
67 73 except UnicodeError:
68 74 pass
69 75
70 76 return u'Unrecoverably corrupt evalue'
71 77
72 78 if sys.version_info[0] >= 3:
73 79 PY3 = True
74 80
75 81 # keep reference to builtin_mod because the kernel overrides that value
76 82 # to forward requests to a frontend.
77 83 def input(prompt=''):
78 84 return builtin_mod.input(prompt)
79 85
80 86 builtin_mod_name = "builtins"
81 87 import builtins as builtin_mod
82 88
83 89 str_to_unicode = no_code
84 90 unicode_to_str = no_code
85 91 str_to_bytes = encode
86 92 bytes_to_str = decode
87 93 cast_bytes_py2 = no_code
88 94 cast_unicode_py2 = no_code
95 buffer_to_bytes_py2 = no_code
89 96
90 97 string_types = (str,)
91 98 unicode_type = str
92 99
93 100 def isidentifier(s, dotted=False):
94 101 if dotted:
95 102 return all(isidentifier(a) for a in s.split("."))
96 103 return s.isidentifier()
97 104
98 105 xrange = range
99 106 def iteritems(d): return iter(d.items())
100 107 def itervalues(d): return iter(d.values())
101 108 getcwd = os.getcwd
102 109
103 110 MethodType = types.MethodType
104 111
105 112 def execfile(fname, glob, loc=None, compiler=None):
106 113 loc = loc if (loc is not None) else glob
107 114 with open(fname, 'rb') as f:
108 115 compiler = compiler or compile
109 116 exec(compiler(f.read(), fname, 'exec'), glob, loc)
110 117
111 118 # Refactor print statements in doctests.
112 119 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
113 120 def _print_statement_sub(match):
114 121 expr = match.groups('expr')
115 122 return "print(%s)" % expr
116 123
117 124 @_modify_str_or_docstring
118 125 def doctest_refactor_print(doc):
119 126 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
120 127 unfortunately doesn't pick up on our doctests.
121 128
122 129 Can accept a string or a function, so it can be used as a decorator."""
123 130 return _print_statement_re.sub(_print_statement_sub, doc)
124 131
125 132 # Abstract u'abc' syntax:
126 133 @_modify_str_or_docstring
127 134 def u_format(s):
128 135 """"{u}'abc'" --> "'abc'" (Python 3)
129 136
130 137 Accepts a string or a function, so it can be used as a decorator."""
131 138 return s.format(u='')
132 139
133 140 def get_closure(f):
134 141 """Get a function's closure attribute"""
135 142 return f.__closure__
136 143
137 144 else:
138 145 PY3 = False
139 146
140 147 # keep reference to builtin_mod because the kernel overrides that value
141 148 # to forward requests to a frontend.
142 149 def input(prompt=''):
143 150 return builtin_mod.raw_input(prompt)
144 151
145 152 builtin_mod_name = "__builtin__"
146 153 import __builtin__ as builtin_mod
147 154
148 155 str_to_unicode = decode
149 156 unicode_to_str = encode
150 157 str_to_bytes = no_code
151 158 bytes_to_str = no_code
152 159 cast_bytes_py2 = cast_bytes
153 160 cast_unicode_py2 = cast_unicode
161 buffer_to_bytes_py2 = buffer_to_bytes
154 162
155 163 string_types = (str, unicode)
156 164 unicode_type = unicode
157 165
158 166 import re
159 167 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
160 168 def isidentifier(s, dotted=False):
161 169 if dotted:
162 170 return all(isidentifier(a) for a in s.split("."))
163 171 return bool(_name_re.match(s))
164 172
165 173 xrange = xrange
166 174 def iteritems(d): return d.iteritems()
167 175 def itervalues(d): return d.itervalues()
168 176 getcwd = os.getcwdu
169 177
170 178 def MethodType(func, instance):
171 179 return types.MethodType(func, instance, type(instance))
172 180
173 181 def doctest_refactor_print(func_or_str):
174 182 return func_or_str
175 183
176 184 def get_closure(f):
177 185 """Get a function's closure attribute"""
178 186 return f.func_closure
179 187
180 188 # Abstract u'abc' syntax:
181 189 @_modify_str_or_docstring
182 190 def u_format(s):
183 191 """"{u}'abc'" --> "u'abc'" (Python 2)
184 192
185 193 Accepts a string or a function, so it can be used as a decorator."""
186 194 return s.format(u='u')
187 195
188 196 if sys.platform == 'win32':
189 197 def execfile(fname, glob=None, loc=None, compiler=None):
190 198 loc = loc if (loc is not None) else glob
191 199 scripttext = builtin_mod.open(fname).read()+ '\n'
192 200 # compile converts unicode filename to str assuming
193 201 # ascii. Let's do the conversion before calling compile
194 202 if isinstance(fname, unicode):
195 203 filename = unicode_to_str(fname)
196 204 else:
197 205 filename = fname
198 206 compiler = compiler or compile
199 207 exec(compiler(scripttext, filename, 'exec'), glob, loc)
200 208
201 209 else:
202 210 def execfile(fname, glob=None, loc=None, compiler=None):
203 211 if isinstance(fname, unicode):
204 212 filename = fname.encode(sys.getfilesystemencoding())
205 213 else:
206 214 filename = fname
207 215 where = [ns for ns in [glob, loc] if ns is not None]
208 216 if compiler is None:
209 217 builtin_mod.execfile(filename, *where)
210 218 else:
211 219 scripttext = builtin_mod.open(fname).read().rstrip() + '\n'
212 220 exec(compiler(scripttext, filename, 'exec'), glob, loc)
213 221
214 222
215 223 def annotate(**kwargs):
216 224 """Python 3 compatible function annotation for Python 2."""
217 225 if not kwargs:
218 226 raise ValueError('annotations must be provided as keyword arguments')
219 227 def dec(f):
220 228 if hasattr(f, '__annotations__'):
221 229 for k, v in kwargs.items():
222 230 f.__annotations__[k] = v
223 231 else:
224 232 f.__annotations__ = kwargs
225 233 return f
226 234 return dec
227 235
228 236
229 237 # Parts below taken from six:
230 238 # Copyright (c) 2010-2013 Benjamin Peterson
231 239 #
232 240 # Permission is hereby granted, free of charge, to any person obtaining a copy
233 241 # of this software and associated documentation files (the "Software"), to deal
234 242 # in the Software without restriction, including without limitation the rights
235 243 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
236 244 # copies of the Software, and to permit persons to whom the Software is
237 245 # furnished to do so, subject to the following conditions:
238 246 #
239 247 # The above copyright notice and this permission notice shall be included in all
240 248 # copies or substantial portions of the Software.
241 249 #
242 250 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
243 251 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
244 252 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
245 253 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
246 254 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
247 255 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
248 256 # SOFTWARE.
249 257
250 258 def with_metaclass(meta, *bases):
251 259 """Create a base class with a metaclass."""
252 260 return meta("_NewBase", bases, {})
General Comments 0
You need to be logged in to leave comments. Login now