##// END OF EJS Templates
Add test for non-ascii characters in docstrings...
Thomas Kluyver -
Show More
@@ -0,0 +1,4 b''
1 # coding: iso-8859-5
2 # (Unlikely to be the default encoding for most testers.)
3 # БЖџрстуфхцчшщъыьэюя <- Cyrillic characters
4 'Ўт№Ф'
@@ -1,290 +1,296 b''
1 """Tests for the object inspection functionality.
1 """Tests for the object inspection functionality.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2010-2011 The IPython Development Team.
4 # Copyright (C) 2010-2011 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the BSD License.
6 # Distributed under the terms of the BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 from __future__ import print_function
14 from __future__ import print_function
15
15
16 # Stdlib imports
16 # Stdlib imports
17 import os
17 import os
18 import re
18 import re
19
19
20 # Third-party imports
20 # Third-party imports
21 import nose.tools as nt
21 import nose.tools as nt
22
22
23 # Our own imports
23 # Our own imports
24 from .. import oinspect
24 from .. import oinspect
25 from IPython.core.magic import (Magics, magics_class, line_magic,
25 from IPython.core.magic import (Magics, magics_class, line_magic,
26 cell_magic, line_cell_magic,
26 cell_magic, line_cell_magic,
27 register_line_magic, register_cell_magic,
27 register_line_magic, register_cell_magic,
28 register_line_cell_magic)
28 register_line_cell_magic)
29 from IPython.external.decorator import decorator
29 from IPython.external.decorator import decorator
30 from IPython.utils import py3compat
30 from IPython.utils import py3compat
31
31
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Globals and constants
34 # Globals and constants
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37 inspector = oinspect.Inspector()
37 inspector = oinspect.Inspector()
38 ip = get_ipython()
38 ip = get_ipython()
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Local utilities
41 # Local utilities
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 # WARNING: since this test checks the line number where a function is
44 # WARNING: since this test checks the line number where a function is
45 # defined, if any code is inserted above, the following line will need to be
45 # defined, if any code is inserted above, the following line will need to be
46 # updated. Do NOT insert any whitespace between the next line and the function
46 # updated. Do NOT insert any whitespace between the next line and the function
47 # definition below.
47 # definition below.
48 THIS_LINE_NUMBER = 48 # Put here the actual number of this line
48 THIS_LINE_NUMBER = 48 # Put here the actual number of this line
49 def test_find_source_lines():
49 def test_find_source_lines():
50 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
50 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
51 THIS_LINE_NUMBER+1)
51 THIS_LINE_NUMBER+1)
52
52
53
53
54 # A couple of utilities to ensure these tests work the same from a source or a
54 # A couple of utilities to ensure these tests work the same from a source or a
55 # binary install
55 # binary install
56 def pyfile(fname):
56 def pyfile(fname):
57 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
57 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
58
58
59
59
60 def match_pyfiles(f1, f2):
60 def match_pyfiles(f1, f2):
61 nt.assert_equal(pyfile(f1), pyfile(f2))
61 nt.assert_equal(pyfile(f1), pyfile(f2))
62
62
63
63
64 def test_find_file():
64 def test_find_file():
65 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
65 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
66
66
67
67
68 def test_find_file_decorated1():
68 def test_find_file_decorated1():
69
69
70 @decorator
70 @decorator
71 def noop1(f):
71 def noop1(f):
72 def wrapper():
72 def wrapper():
73 return f(*a, **kw)
73 return f(*a, **kw)
74 return wrapper
74 return wrapper
75
75
76 @noop1
76 @noop1
77 def f(x):
77 def f(x):
78 "My docstring"
78 "My docstring"
79
79
80 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
80 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
81 nt.assert_equal(f.__doc__, "My docstring")
81 nt.assert_equal(f.__doc__, "My docstring")
82
82
83
83
84 def test_find_file_decorated2():
84 def test_find_file_decorated2():
85
85
86 @decorator
86 @decorator
87 def noop2(f, *a, **kw):
87 def noop2(f, *a, **kw):
88 return f(*a, **kw)
88 return f(*a, **kw)
89
89
90 @noop2
90 @noop2
91 def f(x):
91 def f(x):
92 "My docstring 2"
92 "My docstring 2"
93
93
94 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
94 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
95 nt.assert_equal(f.__doc__, "My docstring 2")
95 nt.assert_equal(f.__doc__, "My docstring 2")
96
96
97
97
98 def test_find_file_magic():
98 def test_find_file_magic():
99 run = ip.find_line_magic('run')
99 run = ip.find_line_magic('run')
100 nt.assert_not_equal(oinspect.find_file(run), None)
100 nt.assert_not_equal(oinspect.find_file(run), None)
101
101
102
102
103 # A few generic objects we can then inspect in the tests below
103 # A few generic objects we can then inspect in the tests below
104
104
105 class Call(object):
105 class Call(object):
106 """This is the class docstring."""
106 """This is the class docstring."""
107
107
108 def __init__(self, x, y=1):
108 def __init__(self, x, y=1):
109 """This is the constructor docstring."""
109 """This is the constructor docstring."""
110
110
111 def __call__(self, *a, **kw):
111 def __call__(self, *a, **kw):
112 """This is the call docstring."""
112 """This is the call docstring."""
113
113
114 def method(self, x, z=2):
114 def method(self, x, z=2):
115 """Some method's docstring"""
115 """Some method's docstring"""
116
116
117
117
118 class OldStyle:
118 class OldStyle:
119 """An old-style class for testing."""
119 """An old-style class for testing."""
120 pass
120 pass
121
121
122
122
123 def f(x, y=2, *a, **kw):
123 def f(x, y=2, *a, **kw):
124 """A simple function."""
124 """A simple function."""
125
125
126
126
127 def g(y, z=3, *a, **kw):
127 def g(y, z=3, *a, **kw):
128 pass # no docstring
128 pass # no docstring
129
129
130
130
131 @register_line_magic
131 @register_line_magic
132 def lmagic(line):
132 def lmagic(line):
133 "A line magic"
133 "A line magic"
134
134
135
135
136 @register_cell_magic
136 @register_cell_magic
137 def cmagic(line, cell):
137 def cmagic(line, cell):
138 "A cell magic"
138 "A cell magic"
139
139
140
140
141 @register_line_cell_magic
141 @register_line_cell_magic
142 def lcmagic(line, cell=None):
142 def lcmagic(line, cell=None):
143 "A line/cell magic"
143 "A line/cell magic"
144
144
145
145
146 @magics_class
146 @magics_class
147 class SimpleMagics(Magics):
147 class SimpleMagics(Magics):
148 @line_magic
148 @line_magic
149 def Clmagic(self, cline):
149 def Clmagic(self, cline):
150 "A class-based line magic"
150 "A class-based line magic"
151
151
152 @cell_magic
152 @cell_magic
153 def Ccmagic(self, cline, ccell):
153 def Ccmagic(self, cline, ccell):
154 "A class-based cell magic"
154 "A class-based cell magic"
155
155
156 @line_cell_magic
156 @line_cell_magic
157 def Clcmagic(self, cline, ccell=None):
157 def Clcmagic(self, cline, ccell=None):
158 "A class-based line/cell magic"
158 "A class-based line/cell magic"
159
159
160
160
161 def check_calltip(obj, name, call, docstring):
161 def check_calltip(obj, name, call, docstring):
162 """Generic check pattern all calltip tests will use"""
162 """Generic check pattern all calltip tests will use"""
163 info = inspector.info(obj, name)
163 info = inspector.info(obj, name)
164 call_line, ds = oinspect.call_tip(info)
164 call_line, ds = oinspect.call_tip(info)
165 nt.assert_equal(call_line, call)
165 nt.assert_equal(call_line, call)
166 nt.assert_equal(ds, docstring)
166 nt.assert_equal(ds, docstring)
167
167
168 #-----------------------------------------------------------------------------
168 #-----------------------------------------------------------------------------
169 # Tests
169 # Tests
170 #-----------------------------------------------------------------------------
170 #-----------------------------------------------------------------------------
171
171
172 def test_calltip_class():
172 def test_calltip_class():
173 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
173 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
174
174
175
175
176 def test_calltip_instance():
176 def test_calltip_instance():
177 c = Call(1)
177 c = Call(1)
178 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
178 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
179
179
180
180
181 def test_calltip_method():
181 def test_calltip_method():
182 c = Call(1)
182 c = Call(1)
183 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
183 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
184
184
185
185
186 def test_calltip_function():
186 def test_calltip_function():
187 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
187 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
188
188
189
189
190 def test_calltip_function2():
190 def test_calltip_function2():
191 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
191 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
192
192
193
193
194 def test_calltip_builtin():
194 def test_calltip_builtin():
195 check_calltip(sum, 'sum', None, sum.__doc__)
195 check_calltip(sum, 'sum', None, sum.__doc__)
196
196
197
197
198 def test_calltip_line_magic():
198 def test_calltip_line_magic():
199 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
199 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
200
200
201
201
202 def test_calltip_cell_magic():
202 def test_calltip_cell_magic():
203 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
203 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
204
204
205
205
206 def test_calltip_line_magic():
206 def test_calltip_line_magic():
207 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
207 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
208 "A line/cell magic")
208 "A line/cell magic")
209
209
210
210
211 def test_class_magics():
211 def test_class_magics():
212 cm = SimpleMagics(ip)
212 cm = SimpleMagics(ip)
213 ip.register_magics(cm)
213 ip.register_magics(cm)
214 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
214 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
215 "A class-based line magic")
215 "A class-based line magic")
216 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
216 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
217 "A class-based cell magic")
217 "A class-based cell magic")
218 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
218 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
219 "A class-based line/cell magic")
219 "A class-based line/cell magic")
220
220
221
221
222 def test_info():
222 def test_info():
223 "Check that Inspector.info fills out various fields as expected."
223 "Check that Inspector.info fills out various fields as expected."
224 i = inspector.info(Call, oname='Call')
224 i = inspector.info(Call, oname='Call')
225 nt.assert_equal(i['type_name'], 'type')
225 nt.assert_equal(i['type_name'], 'type')
226 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
226 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
227 nt.assert_equal(i['base_class'], expted_class)
227 nt.assert_equal(i['base_class'], expted_class)
228 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
228 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
229 fname = __file__
229 fname = __file__
230 if fname.endswith(".pyc"):
230 if fname.endswith(".pyc"):
231 fname = fname[:-1]
231 fname = fname[:-1]
232 # case-insensitive comparison needed on some filesystems
232 # case-insensitive comparison needed on some filesystems
233 # e.g. Windows:
233 # e.g. Windows:
234 nt.assert_equal(i['file'].lower(), fname.lower())
234 nt.assert_equal(i['file'].lower(), fname.lower())
235 nt.assert_equal(i['definition'], 'Call(self, *a, **kw)\n')
235 nt.assert_equal(i['definition'], 'Call(self, *a, **kw)\n')
236 nt.assert_equal(i['docstring'], Call.__doc__)
236 nt.assert_equal(i['docstring'], Call.__doc__)
237 nt.assert_equal(i['source'], None)
237 nt.assert_equal(i['source'], None)
238 nt.assert_true(i['isclass'])
238 nt.assert_true(i['isclass'])
239 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
239 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
240 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
240 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
241
241
242 i = inspector.info(Call, detail_level=1)
242 i = inspector.info(Call, detail_level=1)
243 nt.assert_not_equal(i['source'], None)
243 nt.assert_not_equal(i['source'], None)
244 nt.assert_equal(i['docstring'], None)
244 nt.assert_equal(i['docstring'], None)
245
245
246 c = Call(1)
246 c = Call(1)
247 c.__doc__ = "Modified instance docstring"
247 c.__doc__ = "Modified instance docstring"
248 i = inspector.info(c)
248 i = inspector.info(c)
249 nt.assert_equal(i['type_name'], 'Call')
249 nt.assert_equal(i['type_name'], 'Call')
250 nt.assert_equal(i['docstring'], "Modified instance docstring")
250 nt.assert_equal(i['docstring'], "Modified instance docstring")
251 nt.assert_equal(i['class_docstring'], Call.__doc__)
251 nt.assert_equal(i['class_docstring'], Call.__doc__)
252 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
252 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
253 nt.assert_equal(i['call_docstring'], c.__call__.__doc__)
253 nt.assert_equal(i['call_docstring'], c.__call__.__doc__)
254
254
255 # Test old-style classes, which for example may not have an __init__ method.
255 # Test old-style classes, which for example may not have an __init__ method.
256 if not py3compat.PY3:
256 if not py3compat.PY3:
257 i = inspector.info(OldStyle)
257 i = inspector.info(OldStyle)
258 nt.assert_equal(i['type_name'], 'classobj')
258 nt.assert_equal(i['type_name'], 'classobj')
259
259
260 i = inspector.info(OldStyle())
260 i = inspector.info(OldStyle())
261 nt.assert_equal(i['type_name'], 'instance')
261 nt.assert_equal(i['type_name'], 'instance')
262 nt.assert_equal(i['docstring'], OldStyle.__doc__)
262 nt.assert_equal(i['docstring'], OldStyle.__doc__)
263
263
264 def test_getdoc():
264 def test_getdoc():
265 class A(object):
265 class A(object):
266 """standard docstring"""
266 """standard docstring"""
267 pass
267 pass
268
268
269 class B(object):
269 class B(object):
270 """standard docstring"""
270 """standard docstring"""
271 def getdoc(self):
271 def getdoc(self):
272 return "custom docstring"
272 return "custom docstring"
273
273
274 class C(object):
274 class C(object):
275 """standard docstring"""
275 """standard docstring"""
276 def getdoc(self):
276 def getdoc(self):
277 return None
277 return None
278
278
279 a = A()
279 a = A()
280 b = B()
280 b = B()
281 c = C()
281 c = C()
282
282
283 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
283 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
284 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
284 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
285 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
285 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
286
286
287 def test_pdef():
287 def test_pdef():
288 # See gh-1914
288 # See gh-1914
289 def foo(): pass
289 def foo(): pass
290 inspector.pdef(foo, 'foo')
290 inspector.pdef(foo, 'foo')
291
292 def test_pinfo_nonascii():
293 # See gh-1177
294 from . import nonascii2
295 ip.user_ns['nonascii2'] = nonascii2
296 ip._inspect('pinfo', 'nonascii2', detail_level=1)
General Comments 0
You need to be logged in to leave comments. Login now