##// END OF EJS Templates
python2 init signatures include self
Min RK -
Show More
@@ -1,431 +1,432 b''
1 """Tests for the object inspection functionality.
1 """Tests for the object inspection functionality.
2 """
2 """
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from __future__ import print_function
7 from __future__ import print_function
8
8
9 import os
9 import os
10 import re
10 import re
11 import sys
11 import sys
12
12
13 import nose.tools as nt
13 import nose.tools as nt
14
14
15 from .. import oinspect
15 from .. import oinspect
16 from IPython.core.magic import (Magics, magics_class, line_magic,
16 from IPython.core.magic import (Magics, magics_class, line_magic,
17 cell_magic, line_cell_magic,
17 cell_magic, line_cell_magic,
18 register_line_magic, register_cell_magic,
18 register_line_magic, register_cell_magic,
19 register_line_cell_magic)
19 register_line_cell_magic)
20 from decorator import decorator
20 from decorator import decorator
21 from IPython.testing.decorators import skipif
21 from IPython.testing.decorators import skipif
22 from IPython.testing.tools import AssertPrints
22 from IPython.testing.tools import AssertPrints
23 from IPython.utils.path import compress_user
23 from IPython.utils.path import compress_user
24 from IPython.utils import py3compat
24 from IPython.utils import py3compat
25 from IPython.utils.signatures import Signature, Parameter
25 from IPython.utils.signatures import Signature, Parameter
26
26
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Globals and constants
29 # Globals and constants
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32 inspector = oinspect.Inspector()
32 inspector = oinspect.Inspector()
33 ip = get_ipython()
33 ip = get_ipython()
34
34
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # Local utilities
36 # Local utilities
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38
38
39 # WARNING: since this test checks the line number where a function is
39 # WARNING: since this test checks the line number where a function is
40 # defined, if any code is inserted above, the following line will need to be
40 # defined, if any code is inserted above, the following line will need to be
41 # updated. Do NOT insert any whitespace between the next line and the function
41 # updated. Do NOT insert any whitespace between the next line and the function
42 # definition below.
42 # definition below.
43 THIS_LINE_NUMBER = 43 # Put here the actual number of this line
43 THIS_LINE_NUMBER = 43 # Put here the actual number of this line
44 def test_find_source_lines():
44 def test_find_source_lines():
45 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
45 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
46 THIS_LINE_NUMBER+1)
46 THIS_LINE_NUMBER+1)
47
47
48
48
49 # A couple of utilities to ensure these tests work the same from a source or a
49 # A couple of utilities to ensure these tests work the same from a source or a
50 # binary install
50 # binary install
51 def pyfile(fname):
51 def pyfile(fname):
52 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
52 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
53
53
54
54
55 def match_pyfiles(f1, f2):
55 def match_pyfiles(f1, f2):
56 nt.assert_equal(pyfile(f1), pyfile(f2))
56 nt.assert_equal(pyfile(f1), pyfile(f2))
57
57
58
58
59 def test_find_file():
59 def test_find_file():
60 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
60 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
61
61
62
62
63 def test_find_file_decorated1():
63 def test_find_file_decorated1():
64
64
65 @decorator
65 @decorator
66 def noop1(f):
66 def noop1(f):
67 def wrapper():
67 def wrapper():
68 return f(*a, **kw)
68 return f(*a, **kw)
69 return wrapper
69 return wrapper
70
70
71 @noop1
71 @noop1
72 def f(x):
72 def f(x):
73 "My docstring"
73 "My docstring"
74
74
75 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
75 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
76 nt.assert_equal(f.__doc__, "My docstring")
76 nt.assert_equal(f.__doc__, "My docstring")
77
77
78
78
79 def test_find_file_decorated2():
79 def test_find_file_decorated2():
80
80
81 @decorator
81 @decorator
82 def noop2(f, *a, **kw):
82 def noop2(f, *a, **kw):
83 return f(*a, **kw)
83 return f(*a, **kw)
84
84
85 @noop2
85 @noop2
86 @noop2
86 @noop2
87 @noop2
87 @noop2
88 def f(x):
88 def f(x):
89 "My docstring 2"
89 "My docstring 2"
90
90
91 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
91 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
92 nt.assert_equal(f.__doc__, "My docstring 2")
92 nt.assert_equal(f.__doc__, "My docstring 2")
93
93
94
94
95 def test_find_file_magic():
95 def test_find_file_magic():
96 run = ip.find_line_magic('run')
96 run = ip.find_line_magic('run')
97 nt.assert_not_equal(oinspect.find_file(run), None)
97 nt.assert_not_equal(oinspect.find_file(run), None)
98
98
99
99
100 # A few generic objects we can then inspect in the tests below
100 # A few generic objects we can then inspect in the tests below
101
101
102 class Call(object):
102 class Call(object):
103 """This is the class docstring."""
103 """This is the class docstring."""
104
104
105 def __init__(self, x, y=1):
105 def __init__(self, x, y=1):
106 """This is the constructor docstring."""
106 """This is the constructor docstring."""
107
107
108 def __call__(self, *a, **kw):
108 def __call__(self, *a, **kw):
109 """This is the call docstring."""
109 """This is the call docstring."""
110
110
111 def method(self, x, z=2):
111 def method(self, x, z=2):
112 """Some method's docstring"""
112 """Some method's docstring"""
113
113
114 class HasSignature(object):
114 class HasSignature(object):
115 """This is the class docstring."""
115 """This is the class docstring."""
116 __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
116 __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
117
117
118 def __init__(self, *args):
118 def __init__(self, *args):
119 """This is the init docstring"""
119 """This is the init docstring"""
120
120
121
121
122 class SimpleClass(object):
122 class SimpleClass(object):
123 def method(self, x, z=2):
123 def method(self, x, z=2):
124 """Some method's docstring"""
124 """Some method's docstring"""
125
125
126
126
127 class OldStyle:
127 class OldStyle:
128 """An old-style class for testing."""
128 """An old-style class for testing."""
129 pass
129 pass
130
130
131
131
132 def f(x, y=2, *a, **kw):
132 def f(x, y=2, *a, **kw):
133 """A simple function."""
133 """A simple function."""
134
134
135
135
136 def g(y, z=3, *a, **kw):
136 def g(y, z=3, *a, **kw):
137 pass # no docstring
137 pass # no docstring
138
138
139
139
140 @register_line_magic
140 @register_line_magic
141 def lmagic(line):
141 def lmagic(line):
142 "A line magic"
142 "A line magic"
143
143
144
144
145 @register_cell_magic
145 @register_cell_magic
146 def cmagic(line, cell):
146 def cmagic(line, cell):
147 "A cell magic"
147 "A cell magic"
148
148
149
149
150 @register_line_cell_magic
150 @register_line_cell_magic
151 def lcmagic(line, cell=None):
151 def lcmagic(line, cell=None):
152 "A line/cell magic"
152 "A line/cell magic"
153
153
154
154
155 @magics_class
155 @magics_class
156 class SimpleMagics(Magics):
156 class SimpleMagics(Magics):
157 @line_magic
157 @line_magic
158 def Clmagic(self, cline):
158 def Clmagic(self, cline):
159 "A class-based line magic"
159 "A class-based line magic"
160
160
161 @cell_magic
161 @cell_magic
162 def Ccmagic(self, cline, ccell):
162 def Ccmagic(self, cline, ccell):
163 "A class-based cell magic"
163 "A class-based cell magic"
164
164
165 @line_cell_magic
165 @line_cell_magic
166 def Clcmagic(self, cline, ccell=None):
166 def Clcmagic(self, cline, ccell=None):
167 "A class-based line/cell magic"
167 "A class-based line/cell magic"
168
168
169
169
170 class Awkward(object):
170 class Awkward(object):
171 def __getattr__(self, name):
171 def __getattr__(self, name):
172 raise Exception(name)
172 raise Exception(name)
173
173
174 class NoBoolCall:
174 class NoBoolCall:
175 """
175 """
176 callable with `__bool__` raising should still be inspect-able.
176 callable with `__bool__` raising should still be inspect-able.
177 """
177 """
178
178
179 def __call__(self):
179 def __call__(self):
180 """does nothing"""
180 """does nothing"""
181 pass
181 pass
182
182
183 def __bool__(self):
183 def __bool__(self):
184 """just raise NotImplemented"""
184 """just raise NotImplemented"""
185 raise NotImplementedError('Must be implemented')
185 raise NotImplementedError('Must be implemented')
186
186
187
187
188 class SerialLiar(object):
188 class SerialLiar(object):
189 """Attribute accesses always get another copy of the same class.
189 """Attribute accesses always get another copy of the same class.
190
190
191 unittest.mock.call does something similar, but it's not ideal for testing
191 unittest.mock.call does something similar, but it's not ideal for testing
192 as the failure mode is to eat all your RAM. This gives up after 10k levels.
192 as the failure mode is to eat all your RAM. This gives up after 10k levels.
193 """
193 """
194 def __init__(self, max_fibbing_twig, lies_told=0):
194 def __init__(self, max_fibbing_twig, lies_told=0):
195 if lies_told > 10000:
195 if lies_told > 10000:
196 raise RuntimeError('Nose too long, honesty is the best policy')
196 raise RuntimeError('Nose too long, honesty is the best policy')
197 self.max_fibbing_twig = max_fibbing_twig
197 self.max_fibbing_twig = max_fibbing_twig
198 self.lies_told = lies_told
198 self.lies_told = lies_told
199 max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
199 max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
200
200
201 def __getattr__(self, item):
201 def __getattr__(self, item):
202 return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
202 return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
203
203
204
204
205 def check_calltip(obj, name, call, docstring):
205 def check_calltip(obj, name, call, docstring):
206 """Generic check pattern all calltip tests will use"""
206 """Generic check pattern all calltip tests will use"""
207 info = inspector.info(obj, name)
207 info = inspector.info(obj, name)
208 call_line, ds = oinspect.call_tip(info)
208 call_line, ds = oinspect.call_tip(info)
209 nt.assert_equal(call_line, call)
209 nt.assert_equal(call_line, call)
210 nt.assert_equal(ds, docstring)
210 nt.assert_equal(ds, docstring)
211
211
212 #-----------------------------------------------------------------------------
212 #-----------------------------------------------------------------------------
213 # Tests
213 # Tests
214 #-----------------------------------------------------------------------------
214 #-----------------------------------------------------------------------------
215
215
216 def test_calltip_class():
216 def test_calltip_class():
217 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
217 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
218
218
219
219
220 def test_calltip_instance():
220 def test_calltip_instance():
221 c = Call(1)
221 c = Call(1)
222 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
222 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
223
223
224
224
225 def test_calltip_method():
225 def test_calltip_method():
226 c = Call(1)
226 c = Call(1)
227 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
227 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
228
228
229
229
230 def test_calltip_function():
230 def test_calltip_function():
231 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
231 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
232
232
233
233
234 def test_calltip_function2():
234 def test_calltip_function2():
235 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
235 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
236
236
237
237
238 @skipif(sys.version_info >= (3, 5))
238 @skipif(sys.version_info >= (3, 5))
239 def test_calltip_builtin():
239 def test_calltip_builtin():
240 check_calltip(sum, 'sum', None, sum.__doc__)
240 check_calltip(sum, 'sum', None, sum.__doc__)
241
241
242
242
243 def test_calltip_line_magic():
243 def test_calltip_line_magic():
244 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
244 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
245
245
246
246
247 def test_calltip_cell_magic():
247 def test_calltip_cell_magic():
248 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
248 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
249
249
250
250
251 def test_calltip_line_cell_magic():
251 def test_calltip_line_cell_magic():
252 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
252 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
253 "A line/cell magic")
253 "A line/cell magic")
254
254
255
255
256 def test_class_magics():
256 def test_class_magics():
257 cm = SimpleMagics(ip)
257 cm = SimpleMagics(ip)
258 ip.register_magics(cm)
258 ip.register_magics(cm)
259 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
259 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
260 "A class-based line magic")
260 "A class-based line magic")
261 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
261 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
262 "A class-based cell magic")
262 "A class-based cell magic")
263 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
263 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
264 "A class-based line/cell magic")
264 "A class-based line/cell magic")
265
265
266
266
267 def test_info():
267 def test_info():
268 "Check that Inspector.info fills out various fields as expected."
268 "Check that Inspector.info fills out various fields as expected."
269 i = inspector.info(Call, oname='Call')
269 i = inspector.info(Call, oname='Call')
270 nt.assert_equal(i['type_name'], 'type')
270 nt.assert_equal(i['type_name'], 'type')
271 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
271 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
272 nt.assert_equal(i['base_class'], expted_class)
272 nt.assert_equal(i['base_class'], expted_class)
273 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
273 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
274 fname = __file__
274 fname = __file__
275 if fname.endswith(".pyc"):
275 if fname.endswith(".pyc"):
276 fname = fname[:-1]
276 fname = fname[:-1]
277 # case-insensitive comparison needed on some filesystems
277 # case-insensitive comparison needed on some filesystems
278 # e.g. Windows:
278 # e.g. Windows:
279 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
279 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
280 nt.assert_equal(i['definition'], None)
280 nt.assert_equal(i['definition'], None)
281 nt.assert_equal(i['docstring'], Call.__doc__)
281 nt.assert_equal(i['docstring'], Call.__doc__)
282 nt.assert_equal(i['source'], None)
282 nt.assert_equal(i['source'], None)
283 nt.assert_true(i['isclass'])
283 nt.assert_true(i['isclass'])
284 nt.assert_equal(i['init_definition'], "Call(x, y=1)\n")
284 _self_py2 = '' if py3compat.PY3 else 'self, '
285 nt.assert_equal(i['init_definition'], "Call(%sx, y=1)\n" % _self_py2)
285 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
286 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
286
287
287 i = inspector.info(Call, detail_level=1)
288 i = inspector.info(Call, detail_level=1)
288 nt.assert_not_equal(i['source'], None)
289 nt.assert_not_equal(i['source'], None)
289 nt.assert_equal(i['docstring'], None)
290 nt.assert_equal(i['docstring'], None)
290
291
291 c = Call(1)
292 c = Call(1)
292 c.__doc__ = "Modified instance docstring"
293 c.__doc__ = "Modified instance docstring"
293 i = inspector.info(c)
294 i = inspector.info(c)
294 nt.assert_equal(i['type_name'], 'Call')
295 nt.assert_equal(i['type_name'], 'Call')
295 nt.assert_equal(i['docstring'], "Modified instance docstring")
296 nt.assert_equal(i['docstring'], "Modified instance docstring")
296 nt.assert_equal(i['class_docstring'], Call.__doc__)
297 nt.assert_equal(i['class_docstring'], Call.__doc__)
297 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
298 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
298 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
299 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
299
300
300 # Test old-style classes, which for example may not have an __init__ method.
301 # Test old-style classes, which for example may not have an __init__ method.
301 if not py3compat.PY3:
302 if not py3compat.PY3:
302 i = inspector.info(OldStyle)
303 i = inspector.info(OldStyle)
303 nt.assert_equal(i['type_name'], 'classobj')
304 nt.assert_equal(i['type_name'], 'classobj')
304
305
305 i = inspector.info(OldStyle())
306 i = inspector.info(OldStyle())
306 nt.assert_equal(i['type_name'], 'instance')
307 nt.assert_equal(i['type_name'], 'instance')
307 nt.assert_equal(i['docstring'], OldStyle.__doc__)
308 nt.assert_equal(i['docstring'], OldStyle.__doc__)
308
309
309 def test_class_signature():
310 def test_class_signature():
310 info = inspector.info(HasSignature, 'HasSignature')
311 info = inspector.info(HasSignature, 'HasSignature')
311 nt.assert_equal(info['init_definition'], "HasSignature(test)\n")
312 nt.assert_equal(info['init_definition'], "HasSignature(test)\n")
312 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
313 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
313
314
314 def test_info_awkward():
315 def test_info_awkward():
315 # Just test that this doesn't throw an error.
316 # Just test that this doesn't throw an error.
316 i = inspector.info(Awkward())
317 i = inspector.info(Awkward())
317
318
318 def test_bool_raise():
319 def test_bool_raise():
319 inspector.info(NoBoolCall())
320 inspector.info(NoBoolCall())
320
321
321 def test_info_serialliar():
322 def test_info_serialliar():
322 fib_tracker = [0]
323 fib_tracker = [0]
323 i = inspector.info(SerialLiar(fib_tracker))
324 i = inspector.info(SerialLiar(fib_tracker))
324
325
325 # Nested attribute access should be cut off at 100 levels deep to avoid
326 # Nested attribute access should be cut off at 100 levels deep to avoid
326 # infinite loops: https://github.com/ipython/ipython/issues/9122
327 # infinite loops: https://github.com/ipython/ipython/issues/9122
327 nt.assert_less(fib_tracker[0], 9000)
328 nt.assert_less(fib_tracker[0], 9000)
328
329
329 def test_calldef_none():
330 def test_calldef_none():
330 # We should ignore __call__ for all of these.
331 # We should ignore __call__ for all of these.
331 for obj in [f, SimpleClass().method, any, str.upper]:
332 for obj in [f, SimpleClass().method, any, str.upper]:
332 print(obj)
333 print(obj)
333 i = inspector.info(obj)
334 i = inspector.info(obj)
334 nt.assert_is(i['call_def'], None)
335 nt.assert_is(i['call_def'], None)
335
336
336 if py3compat.PY3:
337 if py3compat.PY3:
337 exec("def f_kwarg(pos, *, kwonly): pass")
338 exec("def f_kwarg(pos, *, kwonly): pass")
338
339
339 @skipif(not py3compat.PY3)
340 @skipif(not py3compat.PY3)
340 def test_definition_kwonlyargs():
341 def test_definition_kwonlyargs():
341 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
342 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
342 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
343 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
343
344
344 def test_getdoc():
345 def test_getdoc():
345 class A(object):
346 class A(object):
346 """standard docstring"""
347 """standard docstring"""
347 pass
348 pass
348
349
349 class B(object):
350 class B(object):
350 """standard docstring"""
351 """standard docstring"""
351 def getdoc(self):
352 def getdoc(self):
352 return "custom docstring"
353 return "custom docstring"
353
354
354 class C(object):
355 class C(object):
355 """standard docstring"""
356 """standard docstring"""
356 def getdoc(self):
357 def getdoc(self):
357 return None
358 return None
358
359
359 a = A()
360 a = A()
360 b = B()
361 b = B()
361 c = C()
362 c = C()
362
363
363 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
364 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
364 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
365 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
365 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
366 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
366
367
367
368
368 def test_empty_property_has_no_source():
369 def test_empty_property_has_no_source():
369 i = inspector.info(property(), detail_level=1)
370 i = inspector.info(property(), detail_level=1)
370 nt.assert_is(i['source'], None)
371 nt.assert_is(i['source'], None)
371
372
372
373
373 def test_property_sources():
374 def test_property_sources():
374 import zlib
375 import zlib
375
376
376 class A(object):
377 class A(object):
377 @property
378 @property
378 def foo(self):
379 def foo(self):
379 return 'bar'
380 return 'bar'
380
381
381 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
382 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
382
383
383 id = property(id)
384 id = property(id)
384 compress = property(zlib.compress)
385 compress = property(zlib.compress)
385
386
386 i = inspector.info(A.foo, detail_level=1)
387 i = inspector.info(A.foo, detail_level=1)
387 nt.assert_in('def foo(self):', i['source'])
388 nt.assert_in('def foo(self):', i['source'])
388 nt.assert_in('lambda self, v:', i['source'])
389 nt.assert_in('lambda self, v:', i['source'])
389
390
390 i = inspector.info(A.id, detail_level=1)
391 i = inspector.info(A.id, detail_level=1)
391 nt.assert_in('fget = <function id>', i['source'])
392 nt.assert_in('fget = <function id>', i['source'])
392
393
393 i = inspector.info(A.compress, detail_level=1)
394 i = inspector.info(A.compress, detail_level=1)
394 nt.assert_in('fget = <function zlib.compress>', i['source'])
395 nt.assert_in('fget = <function zlib.compress>', i['source'])
395
396
396
397
397 def test_property_docstring_is_in_info_for_detail_level_0():
398 def test_property_docstring_is_in_info_for_detail_level_0():
398 class A(object):
399 class A(object):
399 @property
400 @property
400 def foobar():
401 def foobar():
401 """This is `foobar` property."""
402 """This is `foobar` property."""
402 pass
403 pass
403
404
404 ip.user_ns['a_obj'] = A()
405 ip.user_ns['a_obj'] = A()
405 nt.assert_equals(
406 nt.assert_equals(
406 'This is `foobar` property.',
407 'This is `foobar` property.',
407 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
408 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
408
409
409 ip.user_ns['a_cls'] = A
410 ip.user_ns['a_cls'] = A
410 nt.assert_equals(
411 nt.assert_equals(
411 'This is `foobar` property.',
412 'This is `foobar` property.',
412 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
413 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
413
414
414
415
415 def test_pdef():
416 def test_pdef():
416 # See gh-1914
417 # See gh-1914
417 def foo(): pass
418 def foo(): pass
418 inspector.pdef(foo, 'foo')
419 inspector.pdef(foo, 'foo')
419
420
420 def test_pinfo_nonascii():
421 def test_pinfo_nonascii():
421 # See gh-1177
422 # See gh-1177
422 from . import nonascii2
423 from . import nonascii2
423 ip.user_ns['nonascii2'] = nonascii2
424 ip.user_ns['nonascii2'] = nonascii2
424 ip._inspect('pinfo', 'nonascii2', detail_level=1)
425 ip._inspect('pinfo', 'nonascii2', detail_level=1)
425
426
426 def test_pinfo_magic():
427 def test_pinfo_magic():
427 with AssertPrints('Docstring:'):
428 with AssertPrints('Docstring:'):
428 ip._inspect('pinfo', 'lsmagic', detail_level=0)
429 ip._inspect('pinfo', 'lsmagic', detail_level=0)
429
430
430 with AssertPrints('Source:'):
431 with AssertPrints('Source:'):
431 ip._inspect('pinfo', 'lsmagic', detail_level=1)
432 ip._inspect('pinfo', 'lsmagic', detail_level=1)
General Comments 0
You need to be logged in to leave comments. Login now