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