##// END OF EJS Templates
Add function to handle u'abc' (Python 2) vs. 'abc' (Python 3) in doctests and similar.
Thomas Kluyver -
Show More
@@ -1,127 +1,151 b''
1 1 # coding: utf-8
2 2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
3 import functools
3 4 import sys
4 5 import re
5 6 import types
6 7
7 8 orig_open = open
8 9
9 10 def no_code(x, encoding=None):
10 11 return x
11 12
12 13 def decode(s, encoding=None):
13 14 encoding = encoding or sys.stdin.encoding or sys.getdefaultencoding()
14 15 return s.decode(encoding, "replace")
15 16
16 17 def encode(u, encoding=None):
17 18 encoding = encoding or sys.stdin.encoding or sys.getdefaultencoding()
18 19 return u.encode(encoding, "replace")
19 20
20 21 def cast_unicode(s, encoding=None):
21 22 if isinstance(s, bytes):
22 23 return decode(s, encoding)
23 24 return s
24 25
25 26 def cast_bytes(s, encoding=None):
26 27 if not isinstance(s, bytes):
27 28 return encode(s, encoding)
28 29 return s
29 30
31 def _modify_str_or_docstring(str_change_func):
32 @functools.wraps(str_change_func)
33 def wrapper(func_or_str):
34 if isinstance(func_or_str, str):
35 func = None
36 doc = func_or_str
37 else:
38 func = func_or_str
39 doc = func.__doc__
40
41 doc = str_change_func(doc)
42
43 if func:
44 func.__doc__ = doc
45 return func
46 return doc
47 return wrapper
48
30 49 if sys.version_info[0] >= 3:
31 50 PY3 = True
32 51
33 52 input = input
34 53 builtin_mod_name = "builtins"
35 54
36 55 str_to_unicode = no_code
37 56 unicode_to_str = no_code
38 57 str_to_bytes = encode
39 58 bytes_to_str = decode
40 59 cast_bytes_py2 = no_code
41 60
42 61 def isidentifier(s, dotted=False):
43 62 if dotted:
44 63 return all(isidentifier(a) for a in s.split("."))
45 64 return s.isidentifier()
46 65
47 66 open = orig_open
48 67
49 68 MethodType = types.MethodType
50 69
51 70 def execfile(fname, glob, loc=None):
52 71 loc = loc if (loc is not None) else glob
53 72 exec compile(open(fname).read(), fname, 'exec') in glob, loc
54 73
55 74 # Refactor print statements in doctests.
56 75 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
57 76 def _print_statement_sub(match):
58 77 expr = match.groups('expr')
59 78 return "print(%s)" % expr
60 def doctest_refactor_print(func_or_str):
79
80 @_modify_str_or_docstring
81 def doctest_refactor_print(doc):
61 82 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
62 83 unfortunately doesn't pick up on our doctests.
63 84
64 85 Can accept a string or a function, so it can be used as a decorator."""
65 if isinstance(func_or_str, str):
66 func = None
67 doc = func_or_str
68 else:
69 func = func_or_str
70 doc = func.__doc__
71 doc = _print_statement_re.sub(_print_statement_sub, doc)
72
73 if func:
74 func.__doc__ = doc
75 return func
76 return doc
86 return _print_statement_re.sub(_print_statement_sub, doc)
87
88 # Abstract u'abc' syntax:
89 @_modify_str_or_docstring
90 def u_format(s):
91 """"{u}'abc'" --> "'abc'" (Python 3)
77 92
93 Accepts a string or a function, so it can be used as a decorator."""
94 return s.format(u='')
78 95
79 96 else:
80 97 PY3 = False
81 98
82 99 input = raw_input
83 100 builtin_mod_name = "__builtin__"
84 101
85 102 str_to_unicode = decode
86 103 unicode_to_str = encode
87 104 str_to_bytes = no_code
88 105 bytes_to_str = no_code
89 106 cast_bytes_py2 = cast_bytes
90 107
91 108 import re
92 109 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
93 110 def isidentifier(s, dotted=False):
94 111 if dotted:
95 112 return all(isidentifier(a) for a in s.split("."))
96 113 return bool(_name_re.match(s))
97 114
98 115 class open(object):
99 116 """Wrapper providing key part of Python 3 open() interface."""
100 117 def __init__(self, fname, mode="r", encoding="utf-8"):
101 118 self.f = orig_open(fname, mode)
102 119 self.enc = encoding
103 120
104 121 def write(self, s):
105 122 return self.f.write(s.encode(self.enc))
106 123
107 124 def read(self, size=-1):
108 125 return self.f.read(size).decode(self.enc)
109 126
110 127 def close(self):
111 128 return self.f.close()
112 129
113 130 def __enter__(self):
114 131 return self
115 132
116 133 def __exit__(self, etype, value, traceback):
117 134 self.f.close()
118 135
119 136 def MethodType(func, instance):
120 137 return types.MethodType(func, instance, type(instance))
121 138
122 139 # don't override system execfile on 2.x:
123 140 execfile = execfile
124 141
125 142 def doctest_refactor_print(func_or_str):
126 143 return func_or_str
127 144
145 # Abstract u'abc' syntax:
146 @_modify_str_or_docstring
147 def u_format(s):
148 """"{u}'abc'" --> "u'abc'" (Python 2)
149
150 Accepts a string or a function, so it can be used as a decorator."""
151 return s.format(u='u')
General Comments 0
You need to be logged in to leave comments. Login now