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