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