##// END OF EJS Templates
Fix test on Python nightly
Matthias Bussonnier -
Show More
@@ -1,432 +1,433 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 if sys.version_info > (3,):
274 nt.assert_regex(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>")
274 fname = __file__
275 fname = __file__
275 if fname.endswith(".pyc"):
276 if fname.endswith(".pyc"):
276 fname = fname[:-1]
277 fname = fname[:-1]
277 # case-insensitive comparison needed on some filesystems
278 # case-insensitive comparison needed on some filesystems
278 # e.g. Windows:
279 # e.g. Windows:
279 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
280 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
280 nt.assert_equal(i['definition'], None)
281 nt.assert_equal(i['definition'], None)
281 nt.assert_equal(i['docstring'], Call.__doc__)
282 nt.assert_equal(i['docstring'], Call.__doc__)
282 nt.assert_equal(i['source'], None)
283 nt.assert_equal(i['source'], None)
283 nt.assert_true(i['isclass'])
284 nt.assert_true(i['isclass'])
284 _self_py2 = '' if py3compat.PY3 else 'self, '
285 _self_py2 = '' if py3compat.PY3 else 'self, '
285 nt.assert_equal(i['init_definition'], "Call(%sx, y=1)\n" % _self_py2)
286 nt.assert_equal(i['init_definition'], "Call(%sx, y=1)\n" % _self_py2)
286 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
287 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
287
288
288 i = inspector.info(Call, detail_level=1)
289 i = inspector.info(Call, detail_level=1)
289 nt.assert_not_equal(i['source'], None)
290 nt.assert_not_equal(i['source'], None)
290 nt.assert_equal(i['docstring'], None)
291 nt.assert_equal(i['docstring'], None)
291
292
292 c = Call(1)
293 c = Call(1)
293 c.__doc__ = "Modified instance docstring"
294 c.__doc__ = "Modified instance docstring"
294 i = inspector.info(c)
295 i = inspector.info(c)
295 nt.assert_equal(i['type_name'], 'Call')
296 nt.assert_equal(i['type_name'], 'Call')
296 nt.assert_equal(i['docstring'], "Modified instance docstring")
297 nt.assert_equal(i['docstring'], "Modified instance docstring")
297 nt.assert_equal(i['class_docstring'], Call.__doc__)
298 nt.assert_equal(i['class_docstring'], Call.__doc__)
298 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
299 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
299 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
300 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
300
301
301 # Test old-style classes, which for example may not have an __init__ method.
302 # Test old-style classes, which for example may not have an __init__ method.
302 if not py3compat.PY3:
303 if not py3compat.PY3:
303 i = inspector.info(OldStyle)
304 i = inspector.info(OldStyle)
304 nt.assert_equal(i['type_name'], 'classobj')
305 nt.assert_equal(i['type_name'], 'classobj')
305
306
306 i = inspector.info(OldStyle())
307 i = inspector.info(OldStyle())
307 nt.assert_equal(i['type_name'], 'instance')
308 nt.assert_equal(i['type_name'], 'instance')
308 nt.assert_equal(i['docstring'], OldStyle.__doc__)
309 nt.assert_equal(i['docstring'], OldStyle.__doc__)
309
310
310 def test_class_signature():
311 def test_class_signature():
311 info = inspector.info(HasSignature, 'HasSignature')
312 info = inspector.info(HasSignature, 'HasSignature')
312 nt.assert_equal(info['init_definition'], "HasSignature(test)\n")
313 nt.assert_equal(info['init_definition'], "HasSignature(test)\n")
313 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
314 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
314
315
315 def test_info_awkward():
316 def test_info_awkward():
316 # Just test that this doesn't throw an error.
317 # Just test that this doesn't throw an error.
317 i = inspector.info(Awkward())
318 i = inspector.info(Awkward())
318
319
319 def test_bool_raise():
320 def test_bool_raise():
320 inspector.info(NoBoolCall())
321 inspector.info(NoBoolCall())
321
322
322 def test_info_serialliar():
323 def test_info_serialliar():
323 fib_tracker = [0]
324 fib_tracker = [0]
324 i = inspector.info(SerialLiar(fib_tracker))
325 i = inspector.info(SerialLiar(fib_tracker))
325
326
326 # Nested attribute access should be cut off at 100 levels deep to avoid
327 # Nested attribute access should be cut off at 100 levels deep to avoid
327 # infinite loops: https://github.com/ipython/ipython/issues/9122
328 # infinite loops: https://github.com/ipython/ipython/issues/9122
328 nt.assert_less(fib_tracker[0], 9000)
329 nt.assert_less(fib_tracker[0], 9000)
329
330
330 def test_calldef_none():
331 def test_calldef_none():
331 # We should ignore __call__ for all of these.
332 # We should ignore __call__ for all of these.
332 for obj in [f, SimpleClass().method, any, str.upper]:
333 for obj in [f, SimpleClass().method, any, str.upper]:
333 print(obj)
334 print(obj)
334 i = inspector.info(obj)
335 i = inspector.info(obj)
335 nt.assert_is(i['call_def'], None)
336 nt.assert_is(i['call_def'], None)
336
337
337 if py3compat.PY3:
338 if py3compat.PY3:
338 exec("def f_kwarg(pos, *, kwonly): pass")
339 exec("def f_kwarg(pos, *, kwonly): pass")
339
340
340 @skipif(not py3compat.PY3)
341 @skipif(not py3compat.PY3)
341 def test_definition_kwonlyargs():
342 def test_definition_kwonlyargs():
342 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
343 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
343 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
344 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
344
345
345 def test_getdoc():
346 def test_getdoc():
346 class A(object):
347 class A(object):
347 """standard docstring"""
348 """standard docstring"""
348 pass
349 pass
349
350
350 class B(object):
351 class B(object):
351 """standard docstring"""
352 """standard docstring"""
352 def getdoc(self):
353 def getdoc(self):
353 return "custom docstring"
354 return "custom docstring"
354
355
355 class C(object):
356 class C(object):
356 """standard docstring"""
357 """standard docstring"""
357 def getdoc(self):
358 def getdoc(self):
358 return None
359 return None
359
360
360 a = A()
361 a = A()
361 b = B()
362 b = B()
362 c = C()
363 c = C()
363
364
364 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
365 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
365 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
366 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
366 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
367 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
367
368
368
369
369 def test_empty_property_has_no_source():
370 def test_empty_property_has_no_source():
370 i = inspector.info(property(), detail_level=1)
371 i = inspector.info(property(), detail_level=1)
371 nt.assert_is(i['source'], None)
372 nt.assert_is(i['source'], None)
372
373
373
374
374 def test_property_sources():
375 def test_property_sources():
375 import zlib
376 import zlib
376
377
377 class A(object):
378 class A(object):
378 @property
379 @property
379 def foo(self):
380 def foo(self):
380 return 'bar'
381 return 'bar'
381
382
382 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
383 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
383
384
384 id = property(id)
385 id = property(id)
385 compress = property(zlib.compress)
386 compress = property(zlib.compress)
386
387
387 i = inspector.info(A.foo, detail_level=1)
388 i = inspector.info(A.foo, detail_level=1)
388 nt.assert_in('def foo(self):', i['source'])
389 nt.assert_in('def foo(self):', i['source'])
389 nt.assert_in('lambda self, v:', i['source'])
390 nt.assert_in('lambda self, v:', i['source'])
390
391
391 i = inspector.info(A.id, detail_level=1)
392 i = inspector.info(A.id, detail_level=1)
392 nt.assert_in('fget = <function id>', i['source'])
393 nt.assert_in('fget = <function id>', i['source'])
393
394
394 i = inspector.info(A.compress, detail_level=1)
395 i = inspector.info(A.compress, detail_level=1)
395 nt.assert_in('fget = <function zlib.compress>', i['source'])
396 nt.assert_in('fget = <function zlib.compress>', i['source'])
396
397
397
398
398 def test_property_docstring_is_in_info_for_detail_level_0():
399 def test_property_docstring_is_in_info_for_detail_level_0():
399 class A(object):
400 class A(object):
400 @property
401 @property
401 def foobar(self):
402 def foobar(self):
402 """This is `foobar` property."""
403 """This is `foobar` property."""
403 pass
404 pass
404
405
405 ip.user_ns['a_obj'] = A()
406 ip.user_ns['a_obj'] = A()
406 nt.assert_equals(
407 nt.assert_equals(
407 'This is `foobar` property.',
408 'This is `foobar` property.',
408 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
409 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
409
410
410 ip.user_ns['a_cls'] = A
411 ip.user_ns['a_cls'] = A
411 nt.assert_equals(
412 nt.assert_equals(
412 'This is `foobar` property.',
413 'This is `foobar` property.',
413 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
414 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
414
415
415
416
416 def test_pdef():
417 def test_pdef():
417 # See gh-1914
418 # See gh-1914
418 def foo(): pass
419 def foo(): pass
419 inspector.pdef(foo, 'foo')
420 inspector.pdef(foo, 'foo')
420
421
421 def test_pinfo_nonascii():
422 def test_pinfo_nonascii():
422 # See gh-1177
423 # See gh-1177
423 from . import nonascii2
424 from . import nonascii2
424 ip.user_ns['nonascii2'] = nonascii2
425 ip.user_ns['nonascii2'] = nonascii2
425 ip._inspect('pinfo', 'nonascii2', detail_level=1)
426 ip._inspect('pinfo', 'nonascii2', detail_level=1)
426
427
427 def test_pinfo_magic():
428 def test_pinfo_magic():
428 with AssertPrints('Docstring:'):
429 with AssertPrints('Docstring:'):
429 ip._inspect('pinfo', 'lsmagic', detail_level=0)
430 ip._inspect('pinfo', 'lsmagic', detail_level=0)
430
431
431 with AssertPrints('Source:'):
432 with AssertPrints('Source:'):
432 ip._inspect('pinfo', 'lsmagic', detail_level=1)
433 ip._inspect('pinfo', 'lsmagic', detail_level=1)
General Comments 0
You need to be logged in to leave comments. Login now