##// END OF EJS Templates
Backport PR #4132: Fixed name error bug in function safe_unicode in module py3compat.
MinRK -
Show More
@@ -1,204 +1,204
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 __builtin__
3 import __builtin__
4 import functools
4 import functools
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 orig_open = open
11 orig_open = open
12
12
13 def no_code(x, encoding=None):
13 def no_code(x, encoding=None):
14 return x
14 return x
15
15
16 def decode(s, encoding=None):
16 def decode(s, encoding=None):
17 encoding = encoding or DEFAULT_ENCODING
17 encoding = encoding or DEFAULT_ENCODING
18 return s.decode(encoding, "replace")
18 return s.decode(encoding, "replace")
19
19
20 def encode(u, encoding=None):
20 def encode(u, encoding=None):
21 encoding = encoding or DEFAULT_ENCODING
21 encoding = encoding or DEFAULT_ENCODING
22 return u.encode(encoding, "replace")
22 return u.encode(encoding, "replace")
23
23
24
24
25 def cast_unicode(s, encoding=None):
25 def cast_unicode(s, encoding=None):
26 if isinstance(s, bytes):
26 if isinstance(s, bytes):
27 return decode(s, encoding)
27 return decode(s, encoding)
28 return s
28 return s
29
29
30 def cast_bytes(s, encoding=None):
30 def cast_bytes(s, encoding=None):
31 if not isinstance(s, bytes):
31 if not isinstance(s, bytes):
32 return encode(s, encoding)
32 return encode(s, encoding)
33 return s
33 return s
34
34
35 def _modify_str_or_docstring(str_change_func):
35 def _modify_str_or_docstring(str_change_func):
36 @functools.wraps(str_change_func)
36 @functools.wraps(str_change_func)
37 def wrapper(func_or_str):
37 def wrapper(func_or_str):
38 if isinstance(func_or_str, basestring):
38 if isinstance(func_or_str, basestring):
39 func = None
39 func = None
40 doc = func_or_str
40 doc = func_or_str
41 else:
41 else:
42 func = func_or_str
42 func = func_or_str
43 doc = func.__doc__
43 doc = func.__doc__
44
44
45 doc = str_change_func(doc)
45 doc = str_change_func(doc)
46
46
47 if func:
47 if func:
48 func.__doc__ = doc
48 func.__doc__ = doc
49 return func
49 return func
50 return doc
50 return doc
51 return wrapper
51 return wrapper
52
52
53 def safe_unicode(e):
53 def safe_unicode(e):
54 """unicode(e) with various fallbacks. Used for exceptions, which may not be
54 """unicode(e) with various fallbacks. Used for exceptions, which may not be
55 safe to call unicode() on.
55 safe to call unicode() on.
56 """
56 """
57 try:
57 try:
58 return unicode(e)
58 return unicode(e)
59 except UnicodeError:
59 except UnicodeError:
60 pass
60 pass
61
61
62 try:
62 try:
63 return py3compat.str_to_unicode(str(e))
63 return str_to_unicode(str(e))
64 except UnicodeError:
64 except UnicodeError:
65 pass
65 pass
66
66
67 try:
67 try:
68 return py3compat.str_to_unicode(repr(e))
68 return str_to_unicode(repr(e))
69 except UnicodeError:
69 except UnicodeError:
70 pass
70 pass
71
71
72 return u'Unrecoverably corrupt evalue'
72 return u'Unrecoverably corrupt evalue'
73
73
74 if sys.version_info[0] >= 3:
74 if sys.version_info[0] >= 3:
75 PY3 = True
75 PY3 = True
76
76
77 input = input
77 input = input
78 builtin_mod_name = "builtins"
78 builtin_mod_name = "builtins"
79
79
80 str_to_unicode = no_code
80 str_to_unicode = no_code
81 unicode_to_str = no_code
81 unicode_to_str = no_code
82 str_to_bytes = encode
82 str_to_bytes = encode
83 bytes_to_str = decode
83 bytes_to_str = decode
84 cast_bytes_py2 = no_code
84 cast_bytes_py2 = no_code
85
85
86 string_types = (str,)
86 string_types = (str,)
87
87
88 def isidentifier(s, dotted=False):
88 def isidentifier(s, dotted=False):
89 if dotted:
89 if dotted:
90 return all(isidentifier(a) for a in s.split("."))
90 return all(isidentifier(a) for a in s.split("."))
91 return s.isidentifier()
91 return s.isidentifier()
92
92
93 open = orig_open
93 open = orig_open
94
94
95 MethodType = types.MethodType
95 MethodType = types.MethodType
96
96
97 def execfile(fname, glob, loc=None):
97 def execfile(fname, glob, loc=None):
98 loc = loc if (loc is not None) else glob
98 loc = loc if (loc is not None) else glob
99 with open(fname, 'rb') as f:
99 with open(fname, 'rb') as f:
100 exec compile(f.read(), fname, 'exec') in glob, loc
100 exec compile(f.read(), fname, 'exec') in glob, loc
101
101
102 # Refactor print statements in doctests.
102 # Refactor print statements in doctests.
103 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
103 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
104 def _print_statement_sub(match):
104 def _print_statement_sub(match):
105 expr = match.groups('expr')
105 expr = match.groups('expr')
106 return "print(%s)" % expr
106 return "print(%s)" % expr
107
107
108 @_modify_str_or_docstring
108 @_modify_str_or_docstring
109 def doctest_refactor_print(doc):
109 def doctest_refactor_print(doc):
110 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
110 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
111 unfortunately doesn't pick up on our doctests.
111 unfortunately doesn't pick up on our doctests.
112
112
113 Can accept a string or a function, so it can be used as a decorator."""
113 Can accept a string or a function, so it can be used as a decorator."""
114 return _print_statement_re.sub(_print_statement_sub, doc)
114 return _print_statement_re.sub(_print_statement_sub, doc)
115
115
116 # Abstract u'abc' syntax:
116 # Abstract u'abc' syntax:
117 @_modify_str_or_docstring
117 @_modify_str_or_docstring
118 def u_format(s):
118 def u_format(s):
119 """"{u}'abc'" --> "'abc'" (Python 3)
119 """"{u}'abc'" --> "'abc'" (Python 3)
120
120
121 Accepts a string or a function, so it can be used as a decorator."""
121 Accepts a string or a function, so it can be used as a decorator."""
122 return s.format(u='')
122 return s.format(u='')
123
123
124 else:
124 else:
125 PY3 = False
125 PY3 = False
126
126
127 input = raw_input
127 input = raw_input
128 builtin_mod_name = "__builtin__"
128 builtin_mod_name = "__builtin__"
129
129
130 str_to_unicode = decode
130 str_to_unicode = decode
131 unicode_to_str = encode
131 unicode_to_str = encode
132 str_to_bytes = no_code
132 str_to_bytes = no_code
133 bytes_to_str = no_code
133 bytes_to_str = no_code
134 cast_bytes_py2 = cast_bytes
134 cast_bytes_py2 = cast_bytes
135
135
136 string_types = (str, unicode)
136 string_types = (str, unicode)
137
137
138 import re
138 import re
139 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
139 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
140 def isidentifier(s, dotted=False):
140 def isidentifier(s, dotted=False):
141 if dotted:
141 if dotted:
142 return all(isidentifier(a) for a in s.split("."))
142 return all(isidentifier(a) for a in s.split("."))
143 return bool(_name_re.match(s))
143 return bool(_name_re.match(s))
144
144
145 class open(object):
145 class open(object):
146 """Wrapper providing key part of Python 3 open() interface."""
146 """Wrapper providing key part of Python 3 open() interface."""
147 def __init__(self, fname, mode="r", encoding="utf-8"):
147 def __init__(self, fname, mode="r", encoding="utf-8"):
148 self.f = orig_open(fname, mode)
148 self.f = orig_open(fname, mode)
149 self.enc = encoding
149 self.enc = encoding
150
150
151 def write(self, s):
151 def write(self, s):
152 return self.f.write(s.encode(self.enc))
152 return self.f.write(s.encode(self.enc))
153
153
154 def read(self, size=-1):
154 def read(self, size=-1):
155 return self.f.read(size).decode(self.enc)
155 return self.f.read(size).decode(self.enc)
156
156
157 def close(self):
157 def close(self):
158 return self.f.close()
158 return self.f.close()
159
159
160 def __enter__(self):
160 def __enter__(self):
161 return self
161 return self
162
162
163 def __exit__(self, etype, value, traceback):
163 def __exit__(self, etype, value, traceback):
164 self.f.close()
164 self.f.close()
165
165
166 def MethodType(func, instance):
166 def MethodType(func, instance):
167 return types.MethodType(func, instance, type(instance))
167 return types.MethodType(func, instance, type(instance))
168
168
169 # don't override system execfile on 2.x:
169 # don't override system execfile on 2.x:
170 execfile = execfile
170 execfile = execfile
171
171
172 def doctest_refactor_print(func_or_str):
172 def doctest_refactor_print(func_or_str):
173 return func_or_str
173 return func_or_str
174
174
175
175
176 # Abstract u'abc' syntax:
176 # Abstract u'abc' syntax:
177 @_modify_str_or_docstring
177 @_modify_str_or_docstring
178 def u_format(s):
178 def u_format(s):
179 """"{u}'abc'" --> "u'abc'" (Python 2)
179 """"{u}'abc'" --> "u'abc'" (Python 2)
180
180
181 Accepts a string or a function, so it can be used as a decorator."""
181 Accepts a string or a function, so it can be used as a decorator."""
182 return s.format(u='u')
182 return s.format(u='u')
183
183
184 if sys.platform == 'win32':
184 if sys.platform == 'win32':
185 def execfile(fname, glob=None, loc=None):
185 def execfile(fname, glob=None, loc=None):
186 loc = loc if (loc is not None) else glob
186 loc = loc if (loc is not None) else glob
187 # The rstrip() is necessary b/c trailing whitespace in files will
187 # The rstrip() is necessary b/c trailing whitespace in files will
188 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
188 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
189 # but we still support 2.6). See issue 1027.
189 # but we still support 2.6). See issue 1027.
190 scripttext = __builtin__.open(fname).read().rstrip() + '\n'
190 scripttext = __builtin__.open(fname).read().rstrip() + '\n'
191 # compile converts unicode filename to str assuming
191 # compile converts unicode filename to str assuming
192 # ascii. Let's do the conversion before calling compile
192 # ascii. Let's do the conversion before calling compile
193 if isinstance(fname, unicode):
193 if isinstance(fname, unicode):
194 filename = unicode_to_str(fname)
194 filename = unicode_to_str(fname)
195 else:
195 else:
196 filename = fname
196 filename = fname
197 exec compile(scripttext, filename, 'exec') in glob, loc
197 exec compile(scripttext, filename, 'exec') in glob, loc
198 else:
198 else:
199 def execfile(fname, *where):
199 def execfile(fname, *where):
200 if isinstance(fname, unicode):
200 if isinstance(fname, unicode):
201 filename = fname.encode(sys.getfilesystemencoding())
201 filename = fname.encode(sys.getfilesystemencoding())
202 else:
202 else:
203 filename = fname
203 filename = fname
204 __builtin__.execfile(filename, *where)
204 __builtin__.execfile(filename, *where)
General Comments 0
You need to be logged in to leave comments. Login now