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