##// END OF EJS Templates
pinfo magic return mime bundle
Sylvain Corlay -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,933 +1,975 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for inspecting Python objects.
3 3
4 4 Uses syntax highlighting for presenting the various information elements.
5 5
6 6 Similar in spirit to the inspect module, but all calls take a name argument to
7 7 reference the name under which an object is being read.
8 8 """
9 9
10 10 # Copyright (c) IPython Development Team.
11 11 # Distributed under the terms of the Modified BSD License.
12 12
13 13 from __future__ import print_function
14 14
15 15 __all__ = ['Inspector','InspectColors']
16 16
17 17 # stdlib modules
18 18 import inspect
19 19 import linecache
20 20 import os
21 21 from textwrap import dedent
22 22 import types
23 23 import io as stdlib_io
24 24
25 25 try:
26 26 from itertools import izip_longest
27 27 except ImportError:
28 28 from itertools import zip_longest as izip_longest
29 29
30 30 # IPython's own
31 31 from IPython.core import page
32 32 from IPython.lib.pretty import pretty
33 33 from IPython.testing.skipdoctest import skip_doctest_py3
34 34 from IPython.utils import PyColorize
35 35 from IPython.utils import openpy
36 36 from IPython.utils import py3compat
37 37 from IPython.utils.dir2 import safe_hasattr
38 38 from IPython.utils.path import compress_user
39 39 from IPython.utils.text import indent
40 40 from IPython.utils.wildcard import list_namespace
41 41 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
42 42 from IPython.utils.py3compat import cast_unicode, string_types, PY3
43 43 from IPython.utils.signatures import signature
44 44 from IPython.utils.colorable import Colorable
45 45
46 46 # builtin docstrings to ignore
47 47 _func_call_docstring = types.FunctionType.__call__.__doc__
48 48 _object_init_docstring = object.__init__.__doc__
49 49 _builtin_type_docstrings = {
50 50 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
51 51 types.FunctionType, property)
52 52 }
53 53
54 54 _builtin_func_type = type(all)
55 55 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
56 56 #****************************************************************************
57 57 # Builtin color schemes
58 58
59 59 Colors = TermColors # just a shorthand
60 60
61 61 InspectColors = PyColorize.ANSICodeColors
62 62
63 63 #****************************************************************************
64 64 # Auxiliary functions and objects
65 65
66 66 # See the messaging spec for the definition of all these fields. This list
67 67 # effectively defines the order of display
68 68 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
69 69 'length', 'file', 'definition', 'docstring', 'source',
70 70 'init_definition', 'class_docstring', 'init_docstring',
71 71 'call_def', 'call_docstring',
72 72 # These won't be printed but will be used to determine how to
73 73 # format the object
74 74 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
75 75 ]
76 76
77 77
78 78 def object_info(**kw):
79 79 """Make an object info dict with all fields present."""
80 80 infodict = dict(izip_longest(info_fields, [None]))
81 81 infodict.update(kw)
82 82 return infodict
83 83
84 84
85 85 def get_encoding(obj):
86 86 """Get encoding for python source file defining obj
87 87
88 88 Returns None if obj is not defined in a sourcefile.
89 89 """
90 90 ofile = find_file(obj)
91 91 # run contents of file through pager starting at line where the object
92 92 # is defined, as long as the file isn't binary and is actually on the
93 93 # filesystem.
94 94 if ofile is None:
95 95 return None
96 96 elif ofile.endswith(('.so', '.dll', '.pyd')):
97 97 return None
98 98 elif not os.path.isfile(ofile):
99 99 return None
100 100 else:
101 101 # Print only text files, not extension binaries. Note that
102 102 # getsourcelines returns lineno with 1-offset and page() uses
103 103 # 0-offset, so we must adjust.
104 104 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
105 105 encoding, lines = openpy.detect_encoding(buffer.readline)
106 106 return encoding
107 107
108 108 def getdoc(obj):
109 109 """Stable wrapper around inspect.getdoc.
110 110
111 111 This can't crash because of attribute problems.
112 112
113 113 It also attempts to call a getdoc() method on the given object. This
114 114 allows objects which provide their docstrings via non-standard mechanisms
115 (like Pyro proxies) to still be inspected by ipython's ? system."""
115 (like Pyro proxies) to still be inspected by ipython's ? system.
116 """
116 117 # Allow objects to offer customized documentation via a getdoc method:
117 118 try:
118 119 ds = obj.getdoc()
119 120 except Exception:
120 121 pass
121 122 else:
122 123 # if we get extra info, we add it to the normal docstring.
123 124 if isinstance(ds, string_types):
124 125 return inspect.cleandoc(ds)
125
126 126 try:
127 127 docstr = inspect.getdoc(obj)
128 128 encoding = get_encoding(obj)
129 129 return py3compat.cast_unicode(docstr, encoding=encoding)
130 130 except Exception:
131 131 # Harden against an inspect failure, which can occur with
132 # SWIG-wrapped extensions.
132 # extensions modules.
133 133 raise
134 134 return None
135 135
136 136
137 137 def getsource(obj, oname=''):
138 138 """Wrapper around inspect.getsource.
139 139
140 140 This can be modified by other projects to provide customized source
141 141 extraction.
142 142
143 143 Parameters
144 144 ----------
145 145 obj : object
146 146 an object whose source code we will attempt to extract
147 147 oname : str
148 148 (optional) a name under which the object is known
149 149
150 150 Returns
151 151 -------
152 152 src : unicode or None
153 153
154 154 """
155 155
156 156 if isinstance(obj, property):
157 157 sources = []
158 158 for attrname in ['fget', 'fset', 'fdel']:
159 159 fn = getattr(obj, attrname)
160 160 if fn is not None:
161 161 encoding = get_encoding(fn)
162 162 oname_prefix = ('%s.' % oname) if oname else ''
163 163 sources.append(cast_unicode(
164 164 ''.join(('# ', oname_prefix, attrname)),
165 165 encoding=encoding))
166 166 if inspect.isfunction(fn):
167 167 sources.append(dedent(getsource(fn)))
168 168 else:
169 169 # Default str/repr only prints function name,
170 170 # pretty.pretty prints module name too.
171 171 sources.append(cast_unicode(
172 172 '%s%s = %s\n' % (
173 173 oname_prefix, attrname, pretty(fn)),
174 174 encoding=encoding))
175 175 if sources:
176 176 return '\n'.join(sources)
177 177 else:
178 178 return None
179 179
180 180 else:
181 181 # Get source for non-property objects.
182 182
183 183 obj = _get_wrapped(obj)
184 184
185 185 try:
186 186 src = inspect.getsource(obj)
187 187 except TypeError:
188 188 # The object itself provided no meaningful source, try looking for
189 189 # its class definition instead.
190 190 if hasattr(obj, '__class__'):
191 191 try:
192 192 src = inspect.getsource(obj.__class__)
193 193 except TypeError:
194 194 return None
195 195
196 196 encoding = get_encoding(obj)
197 197 return cast_unicode(src, encoding=encoding)
198 198
199 199
200 200 def is_simple_callable(obj):
201 201 """True if obj is a function ()"""
202 202 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
203 203 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
204 204
205 205
206 206 def getargspec(obj):
207 207 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
208 208 :func:inspect.getargspec` on Python 2.
209 209
210 210 In addition to functions and methods, this can also handle objects with a
211 211 ``__call__`` attribute.
212 212 """
213 213 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
214 214 obj = obj.__call__
215 215
216 216 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
217 217
218 218
219 219 def format_argspec(argspec):
220 220 """Format argspect, convenience wrapper around inspect's.
221 221
222 222 This takes a dict instead of ordered arguments and calls
223 223 inspect.format_argspec with the arguments in the necessary order.
224 224 """
225 225 return inspect.formatargspec(argspec['args'], argspec['varargs'],
226 226 argspec['varkw'], argspec['defaults'])
227 227
228 228
229 229 def call_tip(oinfo, format_call=True):
230 230 """Extract call tip data from an oinfo dict.
231 231
232 232 Parameters
233 233 ----------
234 234 oinfo : dict
235 235
236 236 format_call : bool, optional
237 237 If True, the call line is formatted and returned as a string. If not, a
238 238 tuple of (name, argspec) is returned.
239 239
240 240 Returns
241 241 -------
242 242 call_info : None, str or (str, dict) tuple.
243 243 When format_call is True, the whole call information is formattted as a
244 244 single string. Otherwise, the object's name and its argspec dict are
245 245 returned. If no call information is available, None is returned.
246 246
247 247 docstring : str or None
248 248 The most relevant docstring for calling purposes is returned, if
249 249 available. The priority is: call docstring for callable instances, then
250 250 constructor docstring for classes, then main object's docstring otherwise
251 251 (regular functions).
252 252 """
253 253 # Get call definition
254 254 argspec = oinfo.get('argspec')
255 255 if argspec is None:
256 256 call_line = None
257 257 else:
258 258 # Callable objects will have 'self' as their first argument, prune
259 259 # it out if it's there for clarity (since users do *not* pass an
260 260 # extra first argument explicitly).
261 261 try:
262 262 has_self = argspec['args'][0] == 'self'
263 263 except (KeyError, IndexError):
264 264 pass
265 265 else:
266 266 if has_self:
267 267 argspec['args'] = argspec['args'][1:]
268 268
269 269 call_line = oinfo['name']+format_argspec(argspec)
270 270
271 271 # Now get docstring.
272 272 # The priority is: call docstring, constructor docstring, main one.
273 273 doc = oinfo.get('call_docstring')
274 274 if doc is None:
275 275 doc = oinfo.get('init_docstring')
276 276 if doc is None:
277 277 doc = oinfo.get('docstring','')
278 278
279 279 return call_line, doc
280 280
281 281
282 282 def _get_wrapped(obj):
283 283 """Get the original object if wrapped in one or more @decorators
284 284
285 285 Some objects automatically construct similar objects on any unrecognised
286 286 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
287 287 this will arbitrarily cut off after 100 levels of obj.__wrapped__
288 288 attribute access. --TK, Jan 2016
289 289 """
290 290 orig_obj = obj
291 291 i = 0
292 292 while safe_hasattr(obj, '__wrapped__'):
293 293 obj = obj.__wrapped__
294 294 i += 1
295 295 if i > 100:
296 296 # __wrapped__ is probably a lie, so return the thing we started with
297 297 return orig_obj
298 298 return obj
299 299
300 300 def find_file(obj):
301 301 """Find the absolute path to the file where an object was defined.
302 302
303 303 This is essentially a robust wrapper around `inspect.getabsfile`.
304 304
305 305 Returns None if no file can be found.
306 306
307 307 Parameters
308 308 ----------
309 309 obj : any Python object
310 310
311 311 Returns
312 312 -------
313 313 fname : str
314 314 The absolute path to the file where the object was defined.
315 315 """
316 316 obj = _get_wrapped(obj)
317 317
318 318 fname = None
319 319 try:
320 320 fname = inspect.getabsfile(obj)
321 321 except TypeError:
322 322 # For an instance, the file that matters is where its class was
323 323 # declared.
324 324 if hasattr(obj, '__class__'):
325 325 try:
326 326 fname = inspect.getabsfile(obj.__class__)
327 327 except TypeError:
328 328 # Can happen for builtins
329 329 pass
330 330 except:
331 331 pass
332 332 return cast_unicode(fname)
333 333
334 334
335 335 def find_source_lines(obj):
336 336 """Find the line number in a file where an object was defined.
337 337
338 338 This is essentially a robust wrapper around `inspect.getsourcelines`.
339 339
340 340 Returns None if no file can be found.
341 341
342 342 Parameters
343 343 ----------
344 344 obj : any Python object
345 345
346 346 Returns
347 347 -------
348 348 lineno : int
349 349 The line number where the object definition starts.
350 350 """
351 351 obj = _get_wrapped(obj)
352 352
353 353 try:
354 354 try:
355 355 lineno = inspect.getsourcelines(obj)[1]
356 356 except TypeError:
357 357 # For instances, try the class object like getsource() does
358 358 if hasattr(obj, '__class__'):
359 359 lineno = inspect.getsourcelines(obj.__class__)[1]
360 360 else:
361 361 lineno = None
362 362 except:
363 363 return None
364 364
365 365 return lineno
366 366
367 367
368 368 class Inspector(Colorable):
369
369 370 def __init__(self, color_table=InspectColors,
370 371 code_color_table=PyColorize.ANSICodeColors,
371 372 scheme='NoColor',
372 str_detail_level=0,
373 str_detail_level=0,
373 374 parent=None, config=None):
374 375 super(Inspector, self).__init__(parent=parent, config=config)
375 376 self.color_table = color_table
376 377 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
377 378 self.format = self.parser.format
378 379 self.str_detail_level = str_detail_level
379 380 self.set_active_scheme(scheme)
380 381
381 382 def _getdef(self,obj,oname=''):
382 383 """Return the call signature for any callable object.
383 384
384 385 If any exception is generated, None is returned instead and the
385 386 exception is suppressed."""
386 387 try:
387 388 hdef = oname + str(signature(obj))
388 389 return cast_unicode(hdef)
389 390 except:
390 391 return None
391 392
392 393 def __head(self,h):
393 394 """Return a header string with proper colors."""
394 395 return '%s%s%s' % (self.color_table.active_colors.header,h,
395 396 self.color_table.active_colors.normal)
396 397
397 398 def set_active_scheme(self, scheme):
398 399 self.color_table.set_active_scheme(scheme)
399 400 self.parser.color_table.set_active_scheme(scheme)
400 401
401 402 def noinfo(self, msg, oname):
402 403 """Generic message when no information is found."""
403 404 print('No %s found' % msg, end=' ')
404 405 if oname:
405 406 print('for %s' % oname)
406 407 else:
407 408 print()
408 409
409 410 def pdef(self, obj, oname=''):
410 411 """Print the call signature for any callable object.
411 412
412 413 If the object is a class, print the constructor information."""
413 414
414 415 if not callable(obj):
415 416 print('Object is not callable.')
416 417 return
417 418
418 419 header = ''
419 420
420 421 if inspect.isclass(obj):
421 422 header = self.__head('Class constructor information:\n')
422 423 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
423 424 obj = obj.__call__
424 425
425 426 output = self._getdef(obj,oname)
426 427 if output is None:
427 428 self.noinfo('definition header',oname)
428 429 else:
429 430 print(header,self.format(output), end=' ')
430 431
431 432 # In Python 3, all classes are new-style, so they all have __init__.
432 433 @skip_doctest_py3
433 def pdoc(self,obj,oname='',formatter = None):
434 def pdoc(self, obj, oname='', formatter=None):
434 435 """Print the docstring for any object.
435 436
436 437 Optional:
437 438 -formatter: a function to run the docstring through for specially
438 439 formatted docstrings.
439 440
440 441 Examples
441 442 --------
442 443
443 444 In [1]: class NoInit:
444 445 ...: pass
445 446
446 447 In [2]: class NoDoc:
447 448 ...: def __init__(self):
448 449 ...: pass
449 450
450 451 In [3]: %pdoc NoDoc
451 452 No documentation found for NoDoc
452 453
453 454 In [4]: %pdoc NoInit
454 455 No documentation found for NoInit
455 456
456 457 In [5]: obj = NoInit()
457 458
458 459 In [6]: %pdoc obj
459 460 No documentation found for obj
460 461
461 462 In [5]: obj2 = NoDoc()
462 463
463 464 In [6]: %pdoc obj2
464 465 No documentation found for obj2
465 466 """
466 467
467 468 head = self.__head # For convenience
468 469 lines = []
469 470 ds = getdoc(obj)
470 471 if formatter:
471 472 ds = formatter(ds)
472 473 if ds:
473 474 lines.append(head("Class docstring:"))
474 475 lines.append(indent(ds))
475 476 if inspect.isclass(obj) and hasattr(obj, '__init__'):
476 477 init_ds = getdoc(obj.__init__)
477 478 if init_ds is not None:
478 479 lines.append(head("Init docstring:"))
479 480 lines.append(indent(init_ds))
480 481 elif hasattr(obj,'__call__'):
481 482 call_ds = getdoc(obj.__call__)
482 483 if call_ds:
483 484 lines.append(head("Call docstring:"))
484 485 lines.append(indent(call_ds))
485 486
486 487 if not lines:
487 488 self.noinfo('documentation',oname)
488 489 else:
489 490 page.page('\n'.join(lines))
490 491
491 492 def psource(self, obj, oname=''):
492 493 """Print the source code for an object."""
493 494
494 495 # Flush the source cache because inspect can return out-of-date source
495 496 linecache.checkcache()
496 497 try:
497 498 src = getsource(obj, oname=oname)
498 499 except Exception:
499 500 src = None
500 501
501 502 if src is None:
502 503 self.noinfo('source', oname)
503 504 else:
504 505 page.page(self.format(src))
505 506
506 507 def pfile(self, obj, oname=''):
507 508 """Show the whole file where an object was defined."""
508
509
509 510 lineno = find_source_lines(obj)
510 511 if lineno is None:
511 512 self.noinfo('file', oname)
512 513 return
513 514
514 515 ofile = find_file(obj)
515 516 # run contents of file through pager starting at line where the object
516 517 # is defined, as long as the file isn't binary and is actually on the
517 518 # filesystem.
518 519 if ofile.endswith(('.so', '.dll', '.pyd')):
519 520 print('File %r is binary, not printing.' % ofile)
520 521 elif not os.path.isfile(ofile):
521 522 print('File %r does not exist, not printing.' % ofile)
522 523 else:
523 524 # Print only text files, not extension binaries. Note that
524 525 # getsourcelines returns lineno with 1-offset and page() uses
525 526 # 0-offset, so we must adjust.
526 527 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
527 528
528 529 def _format_fields(self, fields, title_width=0):
529 530 """Formats a list of fields for display.
530 531
531 532 Parameters
532 533 ----------
533 534 fields : list
534 535 A list of 2-tuples: (field_title, field_content)
535 536 title_width : int
536 537 How many characters to pad titles to. Default to longest title.
537 538 """
538 539 out = []
539 540 header = self.__head
540 541 if title_width == 0:
541 542 title_width = max(len(title) + 2 for title, _ in fields)
542 543 for title, content in fields:
543 544 if len(content.splitlines()) > 1:
544 title = header(title + ":") + "\n"
545 title = header(title + ':') + '\n'
545 546 else:
546 title = header((title+":").ljust(title_width))
547 title = header((title + ':').ljust(title_width))
547 548 out.append(cast_unicode(title) + cast_unicode(content))
548 549 return "\n".join(out)
549 550
550 def _format_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
551 """Format an info dict as text"""
551 def _mime_format(self, text, formatter=None):
552 """Return a mime bundle representation of the input text.
552 553
553 # hack docstring rendering
554 info = self.info(obj, oname=oname, formatter=None,
555 info=info, detail_level=detail_level)
556 if formatter:
557 return formatter(info["docstring"])
558
559 displayfields = []
560 def add_fields(fields):
561 for title, key in fields:
562 field = info[key]
563 if field is not None:
564 if key == "source":
565 displayfields.append((title, self.format(cast_unicode(field.rstrip()))))
566 else:
567 displayfields.append((title, field.rstrip()))
554 - if `formatter` is None, the returned mime bundle has
555 a `text/plain` field, with the input text.
556 a `text/html` field with a `<pre>` tag containing the input text.
557
558 - if `formatter` is not None, it must be a callable transforming the
559 input text into a mime bundle. Default values for `text/plain` and
560 `text/html` representations are the ones described above.
561
562 Note:
563
564 Formatters returning strings are supported but this behavior is deprecated.
565
566 """
567 text = cast_unicode(text)
568 defaults = {
569 'text/plain': text,
570 'text/html': '<pre>' + text + '</pre>'
571 }
572
573 if formatter is None:
574 return defaults
575 else:
576 formatted = formatter(text)
577
578 if not isinstance(formatted, dict):
579 # Handle the deprecated behavior of a formatter returning
580 # a string instead of a mime bundle.
581 return {
582 'text/plain': formatted,
583 'text/html': '<pre>' + formatted + '</pre>'
584 }
585
586 else:
587 return dict(defaults, **formatted)
588
589 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
590 """Retrieve an info dict and format it."""
591
592 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
593
594 mime = {
595 'text/plain': '',
596 'text/html': '',
597 }
598
599 def append_field(bundle, title, key, formatter=None):
600 field = info[key]
601 if field is not None:
602 formatted_field = self._mime_format(field, formatter)
603 bundle['text/plain'] += self.__head(title) + ':\n' + formatted_field['text/plain'] + '\n'
604 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
605
606 def code_formatter(text):
607 return {
608 'text/plain': self.format(text),
609 'text/html': '<pre>' + text + '</pre>'
610 }
568 611
569 612 if info['isalias']:
570 add_fields([('Repr', "string_form")])
613 append_field(mime, 'Repr', 'string_form')
571 614
572 615 elif info['ismagic']:
573 if detail_level > 0 and info['source'] is not None:
574 add_fields([("Source", "source")])
616 if detail_level > 0:
617 append_field(mime, 'Source', 'source', code_formatter)
575 618 else:
576 add_fields([("Docstring", "docstring")])
577
578 add_fields([("File", "file"),
579 ])
619 append_field(mime, 'Docstring', 'docstring', formatter)
620 append_field(mime, 'File', 'file')
580 621
581 622 elif info['isclass'] or is_simple_callable(obj):
582 623 # Functions, methods, classes
583 add_fields([("Signature", "definition"),
584 ("Init signature", "init_definition"),
585 ])
586 if detail_level > 0 and info['source'] is not None:
587 add_fields([("Source", "source")])
624 append_field(mime, 'Signature', 'definition', code_formatter)
625 append_field(mime, 'Init signature', 'init_definition', code_formatter)
626 if detail_level > 0:
627 append_field(mime, 'Source', 'source', code_formatter)
588 628 else:
589 add_fields([("Docstring", "docstring"),
590 ("Init docstring", "init_docstring"),
591 ])
629 append_field(mime, 'Docstring', 'docstring', formatter)
630 append_field(mime, 'Init docstring', 'init_docstring', formatter)
592 631
593 add_fields([('File', 'file'),
594 ('Type', 'type_name'),
595 ])
632 append_field(mime, 'File', 'file')
633 append_field(mime, 'Type', 'type_name')
596 634
597 635 else:
598 636 # General Python objects
599 add_fields([("Type", "type_name")])
637 append_field(mime, 'Type', 'type_name')
600 638
601 639 # Base class for old-style instances
602 640 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
603 displayfields.append(("Base Class", info['base_class'].rstrip()))
641 append_field(mime, 'Base Class', 'base_class')
604 642
605 add_fields([("String form", "string_form")])
643 append_field(mime, 'String form', 'string_form')
606 644
607 645 # Namespace
608 646 if info['namespace'] != 'Interactive':
609 displayfields.append(("Namespace", info['namespace'].rstrip()))
647 append_field(mime, 'Namespace', 'namespace')
610 648
611 add_fields([("Length", "length"),
612 ("File", "file"),
613 ("Signature", "definition"),
614 ])
649 append_field(mime, 'Length', 'length')
650 append_field(mime, 'File', 'file'),
651 append_field(mime, 'Signature', 'definition', code_formatter)
615 652
616 653 # Source or docstring, depending on detail level and whether
617 654 # source found.
618 if detail_level > 0 and info['source'] is not None:
619 displayfields.append(("Source",
620 self.format(cast_unicode(info['source']))))
621 elif info['docstring'] is not None:
622 displayfields.append(("Docstring", info["docstring"]))
623
624 add_fields([("Class docstring", "class_docstring"),
625 ("Init docstring", "init_docstring"),
626 ("Call signature", "call_def"),
627 ("Call docstring", "call_docstring")])
628
629 if displayfields:
630 return self._format_fields(displayfields)
631 else:
632 return u''
633
655 if detail_level > 0:
656 append_field(mime, 'Source', 'source', code_formatter)
657 else:
658 append_field(mime, 'Docstring', 'docstring', formatter)
659
660 append_field(mime, 'Class docstring', 'class_docstring', formatter)
661 append_field(mime, 'Init docstring', 'init_docstring', formatter)
662 append_field(mime, 'Call signature', 'call_def', code_formatter)
663 append_field(mime, 'Call docstring', 'call_docstring', formatter)
664
665 return mime
666
634 667 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0):
635 668 """Show detailed information about an object.
636 669
637 670 Optional arguments:
638 671
639 672 - oname: name of the variable pointing to the object.
640 673
641 - formatter: special formatter for docstrings (see pdoc)
674 - formatter: callable (optional)
675 A special formatter for docstrings.
676
677 The formatter is a callable that takes a string as an input
678 and returns either a formatted string or a mime type bundle
679 in the form of a dictionnary.
680
681 Although the support of custom formatter returning a string
682 instead of a mime type bundle is deprecated.
642 683
643 684 - info: a structure with some information fields which may have been
644 685 precomputed already.
645 686
646 687 - detail_level: if set to 1, more information is given.
647 688 """
648 text = self._format_info(obj, oname, formatter, info, detail_level)
649 if text:
650 page.page(text)
651
689 info = self._get_info(obj, oname, formatter, info, detail_level)
690 if info:
691 page.page(info)
692
652 693 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
694 """DEPRECATED. Compute a dict with detailed information about an object.
695 """
696 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
697
698 def _info(self, obj, oname='', info=None, detail_level=0):
653 699 """Compute a dict with detailed information about an object.
654 700
655 701 Optional arguments:
656 702
657 703 - oname: name of the variable pointing to the object.
658 704
659 - formatter: special formatter for docstrings (see pdoc)
660
661 705 - info: a structure with some information fields which may have been
662 706 precomputed already.
663 707
664 708 - detail_level: if set to 1, more information is given.
665 709 """
666 710
667 711 obj_type = type(obj)
668 712
669 713 if info is None:
670 714 ismagic = 0
671 715 isalias = 0
672 716 ospace = ''
673 717 else:
674 718 ismagic = info.ismagic
675 719 isalias = info.isalias
676 720 ospace = info.namespace
677 721
678 722 # Get docstring, special-casing aliases:
679 723 if isalias:
680 724 if not callable(obj):
681 725 try:
682 726 ds = "Alias to the system command:\n %s" % obj[1]
683 727 except:
684 728 ds = "Alias: " + str(obj)
685 729 else:
686 730 ds = "Alias to " + str(obj)
687 731 if obj.__doc__:
688 732 ds += "\nDocstring:\n" + obj.__doc__
689 733 else:
690 734 ds = getdoc(obj)
691 735 if ds is None:
692 736 ds = '<no docstring>'
693 if formatter is not None:
694 ds = formatter(ds)
695 737
696 738 # store output in a dict, we initialize it here and fill it as we go
697 739 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
698 740
699 741 string_max = 200 # max size of strings to show (snipped if longer)
700 shalf = int((string_max -5)/2)
742 shalf = int((string_max - 5) / 2)
701 743
702 744 if ismagic:
703 745 obj_type_name = 'Magic function'
704 746 elif isalias:
705 747 obj_type_name = 'System alias'
706 748 else:
707 749 obj_type_name = obj_type.__name__
708 750 out['type_name'] = obj_type_name
709 751
710 752 try:
711 753 bclass = obj.__class__
712 754 out['base_class'] = str(bclass)
713 755 except: pass
714 756
715 757 # String form, but snip if too long in ? form (full in ??)
716 758 if detail_level >= self.str_detail_level:
717 759 try:
718 760 ostr = str(obj)
719 761 str_head = 'string_form'
720 762 if not detail_level and len(ostr)>string_max:
721 763 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
722 764 ostr = ("\n" + " " * len(str_head.expandtabs())).\
723 765 join(q.strip() for q in ostr.split("\n"))
724 766 out[str_head] = ostr
725 767 except:
726 768 pass
727 769
728 770 if ospace:
729 771 out['namespace'] = ospace
730 772
731 773 # Length (for strings and lists)
732 774 try:
733 775 out['length'] = str(len(obj))
734 776 except: pass
735 777
736 778 # Filename where object was defined
737 779 binary_file = False
738 780 fname = find_file(obj)
739 781 if fname is None:
740 782 # if anything goes wrong, we don't want to show source, so it's as
741 783 # if the file was binary
742 784 binary_file = True
743 785 else:
744 786 if fname.endswith(('.so', '.dll', '.pyd')):
745 787 binary_file = True
746 788 elif fname.endswith('<string>'):
747 789 fname = 'Dynamically generated function. No source code available.'
748 790 out['file'] = compress_user(fname)
749 791
750 792 # Original source code for a callable, class or property.
751 793 if detail_level:
752 794 # Flush the source cache because inspect can return out-of-date
753 795 # source
754 796 linecache.checkcache()
755 797 try:
756 798 if isinstance(obj, property) or not binary_file:
757 799 src = getsource(obj, oname)
758 800 if src is not None:
759 801 src = src.rstrip()
760 802 out['source'] = src
761 803
762 804 except Exception:
763 805 pass
764 806
765 807 # Add docstring only if no source is to be shown (avoid repetitions).
766 808 if ds and out.get('source', None) is None:
767 809 out['docstring'] = ds
768 810
769 811 # Constructor docstring for classes
770 812 if inspect.isclass(obj):
771 813 out['isclass'] = True
772 814
773 815 # get the init signature:
774 816 try:
775 817 init_def = self._getdef(obj, oname)
776 818 except AttributeError:
777 819 init_def = None
778 820
779 821 if init_def:
780 822 out['init_definition'] = self.format(init_def)
781 823
782 824 # get the __init__ docstring
783 825 try:
784 826 obj_init = obj.__init__
785 827 except AttributeError:
786 828 init_ds = None
787 829 else:
788 830 init_ds = getdoc(obj_init)
789 831 # Skip Python's auto-generated docstrings
790 832 if init_ds == _object_init_docstring:
791 833 init_ds = None
792 834
793 835 if init_ds:
794 836 out['init_docstring'] = init_ds
795 837
796 838 # and class docstring for instances:
797 839 else:
798 840 # reconstruct the function definition and print it:
799 841 defln = self._getdef(obj, oname)
800 842 if defln:
801 out['definition'] = self.format(defln)
843 out['definition'] = defln
802 844
803 845 # First, check whether the instance docstring is identical to the
804 846 # class one, and print it separately if they don't coincide. In
805 847 # most cases they will, but it's nice to print all the info for
806 848 # objects which use instance-customized docstrings.
807 849 if ds:
808 850 try:
809 851 cls = getattr(obj,'__class__')
810 852 except:
811 853 class_ds = None
812 854 else:
813 855 class_ds = getdoc(cls)
814 856 # Skip Python's auto-generated docstrings
815 857 if class_ds in _builtin_type_docstrings:
816 858 class_ds = None
817 859 if class_ds and ds != class_ds:
818 860 out['class_docstring'] = class_ds
819 861
820 862 # Next, try to show constructor docstrings
821 863 try:
822 864 init_ds = getdoc(obj.__init__)
823 865 # Skip Python's auto-generated docstrings
824 866 if init_ds == _object_init_docstring:
825 867 init_ds = None
826 868 except AttributeError:
827 869 init_ds = None
828 870 if init_ds:
829 871 out['init_docstring'] = init_ds
830 872
831 873 # Call form docstring for callable instances
832 874 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
833 875 call_def = self._getdef(obj.__call__, oname)
834 876 if call_def:
835 call_def = self.format(call_def)
877 call_def = call_def
836 878 # it may never be the case that call def and definition differ,
837 879 # but don't include the same signature twice
838 880 if call_def != out.get('definition'):
839 881 out['call_def'] = call_def
840 882 call_ds = getdoc(obj.__call__)
841 883 # Skip Python's auto-generated docstrings
842 884 if call_ds == _func_call_docstring:
843 885 call_ds = None
844 886 if call_ds:
845 887 out['call_docstring'] = call_ds
846 888
847 889 # Compute the object's argspec as a callable. The key is to decide
848 890 # whether to pull it from the object itself, from its __init__ or
849 891 # from its __call__ method.
850 892
851 893 if inspect.isclass(obj):
852 894 # Old-style classes need not have an __init__
853 895 callable_obj = getattr(obj, "__init__", None)
854 896 elif callable(obj):
855 897 callable_obj = obj
856 898 else:
857 899 callable_obj = None
858 900
859 901 if callable_obj is not None:
860 902 try:
861 903 argspec = getargspec(callable_obj)
862 904 except (TypeError, AttributeError):
863 905 # For extensions/builtins we can't retrieve the argspec
864 906 pass
865 907 else:
866 908 # named tuples' _asdict() method returns an OrderedDict, but we
867 909 # we want a normal
868 910 out['argspec'] = argspec_dict = dict(argspec._asdict())
869 911 # We called this varkw before argspec became a named tuple.
870 912 # With getfullargspec it's also called varkw.
871 913 if 'varkw' not in argspec_dict:
872 914 argspec_dict['varkw'] = argspec_dict.pop('keywords')
873 915
874 916 return object_info(**out)
875 917
876 918 def psearch(self,pattern,ns_table,ns_search=[],
877 919 ignore_case=False,show_all=False):
878 920 """Search namespaces with wildcards for objects.
879 921
880 922 Arguments:
881 923
882 924 - pattern: string containing shell-like wildcards to use in namespace
883 925 searches and optionally a type specification to narrow the search to
884 926 objects of that type.
885 927
886 928 - ns_table: dict of name->namespaces for search.
887 929
888 930 Optional arguments:
889 931
890 932 - ns_search: list of namespace names to include in search.
891 933
892 934 - ignore_case(False): make the search case-insensitive.
893 935
894 936 - show_all(False): show all names, including those starting with
895 937 underscores.
896 938 """
897 939 #print 'ps pattern:<%r>' % pattern # dbg
898 940
899 941 # defaults
900 942 type_pattern = 'all'
901 943 filter = ''
902 944
903 945 cmds = pattern.split()
904 946 len_cmds = len(cmds)
905 947 if len_cmds == 1:
906 948 # Only filter pattern given
907 949 filter = cmds[0]
908 950 elif len_cmds == 2:
909 951 # Both filter and type specified
910 952 filter,type_pattern = cmds
911 953 else:
912 954 raise ValueError('invalid argument string for psearch: <%s>' %
913 955 pattern)
914 956
915 957 # filter search namespaces
916 958 for name in ns_search:
917 959 if name not in ns_table:
918 960 raise ValueError('invalid namespace <%s>. Valid names: %s' %
919 961 (name,ns_table.keys()))
920 962
921 963 #print 'type_pattern:',type_pattern # dbg
922 964 search_result, namespaces_seen = set(), set()
923 965 for ns_name in ns_search:
924 966 ns = ns_table[ns_name]
925 967 # Normally, locals and globals are the same, so we just check one.
926 968 if id(ns) in namespaces_seen:
927 969 continue
928 970 namespaces_seen.add(id(ns))
929 971 tmp_res = list_namespace(ns, type_pattern, filter,
930 972 ignore_case=ignore_case, show_all=show_all)
931 973 search_result.update(tmp_res)
932 974
933 975 page.page('\n'.join(sorted(search_result)))
@@ -1,432 +1,432 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 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
274 274 fname = __file__
275 275 if fname.endswith(".pyc"):
276 276 fname = fname[:-1]
277 277 # case-insensitive comparison needed on some filesystems
278 278 # e.g. Windows:
279 279 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
280 280 nt.assert_equal(i['definition'], None)
281 281 nt.assert_equal(i['docstring'], Call.__doc__)
282 282 nt.assert_equal(i['source'], None)
283 283 nt.assert_true(i['isclass'])
284 284 _self_py2 = '' if py3compat.PY3 else 'self, '
285 285 nt.assert_equal(i['init_definition'], "Call(%sx, y=1)\n" % _self_py2)
286 286 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
287 287
288 288 i = inspector.info(Call, detail_level=1)
289 289 nt.assert_not_equal(i['source'], None)
290 290 nt.assert_equal(i['docstring'], None)
291 291
292 292 c = Call(1)
293 293 c.__doc__ = "Modified instance docstring"
294 294 i = inspector.info(c)
295 295 nt.assert_equal(i['type_name'], 'Call')
296 296 nt.assert_equal(i['docstring'], "Modified instance docstring")
297 297 nt.assert_equal(i['class_docstring'], Call.__doc__)
298 298 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
299 299 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
300 300
301 301 # Test old-style classes, which for example may not have an __init__ method.
302 302 if not py3compat.PY3:
303 303 i = inspector.info(OldStyle)
304 304 nt.assert_equal(i['type_name'], 'classobj')
305 305
306 306 i = inspector.info(OldStyle())
307 307 nt.assert_equal(i['type_name'], 'instance')
308 308 nt.assert_equal(i['docstring'], OldStyle.__doc__)
309 309
310 310 def test_class_signature():
311 311 info = inspector.info(HasSignature, 'HasSignature')
312 312 nt.assert_equal(info['init_definition'], "HasSignature(test)\n")
313 313 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
314 314
315 315 def test_info_awkward():
316 316 # Just test that this doesn't throw an error.
317 317 i = inspector.info(Awkward())
318 318
319 319 def test_bool_raise():
320 320 inspector.info(NoBoolCall())
321 321
322 322 def test_info_serialliar():
323 323 fib_tracker = [0]
324 324 i = inspector.info(SerialLiar(fib_tracker))
325 325
326 326 # Nested attribute access should be cut off at 100 levels deep to avoid
327 327 # infinite loops: https://github.com/ipython/ipython/issues/9122
328 328 nt.assert_less(fib_tracker[0], 9000)
329 329
330 330 def test_calldef_none():
331 331 # We should ignore __call__ for all of these.
332 332 for obj in [f, SimpleClass().method, any, str.upper]:
333 333 print(obj)
334 334 i = inspector.info(obj)
335 335 nt.assert_is(i['call_def'], None)
336 336
337 337 if py3compat.PY3:
338 338 exec("def f_kwarg(pos, *, kwonly): pass")
339 339
340 340 @skipif(not py3compat.PY3)
341 341 def test_definition_kwonlyargs():
342 342 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
343 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
343 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)")
344 344
345 345 def test_getdoc():
346 346 class A(object):
347 347 """standard docstring"""
348 348 pass
349
349
350 350 class B(object):
351 351 """standard docstring"""
352 352 def getdoc(self):
353 353 return "custom docstring"
354 354
355 355 class C(object):
356 356 """standard docstring"""
357 357 def getdoc(self):
358 358 return None
359 359
360 360 a = A()
361 361 b = B()
362 362 c = C()
363 363
364 364 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
365 365 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
366 366 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
367 367
368 368
369 369 def test_empty_property_has_no_source():
370 370 i = inspector.info(property(), detail_level=1)
371 371 nt.assert_is(i['source'], None)
372 372
373 373
374 374 def test_property_sources():
375 375 import zlib
376 376
377 377 class A(object):
378 378 @property
379 379 def foo(self):
380 380 return 'bar'
381 381
382 382 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
383 383
384 384 id = property(id)
385 385 compress = property(zlib.compress)
386 386
387 387 i = inspector.info(A.foo, detail_level=1)
388 388 nt.assert_in('def foo(self):', i['source'])
389 389 nt.assert_in('lambda self, v:', i['source'])
390 390
391 391 i = inspector.info(A.id, detail_level=1)
392 392 nt.assert_in('fget = <function id>', i['source'])
393 393
394 394 i = inspector.info(A.compress, detail_level=1)
395 395 nt.assert_in('fget = <function zlib.compress>', i['source'])
396 396
397 397
398 398 def test_property_docstring_is_in_info_for_detail_level_0():
399 399 class A(object):
400 400 @property
401 401 def foobar(self):
402 402 """This is `foobar` property."""
403 403 pass
404 404
405 405 ip.user_ns['a_obj'] = A()
406 406 nt.assert_equals(
407 407 'This is `foobar` property.',
408 408 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
409 409
410 410 ip.user_ns['a_cls'] = A
411 411 nt.assert_equals(
412 412 'This is `foobar` property.',
413 413 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
414 414
415 415
416 416 def test_pdef():
417 417 # See gh-1914
418 418 def foo(): pass
419 419 inspector.pdef(foo, 'foo')
420 420
421 421 def test_pinfo_nonascii():
422 422 # See gh-1177
423 423 from . import nonascii2
424 424 ip.user_ns['nonascii2'] = nonascii2
425 425 ip._inspect('pinfo', 'nonascii2', detail_level=1)
426 426
427 427 def test_pinfo_magic():
428 428 with AssertPrints('Docstring:'):
429 429 ip._inspect('pinfo', 'lsmagic', detail_level=0)
430 430
431 431 with AssertPrints('Source:'):
432 432 ip._inspect('pinfo', 'lsmagic', detail_level=1)
General Comments 0
You need to be logged in to leave comments. Login now