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