##// END OF EJS Templates
Remove Python 2 shim....
Matthias Bussonnier -
Show More
@@ -1,80 +1,77 b''
1 """Tests for the ipdoctest machinery itself.
1 """Tests for the ipdoctest machinery itself.
2
2
3 Note: in a file named test_X, functions whose only test is their docstring (as
3 Note: in a file named test_X, functions whose only test is their docstring (as
4 a doctest) and which have no test functionality of their own, should be called
4 a doctest) and which have no test functionality of their own, should be called
5 'doctest_foo' instead of 'test_foo', otherwise they get double-counted (the
5 'doctest_foo' instead of 'test_foo', otherwise they get double-counted (the
6 empty function call is counted as a test, which just inflates tests numbers
6 empty function call is counted as a test, which just inflates tests numbers
7 artificially).
7 artificially).
8 """
8 """
9 from IPython.utils.py3compat import doctest_refactor_print
9 from IPython.utils.py3compat import doctest_refactor_print
10
10
11 @doctest_refactor_print
12 def doctest_simple():
11 def doctest_simple():
13 """ipdoctest must handle simple inputs
12 """ipdoctest must handle simple inputs
14
13
15 In [1]: 1
14 In [1]: 1
16 Out[1]: 1
15 Out[1]: 1
17
16
18 In [2]: print 1
17 In [2]: print(1)
19 1
18 1
20 """
19 """
21
20
22 @doctest_refactor_print
23 def doctest_multiline1():
21 def doctest_multiline1():
24 """The ipdoctest machinery must handle multiline examples gracefully.
22 """The ipdoctest machinery must handle multiline examples gracefully.
25
23
26 In [2]: for i in range(4):
24 In [2]: for i in range(4):
27 ...: print i
25 ...: print(i)
28 ...:
26 ...:
29 0
27 0
30 1
28 1
31 2
29 2
32 3
30 3
33 """
31 """
34
32
35 @doctest_refactor_print
36 def doctest_multiline2():
33 def doctest_multiline2():
37 """Multiline examples that define functions and print output.
34 """Multiline examples that define functions and print output.
38
35
39 In [7]: def f(x):
36 In [7]: def f(x):
40 ...: return x+1
37 ...: return x+1
41 ...:
38 ...:
42
39
43 In [8]: f(1)
40 In [8]: f(1)
44 Out[8]: 2
41 Out[8]: 2
45
42
46 In [9]: def g(x):
43 In [9]: def g(x):
47 ...: print 'x is:',x
44 ...: print('x is:',x)
48 ...:
45 ...:
49
46
50 In [10]: g(1)
47 In [10]: g(1)
51 x is: 1
48 x is: 1
52
49
53 In [11]: g('hello')
50 In [11]: g('hello')
54 x is: hello
51 x is: hello
55 """
52 """
56
53
57
54
58 def doctest_multiline3():
55 def doctest_multiline3():
59 """Multiline examples with blank lines.
56 """Multiline examples with blank lines.
60
57
61 In [12]: def h(x):
58 In [12]: def h(x):
62 ....: if x>1:
59 ....: if x>1:
63 ....: return x**2
60 ....: return x**2
64 ....: # To leave a blank line in the input, you must mark it
61 ....: # To leave a blank line in the input, you must mark it
65 ....: # with a comment character:
62 ....: # with a comment character:
66 ....: #
63 ....: #
67 ....: # otherwise the doctest parser gets confused.
64 ....: # otherwise the doctest parser gets confused.
68 ....: else:
65 ....: else:
69 ....: return -1
66 ....: return -1
70 ....:
67 ....:
71
68
72 In [13]: h(5)
69 In [13]: h(5)
73 Out[13]: 25
70 Out[13]: 25
74
71
75 In [14]: h(1)
72 In [14]: h(1)
76 Out[14]: -1
73 Out[14]: -1
77
74
78 In [15]: h(0)
75 In [15]: h(0)
79 Out[15]: -1
76 Out[15]: -1
80 """
77 """
@@ -1,258 +1,250 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
3
4 This file is deprecated and will be removed in a future version.
4 This file is deprecated and will be removed in a future version.
5 """
5 """
6 import functools
6 import functools
7 import os
7 import os
8 import sys
8 import sys
9 import re
9 import re
10 import shutil
10 import shutil
11 import types
11 import types
12 import platform
12 import platform
13
13
14 from .encoding import DEFAULT_ENCODING
14 from .encoding import DEFAULT_ENCODING
15
15
16 def no_code(x, encoding=None):
16 def no_code(x, encoding=None):
17 return x
17 return x
18
18
19 def decode(s, encoding=None):
19 def decode(s, encoding=None):
20 encoding = encoding or DEFAULT_ENCODING
20 encoding = encoding or DEFAULT_ENCODING
21 return s.decode(encoding, "replace")
21 return s.decode(encoding, "replace")
22
22
23 def encode(u, encoding=None):
23 def encode(u, encoding=None):
24 encoding = encoding or DEFAULT_ENCODING
24 encoding = encoding or DEFAULT_ENCODING
25 return u.encode(encoding, "replace")
25 return u.encode(encoding, "replace")
26
26
27
27
28 def cast_unicode(s, encoding=None):
28 def cast_unicode(s, encoding=None):
29 if isinstance(s, bytes):
29 if isinstance(s, bytes):
30 return decode(s, encoding)
30 return decode(s, encoding)
31 return s
31 return s
32
32
33 def cast_bytes(s, encoding=None):
33 def cast_bytes(s, encoding=None):
34 if not isinstance(s, bytes):
34 if not isinstance(s, bytes):
35 return encode(s, encoding)
35 return encode(s, encoding)
36 return s
36 return s
37
37
38 def buffer_to_bytes(buf):
38 def buffer_to_bytes(buf):
39 """Cast a buffer object to bytes"""
39 """Cast a buffer object to bytes"""
40 if not isinstance(buf, bytes):
40 if not isinstance(buf, bytes):
41 buf = bytes(buf)
41 buf = bytes(buf)
42 return buf
42 return buf
43
43
44 def _modify_str_or_docstring(str_change_func):
44 def _modify_str_or_docstring(str_change_func):
45 @functools.wraps(str_change_func)
45 @functools.wraps(str_change_func)
46 def wrapper(func_or_str):
46 def wrapper(func_or_str):
47 if isinstance(func_or_str, string_types):
47 if isinstance(func_or_str, string_types):
48 func = None
48 func = None
49 doc = func_or_str
49 doc = func_or_str
50 else:
50 else:
51 func = func_or_str
51 func = func_or_str
52 doc = func.__doc__
52 doc = func.__doc__
53
53
54 # PYTHONOPTIMIZE=2 strips docstrings, so they can disappear unexpectedly
54 # PYTHONOPTIMIZE=2 strips docstrings, so they can disappear unexpectedly
55 if doc is not None:
55 if doc is not None:
56 doc = str_change_func(doc)
56 doc = str_change_func(doc)
57
57
58 if func:
58 if func:
59 func.__doc__ = doc
59 func.__doc__ = doc
60 return func
60 return func
61 return doc
61 return doc
62 return wrapper
62 return wrapper
63
63
64 def safe_unicode(e):
64 def safe_unicode(e):
65 """unicode(e) with various fallbacks. Used for exceptions, which may not be
65 """unicode(e) with various fallbacks. Used for exceptions, which may not be
66 safe to call unicode() on.
66 safe to call unicode() on.
67 """
67 """
68 try:
68 try:
69 return unicode_type(e)
69 return unicode_type(e)
70 except UnicodeError:
70 except UnicodeError:
71 pass
71 pass
72
72
73 try:
73 try:
74 return str_to_unicode(str(e))
74 return str_to_unicode(str(e))
75 except UnicodeError:
75 except UnicodeError:
76 pass
76 pass
77
77
78 try:
78 try:
79 return str_to_unicode(repr(e))
79 return str_to_unicode(repr(e))
80 except UnicodeError:
80 except UnicodeError:
81 pass
81 pass
82
82
83 return u'Unrecoverably corrupt evalue'
83 return u'Unrecoverably corrupt evalue'
84
84
85 # shutil.which from Python 3.4
85 # shutil.which from Python 3.4
86 def _shutil_which(cmd, mode=os.F_OK | os.X_OK, path=None):
86 def _shutil_which(cmd, mode=os.F_OK | os.X_OK, path=None):
87 """Given a command, mode, and a PATH string, return the path which
87 """Given a command, mode, and a PATH string, return the path which
88 conforms to the given mode on the PATH, or None if there is no such
88 conforms to the given mode on the PATH, or None if there is no such
89 file.
89 file.
90
90
91 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
91 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
92 of os.environ.get("PATH"), or can be overridden with a custom search
92 of os.environ.get("PATH"), or can be overridden with a custom search
93 path.
93 path.
94
94
95 This is a backport of shutil.which from Python 3.4
95 This is a backport of shutil.which from Python 3.4
96 """
96 """
97 # Check that a given file can be accessed with the correct mode.
97 # Check that a given file can be accessed with the correct mode.
98 # Additionally check that `file` is not a directory, as on Windows
98 # Additionally check that `file` is not a directory, as on Windows
99 # directories pass the os.access check.
99 # directories pass the os.access check.
100 def _access_check(fn, mode):
100 def _access_check(fn, mode):
101 return (os.path.exists(fn) and os.access(fn, mode)
101 return (os.path.exists(fn) and os.access(fn, mode)
102 and not os.path.isdir(fn))
102 and not os.path.isdir(fn))
103
103
104 # If we're given a path with a directory part, look it up directly rather
104 # If we're given a path with a directory part, look it up directly rather
105 # than referring to PATH directories. This includes checking relative to the
105 # than referring to PATH directories. This includes checking relative to the
106 # current directory, e.g. ./script
106 # current directory, e.g. ./script
107 if os.path.dirname(cmd):
107 if os.path.dirname(cmd):
108 if _access_check(cmd, mode):
108 if _access_check(cmd, mode):
109 return cmd
109 return cmd
110 return None
110 return None
111
111
112 if path is None:
112 if path is None:
113 path = os.environ.get("PATH", os.defpath)
113 path = os.environ.get("PATH", os.defpath)
114 if not path:
114 if not path:
115 return None
115 return None
116 path = path.split(os.pathsep)
116 path = path.split(os.pathsep)
117
117
118 if sys.platform == "win32":
118 if sys.platform == "win32":
119 # The current directory takes precedence on Windows.
119 # The current directory takes precedence on Windows.
120 if not os.curdir in path:
120 if not os.curdir in path:
121 path.insert(0, os.curdir)
121 path.insert(0, os.curdir)
122
122
123 # PATHEXT is necessary to check on Windows.
123 # PATHEXT is necessary to check on Windows.
124 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
124 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
125 # See if the given file matches any of the expected path extensions.
125 # See if the given file matches any of the expected path extensions.
126 # This will allow us to short circuit when given "python.exe".
126 # This will allow us to short circuit when given "python.exe".
127 # If it does match, only test that one, otherwise we have to try
127 # If it does match, only test that one, otherwise we have to try
128 # others.
128 # others.
129 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
129 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
130 files = [cmd]
130 files = [cmd]
131 else:
131 else:
132 files = [cmd + ext for ext in pathext]
132 files = [cmd + ext for ext in pathext]
133 else:
133 else:
134 # On other platforms you don't have things like PATHEXT to tell you
134 # On other platforms you don't have things like PATHEXT to tell you
135 # what file suffixes are executable, so just pass on cmd as-is.
135 # what file suffixes are executable, so just pass on cmd as-is.
136 files = [cmd]
136 files = [cmd]
137
137
138 seen = set()
138 seen = set()
139 for dir in path:
139 for dir in path:
140 normdir = os.path.normcase(dir)
140 normdir = os.path.normcase(dir)
141 if not normdir in seen:
141 if not normdir in seen:
142 seen.add(normdir)
142 seen.add(normdir)
143 for thefile in files:
143 for thefile in files:
144 name = os.path.join(dir, thefile)
144 name = os.path.join(dir, thefile)
145 if _access_check(name, mode):
145 if _access_check(name, mode):
146 return name
146 return name
147 return None
147 return None
148
148
149 PY3 = True
149 PY3 = True
150
150
151 # keep reference to builtin_mod because the kernel overrides that value
151 # keep reference to builtin_mod because the kernel overrides that value
152 # to forward requests to a frontend.
152 # to forward requests to a frontend.
153 def input(prompt=''):
153 def input(prompt=''):
154 return builtin_mod.input(prompt)
154 return builtin_mod.input(prompt)
155
155
156 builtin_mod_name = "builtins"
156 builtin_mod_name = "builtins"
157 import builtins as builtin_mod
157 import builtins as builtin_mod
158
158
159 str_to_unicode = no_code
159 str_to_unicode = no_code
160 unicode_to_str = no_code
160 unicode_to_str = no_code
161 str_to_bytes = encode
161 str_to_bytes = encode
162 bytes_to_str = decode
162 bytes_to_str = decode
163 cast_bytes_py2 = no_code
163 cast_bytes_py2 = no_code
164 cast_unicode_py2 = no_code
164 cast_unicode_py2 = no_code
165 buffer_to_bytes_py2 = no_code
165 buffer_to_bytes_py2 = no_code
166
166
167 string_types = (str,)
167 string_types = (str,)
168 unicode_type = str
168 unicode_type = str
169
169
170 which = shutil.which
170 which = shutil.which
171
171
172 def isidentifier(s, dotted=False):
172 def isidentifier(s, dotted=False):
173 if dotted:
173 if dotted:
174 return all(isidentifier(a) for a in s.split("."))
174 return all(isidentifier(a) for a in s.split("."))
175 return s.isidentifier()
175 return s.isidentifier()
176
176
177 xrange = range
177 xrange = range
178 def iteritems(d): return iter(d.items())
178 def iteritems(d): return iter(d.items())
179 def itervalues(d): return iter(d.values())
179 def itervalues(d): return iter(d.values())
180 getcwd = os.getcwd
180 getcwd = os.getcwd
181
181
182 MethodType = types.MethodType
182 MethodType = types.MethodType
183
183
184 def execfile(fname, glob, loc=None, compiler=None):
184 def execfile(fname, glob, loc=None, compiler=None):
185 loc = loc if (loc is not None) else glob
185 loc = loc if (loc is not None) else glob
186 with open(fname, 'rb') as f:
186 with open(fname, 'rb') as f:
187 compiler = compiler or compile
187 compiler = compiler or compile
188 exec(compiler(f.read(), fname, 'exec'), glob, loc)
188 exec(compiler(f.read(), fname, 'exec'), glob, loc)
189
189
190 # Refactor print statements in doctests.
190 # Refactor print statements in doctests.
191 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
191 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
192 def _print_statement_sub(match):
192 def _print_statement_sub(match):
193 expr = match.groups('expr')
193 expr = match.groups('expr')
194 return "print(%s)" % expr
194 return "print(%s)" % expr
195
195
196 @_modify_str_or_docstring
197 def doctest_refactor_print(doc):
198 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
199 unfortunately doesn't pick up on our doctests.
200
201 Can accept a string or a function, so it can be used as a decorator."""
202 return _print_statement_re.sub(_print_statement_sub, doc)
203
204 # Abstract u'abc' syntax:
196 # Abstract u'abc' syntax:
205 @_modify_str_or_docstring
197 @_modify_str_or_docstring
206 def u_format(s):
198 def u_format(s):
207 """"{u}'abc'" --> "'abc'" (Python 3)
199 """"{u}'abc'" --> "'abc'" (Python 3)
208
200
209 Accepts a string or a function, so it can be used as a decorator."""
201 Accepts a string or a function, so it can be used as a decorator."""
210 return s.format(u='')
202 return s.format(u='')
211
203
212 def get_closure(f):
204 def get_closure(f):
213 """Get a function's closure attribute"""
205 """Get a function's closure attribute"""
214 return f.__closure__
206 return f.__closure__
215
207
216
208
217 PY2 = not PY3
209 PY2 = not PY3
218 PYPY = platform.python_implementation() == "PyPy"
210 PYPY = platform.python_implementation() == "PyPy"
219
211
220
212
221 def annotate(**kwargs):
213 def annotate(**kwargs):
222 """Python 3 compatible function annotation for Python 2."""
214 """Python 3 compatible function annotation for Python 2."""
223 if not kwargs:
215 if not kwargs:
224 raise ValueError('annotations must be provided as keyword arguments')
216 raise ValueError('annotations must be provided as keyword arguments')
225 def dec(f):
217 def dec(f):
226 if hasattr(f, '__annotations__'):
218 if hasattr(f, '__annotations__'):
227 for k, v in kwargs.items():
219 for k, v in kwargs.items():
228 f.__annotations__[k] = v
220 f.__annotations__[k] = v
229 else:
221 else:
230 f.__annotations__ = kwargs
222 f.__annotations__ = kwargs
231 return f
223 return f
232 return dec
224 return dec
233
225
234
226
235 # Parts below taken from six:
227 # Parts below taken from six:
236 # Copyright (c) 2010-2013 Benjamin Peterson
228 # Copyright (c) 2010-2013 Benjamin Peterson
237 #
229 #
238 # Permission is hereby granted, free of charge, to any person obtaining a copy
230 # Permission is hereby granted, free of charge, to any person obtaining a copy
239 # of this software and associated documentation files (the "Software"), to deal
231 # of this software and associated documentation files (the "Software"), to deal
240 # in the Software without restriction, including without limitation the rights
232 # in the Software without restriction, including without limitation the rights
241 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
233 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
242 # copies of the Software, and to permit persons to whom the Software is
234 # copies of the Software, and to permit persons to whom the Software is
243 # furnished to do so, subject to the following conditions:
235 # furnished to do so, subject to the following conditions:
244 #
236 #
245 # The above copyright notice and this permission notice shall be included in all
237 # The above copyright notice and this permission notice shall be included in all
246 # copies or substantial portions of the Software.
238 # copies or substantial portions of the Software.
247 #
239 #
248 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
240 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
249 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
241 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
250 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
242 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
251 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
243 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
252 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
244 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
253 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
245 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
254 # SOFTWARE.
246 # SOFTWARE.
255
247
256 def with_metaclass(meta, *bases):
248 def with_metaclass(meta, *bases):
257 """Create a base class with a metaclass."""
249 """Create a base class with a metaclass."""
258 return meta("_NewBase", bases, {})
250 return meta("_NewBase", bases, {})
General Comments 0
You need to be logged in to leave comments. Login now