##// END OF EJS Templates
Fix finding of file info for magics and decorated functions....
Fernando Perez -
Show More
@@ -1,772 +1,827 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 #*****************************************************************************
11 11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #*****************************************************************************
16 16
17 17 __all__ = ['Inspector','InspectColors']
18 18
19 19 # stdlib modules
20 20 import __builtin__
21 21 import inspect
22 22 import linecache
23 23 import os
24 24 import sys
25 25 import types
26 26 from collections import namedtuple
27 27 try:
28 28 from itertools import izip_longest
29 29 except ImportError:
30 30 from itertools import zip_longest as izip_longest
31 31
32 32 # IPython's own
33 33 from IPython.core import page
34 34 from IPython.testing.skipdoctest import skip_doctest_py3
35 35 from IPython.utils import PyColorize
36 36 from IPython.utils import io
37 37 from IPython.utils import py3compat
38 38 from IPython.utils.text import indent
39 39 from IPython.utils.wildcard import list_namespace
40 40 from IPython.utils.coloransi import *
41 41
42 42 #****************************************************************************
43 43 # Builtin color schemes
44 44
45 45 Colors = TermColors # just a shorthand
46 46
47 47 # Build a few color schemes
48 48 NoColor = ColorScheme(
49 49 'NoColor',{
50 50 'header' : Colors.NoColor,
51 51 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
52 52 } )
53 53
54 54 LinuxColors = ColorScheme(
55 55 'Linux',{
56 56 'header' : Colors.LightRed,
57 57 'normal' : Colors.Normal # color off (usu. Colors.Normal)
58 58 } )
59 59
60 60 LightBGColors = ColorScheme(
61 61 'LightBG',{
62 62 'header' : Colors.Red,
63 63 'normal' : Colors.Normal # color off (usu. Colors.Normal)
64 64 } )
65 65
66 66 # Build table of color schemes (needed by the parser)
67 67 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
68 68 'Linux')
69 69
70 70 #****************************************************************************
71 71 # Auxiliary functions and objects
72 72
73 73 # See the messaging spec for the definition of all these fields. This list
74 74 # effectively defines the order of display
75 75 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
76 76 'length', 'file', 'definition', 'docstring', 'source',
77 77 'init_definition', 'class_docstring', 'init_docstring',
78 78 'call_def', 'call_docstring',
79 79 # These won't be printed but will be used to determine how to
80 80 # format the object
81 81 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
82 82 ]
83 83
84 84
85 85 def object_info(**kw):
86 86 """Make an object info dict with all fields present."""
87 87 infodict = dict(izip_longest(info_fields, [None]))
88 88 infodict.update(kw)
89 89 return infodict
90 90
91 91
92 92 def getdoc(obj):
93 93 """Stable wrapper around inspect.getdoc.
94 94
95 95 This can't crash because of attribute problems.
96 96
97 97 It also attempts to call a getdoc() method on the given object. This
98 98 allows objects which provide their docstrings via non-standard mechanisms
99 99 (like Pyro proxies) to still be inspected by ipython's ? system."""
100 100 # Allow objects to offer customized documentation via a getdoc method:
101 101 try:
102 102 ds = obj.getdoc()
103 103 except Exception:
104 104 pass
105 105 else:
106 106 # if we get extra info, we add it to the normal docstring.
107 107 if isinstance(ds, basestring):
108 108 return inspect.cleandoc(ds)
109 109
110 110 try:
111 111 return inspect.getdoc(obj)
112 112 except Exception:
113 113 # Harden against an inspect failure, which can occur with
114 114 # SWIG-wrapped extensions.
115 115 return None
116 116
117 117
118 118 def getsource(obj,is_binary=False):
119 119 """Wrapper around inspect.getsource.
120 120
121 121 This can be modified by other projects to provide customized source
122 122 extraction.
123 123
124 124 Inputs:
125 125
126 126 - obj: an object whose source code we will attempt to extract.
127 127
128 128 Optional inputs:
129 129
130 130 - is_binary: whether the object is known to come from a binary source.
131 131 This implementation will skip returning any output for binary objects, but
132 132 custom extractors may know how to meaningfully process them."""
133 133
134 134 if is_binary:
135 135 return None
136 136 else:
137 137 # get source if obj was decorated with @decorator
138 138 if hasattr(obj,"__wrapped__"):
139 139 obj = obj.__wrapped__
140 140 try:
141 141 src = inspect.getsource(obj)
142 142 except TypeError:
143 143 if hasattr(obj,'__class__'):
144 144 src = inspect.getsource(obj.__class__)
145 145 return src
146 146
147 147 def getargspec(obj):
148 148 """Get the names and default values of a function's arguments.
149 149
150 150 A tuple of four things is returned: (args, varargs, varkw, defaults).
151 151 'args' is a list of the argument names (it may contain nested lists).
152 152 'varargs' and 'varkw' are the names of the * and ** arguments or None.
153 153 'defaults' is an n-tuple of the default values of the last n arguments.
154 154
155 155 Modified version of inspect.getargspec from the Python Standard
156 156 Library."""
157 157
158 158 if inspect.isfunction(obj):
159 159 func_obj = obj
160 160 elif inspect.ismethod(obj):
161 161 func_obj = obj.im_func
162 162 elif hasattr(obj, '__call__'):
163 163 func_obj = obj.__call__
164 164 else:
165 165 raise TypeError('arg is not a Python function')
166 166 args, varargs, varkw = inspect.getargs(func_obj.func_code)
167 167 return args, varargs, varkw, func_obj.func_defaults
168 168
169 169
170 170 def format_argspec(argspec):
171 171 """Format argspect, convenience wrapper around inspect's.
172 172
173 173 This takes a dict instead of ordered arguments and calls
174 174 inspect.format_argspec with the arguments in the necessary order.
175 175 """
176 176 return inspect.formatargspec(argspec['args'], argspec['varargs'],
177 177 argspec['varkw'], argspec['defaults'])
178 178
179 179
180 180 def call_tip(oinfo, format_call=True):
181 181 """Extract call tip data from an oinfo dict.
182 182
183 183 Parameters
184 184 ----------
185 185 oinfo : dict
186 186
187 187 format_call : bool, optional
188 188 If True, the call line is formatted and returned as a string. If not, a
189 189 tuple of (name, argspec) is returned.
190 190
191 191 Returns
192 192 -------
193 193 call_info : None, str or (str, dict) tuple.
194 194 When format_call is True, the whole call information is formattted as a
195 195 single string. Otherwise, the object's name and its argspec dict are
196 196 returned. If no call information is available, None is returned.
197 197
198 198 docstring : str or None
199 199 The most relevant docstring for calling purposes is returned, if
200 200 available. The priority is: call docstring for callable instances, then
201 201 constructor docstring for classes, then main object's docstring otherwise
202 202 (regular functions).
203 203 """
204 204 # Get call definition
205 205 argspec = oinfo.get('argspec')
206 206 if argspec is None:
207 207 call_line = None
208 208 else:
209 209 # Callable objects will have 'self' as their first argument, prune
210 210 # it out if it's there for clarity (since users do *not* pass an
211 211 # extra first argument explicitly).
212 212 try:
213 213 has_self = argspec['args'][0] == 'self'
214 214 except (KeyError, IndexError):
215 215 pass
216 216 else:
217 217 if has_self:
218 218 argspec['args'] = argspec['args'][1:]
219 219
220 220 call_line = oinfo['name']+format_argspec(argspec)
221 221
222 222 # Now get docstring.
223 223 # The priority is: call docstring, constructor docstring, main one.
224 224 doc = oinfo.get('call_docstring')
225 225 if doc is None:
226 226 doc = oinfo.get('init_docstring')
227 227 if doc is None:
228 228 doc = oinfo.get('docstring','')
229 229
230 230 return call_line, doc
231 231
232 232
233 def find_file(obj):
234 """Find the absolute path to the file where an object was defined.
235
236 This is essentially a robust wrapper around `inspect.getabsfile`.
237
238 Returns None if no file can be found.
239
240 Parameters
241 ----------
242 obj : any Python object
243
244 Returns
245 -------
246 fname : str
247 The absolute path to the file where the object was defined.
248 """
249 try:
250 fname = inspect.getabsfile(obj)
251 except TypeError:
252 # For an instance, the file that matters is where its class was
253 # declared.
254 if hasattr(obj,'__class__'):
255 try:
256 fname = inspect.getabsfile(obj.__class__)
257 except TypeError:
258 # Can happen for builtins
259 fname = None
260 except:
261 fname = None
262 else:
263 if fname.endswith('<string>') and hasattr(obj, '__wrapped__'):
264 # Analyze decorated functions and methods correctly
265 fname = inspect.getabsfile(obj.__wrapped__)
266 return fname
267
268
269 def find_source_lines(obj):
270 """Find the line number in a file where an object was defined.
271
272 This is essentially a robust wrapper around `inspect.getsourcelines`.
273
274 Returns None if no file can be found.
275
276 Parameters
277 ----------
278 obj : any Python object
279
280 Returns
281 -------
282 lineno : int
283 The line number where the object definition starts.
284 """
285 try:
286 try:
287 lineno = inspect.getsourcelines(obj)[1]
288 except TypeError:
289 # For instances, try the class object like getsource() does
290 if hasattr(obj,'__class__'):
291 lineno = inspect.getsourcelines(obj.__class__)[1]
292 # Adjust the inspected object so getabsfile() below works
293 obj = obj.__class__
294 except IOError:
295 if hasattr(obj, '__wrapped__'):
296 obj = obj.__wrapped__
297 lineno = inspect.getsourcelines(obj)[1]
298 except:
299 return None
300
301 return lineno
302
303
233 304 class Inspector:
234 305 def __init__(self, color_table=InspectColors,
235 306 code_color_table=PyColorize.ANSICodeColors,
236 307 scheme='NoColor',
237 308 str_detail_level=0):
238 309 self.color_table = color_table
239 310 self.parser = PyColorize.Parser(code_color_table,out='str')
240 311 self.format = self.parser.format
241 312 self.str_detail_level = str_detail_level
242 313 self.set_active_scheme(scheme)
243 314
244 315 def _getdef(self,obj,oname=''):
245 316 """Return the definition header for any callable object.
246 317
247 318 If any exception is generated, None is returned instead and the
248 319 exception is suppressed."""
249 320
250 321 try:
251 322 # We need a plain string here, NOT unicode!
252 323 hdef = oname + inspect.formatargspec(*getargspec(obj))
253 324 return py3compat.unicode_to_str(hdef, 'ascii')
254 325 except:
255 326 return None
256 327
257 328 def __head(self,h):
258 329 """Return a header string with proper colors."""
259 330 return '%s%s%s' % (self.color_table.active_colors.header,h,
260 331 self.color_table.active_colors.normal)
261 332
262 def set_active_scheme(self,scheme):
333 def set_active_scheme(self, scheme):
263 334 self.color_table.set_active_scheme(scheme)
264 335 self.parser.color_table.set_active_scheme(scheme)
265 336
266 def noinfo(self,msg,oname):
337 def noinfo(self, msg, oname):
267 338 """Generic message when no information is found."""
268 339 print 'No %s found' % msg,
269 340 if oname:
270 341 print 'for %s' % oname
271 342 else:
272 343 print
273 344
274 def pdef(self,obj,oname=''):
345 def pdef(self, obj, oname=''):
275 346 """Print the definition header for any callable object.
276 347
277 348 If the object is a class, print the constructor information."""
278 349
279 350 if not callable(obj):
280 351 print 'Object is not callable.'
281 352 return
282 353
283 354 header = ''
284 355
285 356 if inspect.isclass(obj):
286 357 header = self.__head('Class constructor information:\n')
287 358 obj = obj.__init__
288 359 elif type(obj) is types.InstanceType:
289 360 obj = obj.__call__
290 361
291 362 output = self._getdef(obj,oname)
292 363 if output is None:
293 364 self.noinfo('definition header',oname)
294 365 else:
295 366 print >>io.stdout, header,self.format(output),
296 367
297 368 # In Python 3, all classes are new-style, so they all have __init__.
298 369 @skip_doctest_py3
299 370 def pdoc(self,obj,oname='',formatter = None):
300 371 """Print the docstring for any object.
301 372
302 373 Optional:
303 374 -formatter: a function to run the docstring through for specially
304 375 formatted docstrings.
305 376
306 377 Examples
307 378 --------
308 379
309 380 In [1]: class NoInit:
310 381 ...: pass
311 382
312 383 In [2]: class NoDoc:
313 384 ...: def __init__(self):
314 385 ...: pass
315 386
316 387 In [3]: %pdoc NoDoc
317 388 No documentation found for NoDoc
318 389
319 390 In [4]: %pdoc NoInit
320 391 No documentation found for NoInit
321 392
322 393 In [5]: obj = NoInit()
323 394
324 395 In [6]: %pdoc obj
325 396 No documentation found for obj
326 397
327 398 In [5]: obj2 = NoDoc()
328 399
329 400 In [6]: %pdoc obj2
330 401 No documentation found for obj2
331 402 """
332 403
333 404 head = self.__head # For convenience
334 405 lines = []
335 406 ds = getdoc(obj)
336 407 if formatter:
337 408 ds = formatter(ds)
338 409 if ds:
339 410 lines.append(head("Class Docstring:"))
340 411 lines.append(indent(ds))
341 412 if inspect.isclass(obj) and hasattr(obj, '__init__'):
342 413 init_ds = getdoc(obj.__init__)
343 414 if init_ds is not None:
344 415 lines.append(head("Constructor Docstring:"))
345 416 lines.append(indent(init_ds))
346 417 elif hasattr(obj,'__call__'):
347 418 call_ds = getdoc(obj.__call__)
348 419 if call_ds:
349 420 lines.append(head("Calling Docstring:"))
350 421 lines.append(indent(call_ds))
351 422
352 423 if not lines:
353 424 self.noinfo('documentation',oname)
354 425 else:
355 426 page.page('\n'.join(lines))
356 427
357 428 def psource(self,obj,oname=''):
358 429 """Print the source code for an object."""
359 430
360 431 # Flush the source cache because inspect can return out-of-date source
361 432 linecache.checkcache()
362 433 try:
363 434 src = getsource(obj)
364 435 except:
365 436 self.noinfo('source',oname)
366 437 else:
367 438 page.page(self.format(py3compat.unicode_to_str(src)))
368 439
369 def pfile(self,obj,oname=''):
440 def pfile(self, obj, oname=''):
370 441 """Show the whole file where an object was defined."""
371
372 try:
373 try:
374 lineno = inspect.getsourcelines(obj)[1]
375 except TypeError:
376 # For instances, try the class object like getsource() does
377 if hasattr(obj,'__class__'):
378 lineno = inspect.getsourcelines(obj.__class__)[1]
379 # Adjust the inspected object so getabsfile() below works
380 obj = obj.__class__
381 except:
382 self.noinfo('file',oname)
442
443 lineno = find_source_lines(obj)
444 if lineno is None:
445 self.noinfo('file', oname)
383 446 return
384 447
385 # We only reach this point if object was successfully queried
386
387 # run contents of file through pager starting at line
388 # where the object is defined
389 ofile = inspect.getabsfile(obj)
390
448 ofile = find_file(obj)
449 # run contents of file through pager starting at line where the object
450 # is defined, as long as the file isn't binary and is actually on the
451 # filesystem.
391 452 if ofile.endswith(('.so', '.dll', '.pyd')):
392 453 print 'File %r is binary, not printing.' % ofile
393 454 elif not os.path.isfile(ofile):
394 455 print 'File %r does not exist, not printing.' % ofile
395 456 else:
396 457 # Print only text files, not extension binaries. Note that
397 458 # getsourcelines returns lineno with 1-offset and page() uses
398 459 # 0-offset, so we must adjust.
399 page.page(self.format(open(ofile).read()),lineno-1)
460 page.page(self.format(open(ofile).read()), lineno-1)
400 461
401 462 def _format_fields(self, fields, title_width=12):
402 463 """Formats a list of fields for display.
403 464
404 465 Parameters
405 466 ----------
406 467 fields : list
407 468 A list of 2-tuples: (field_title, field_content)
408 469 title_width : int
409 470 How many characters to pad titles to. Default 12.
410 471 """
411 472 out = []
412 473 header = self.__head
413 474 for title, content in fields:
414 475 if len(content.splitlines()) > 1:
415 476 title = header(title + ":") + "\n"
416 477 else:
417 478 title = header((title+":").ljust(title_width))
418 479 out.append(title + content)
419 480 return "\n".join(out)
420 481
421 482 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
422 483 pinfo_fields1 = [("Type", "type_name"),
423 484 ("Base Class", "base_class"),
424 485 ("String Form", "string_form"),
425 486 ("Namespace", "namespace"),
426 487 ("Length", "length"),
427 488 ("File", "file"),
428 489 ("Definition", "definition")]
429 490
430 491 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
431 492 ("Constructor Docstring","init_docstring"),
432 493 ("Call def", "call_def"),
433 494 ("Call docstring", "call_docstring")]
434 495
435 496 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
436 497 """Show detailed information about an object.
437 498
438 499 Optional arguments:
439 500
440 501 - oname: name of the variable pointing to the object.
441 502
442 503 - formatter: special formatter for docstrings (see pdoc)
443 504
444 505 - info: a structure with some information fields which may have been
445 506 precomputed already.
446 507
447 508 - detail_level: if set to 1, more information is given.
448 509 """
449 510 info = self.info(obj, oname=oname, formatter=formatter,
450 511 info=info, detail_level=detail_level)
451 512 displayfields = []
452 513 for title, key in self.pinfo_fields1:
453 514 field = info[key]
454 515 if field is not None:
455 516 displayfields.append((title, field.rstrip()))
456 517
457 518 # Source or docstring, depending on detail level and whether
458 519 # source found.
459 520 if detail_level > 0 and info['source'] is not None:
460 521 displayfields.append(("Source", self.format(py3compat.cast_bytes_py2(info['source']))))
461 522 elif info['docstring'] is not None:
462 523 displayfields.append(("Docstring", info["docstring"]))
463 524
464 525 # Constructor info for classes
465 526 if info['isclass']:
466 527 if info['init_definition'] or info['init_docstring']:
467 528 displayfields.append(("Constructor information", ""))
468 529 if info['init_definition'] is not None:
469 530 displayfields.append((" Definition",
470 531 info['init_definition'].rstrip()))
471 532 if info['init_docstring'] is not None:
472 533 displayfields.append((" Docstring",
473 534 indent(info['init_docstring'])))
474 535
475 536 # Info for objects:
476 537 else:
477 538 for title, key in self.pinfo_fields_obj:
478 539 field = info[key]
479 540 if field is not None:
480 541 displayfields.append((title, field.rstrip()))
481 542
482 543 # Finally send to printer/pager:
483 544 if displayfields:
484 545 page.page(self._format_fields(displayfields))
485 546
486 547 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
487 548 """Compute a dict with detailed information about an object.
488 549
489 550 Optional arguments:
490 551
491 552 - oname: name of the variable pointing to the object.
492 553
493 554 - formatter: special formatter for docstrings (see pdoc)
494 555
495 556 - info: a structure with some information fields which may have been
496 557 precomputed already.
497 558
498 559 - detail_level: if set to 1, more information is given.
499 560 """
500 561
501 562 obj_type = type(obj)
502 563
503 564 header = self.__head
504 565 if info is None:
505 566 ismagic = 0
506 567 isalias = 0
507 568 ospace = ''
508 569 else:
509 570 ismagic = info.ismagic
510 571 isalias = info.isalias
511 572 ospace = info.namespace
512 573
513 574 # Get docstring, special-casing aliases:
514 575 if isalias:
515 576 if not callable(obj):
516 577 try:
517 578 ds = "Alias to the system command:\n %s" % obj[1]
518 579 except:
519 580 ds = "Alias: " + str(obj)
520 581 else:
521 582 ds = "Alias to " + str(obj)
522 583 if obj.__doc__:
523 584 ds += "\nDocstring:\n" + obj.__doc__
524 585 else:
525 586 ds = getdoc(obj)
526 587 if ds is None:
527 588 ds = '<no docstring>'
528 589 if formatter is not None:
529 590 ds = formatter(ds)
530 591
531 592 # store output in a dict, we initialize it here and fill it as we go
532 593 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
533 594
534 595 string_max = 200 # max size of strings to show (snipped if longer)
535 596 shalf = int((string_max -5)/2)
536 597
537 598 if ismagic:
538 599 obj_type_name = 'Magic function'
539 600 elif isalias:
540 601 obj_type_name = 'System alias'
541 602 else:
542 603 obj_type_name = obj_type.__name__
543 604 out['type_name'] = obj_type_name
544 605
545 606 try:
546 607 bclass = obj.__class__
547 608 out['base_class'] = str(bclass)
548 609 except: pass
549 610
550 611 # String form, but snip if too long in ? form (full in ??)
551 612 if detail_level >= self.str_detail_level:
552 613 try:
553 614 ostr = str(obj)
554 615 str_head = 'string_form'
555 616 if not detail_level and len(ostr)>string_max:
556 617 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
557 618 ostr = ("\n" + " " * len(str_head.expandtabs())).\
558 619 join(q.strip() for q in ostr.split("\n"))
559 620 out[str_head] = ostr
560 621 except:
561 622 pass
562 623
563 624 if ospace:
564 625 out['namespace'] = ospace
565 626
566 627 # Length (for strings and lists)
567 628 try:
568 629 out['length'] = str(len(obj))
569 630 except: pass
570 631
571 632 # Filename where object was defined
572 633 binary_file = False
573 try:
574 try:
575 fname = inspect.getabsfile(obj)
576 except TypeError:
577 # For an instance, the file that matters is where its class was
578 # declared.
579 if hasattr(obj,'__class__'):
580 fname = inspect.getabsfile(obj.__class__)
581 if fname.endswith('<string>'):
582 fname = 'Dynamically generated function. No source code available.'
583 if fname.endswith(('.so', '.dll', '.pyd')):
584 binary_file = True
585 out['file'] = fname
586 except:
634 fname = find_file(obj)
635 if fname is None:
587 636 # if anything goes wrong, we don't want to show source, so it's as
588 637 # if the file was binary
589 638 binary_file = True
590
639 else:
640 if fname.endswith(('.so', '.dll', '.pyd')):
641 binary_file = True
642 elif fname.endswith('<string>'):
643 fname = 'Dynamically generated function. No source code available.'
644 out['file'] = fname
645
591 646 # reconstruct the function definition and print it:
592 647 defln = self._getdef(obj, oname)
593 648 if defln:
594 649 out['definition'] = self.format(defln)
595 650
596 651 # Docstrings only in detail 0 mode, since source contains them (we
597 652 # avoid repetitions). If source fails, we add them back, see below.
598 653 if ds and detail_level == 0:
599 654 out['docstring'] = ds
600 655
601 656 # Original source code for any callable
602 657 if detail_level:
603 658 # Flush the source cache because inspect can return out-of-date
604 659 # source
605 660 linecache.checkcache()
606 661 source = None
607 662 try:
608 663 try:
609 source = getsource(obj,binary_file)
664 source = getsource(obj, binary_file)
610 665 except TypeError:
611 if hasattr(obj,'__class__'):
612 source = getsource(obj.__class__,binary_file)
666 if hasattr(obj, '__class__'):
667 source = getsource(obj.__class__, binary_file)
613 668 if source is not None:
614 669 out['source'] = source.rstrip()
615 670 except Exception:
616 671 pass
617 672
618 673 if ds and source is None:
619 674 out['docstring'] = ds
620 675
621 676
622 677 # Constructor docstring for classes
623 678 if inspect.isclass(obj):
624 679 out['isclass'] = True
625 680 # reconstruct the function definition and print it:
626 681 try:
627 682 obj_init = obj.__init__
628 683 except AttributeError:
629 684 init_def = init_ds = None
630 685 else:
631 686 init_def = self._getdef(obj_init,oname)
632 687 init_ds = getdoc(obj_init)
633 688 # Skip Python's auto-generated docstrings
634 689 if init_ds and \
635 690 init_ds.startswith('x.__init__(...) initializes'):
636 691 init_ds = None
637 692
638 693 if init_def or init_ds:
639 694 if init_def:
640 695 out['init_definition'] = self.format(init_def)
641 696 if init_ds:
642 697 out['init_docstring'] = init_ds
643 698
644 699 # and class docstring for instances:
645 700 else:
646 701 # First, check whether the instance docstring is identical to the
647 702 # class one, and print it separately if they don't coincide. In
648 703 # most cases they will, but it's nice to print all the info for
649 704 # objects which use instance-customized docstrings.
650 705 if ds:
651 706 try:
652 707 cls = getattr(obj,'__class__')
653 708 except:
654 709 class_ds = None
655 710 else:
656 711 class_ds = getdoc(cls)
657 712 # Skip Python's auto-generated docstrings
658 713 if class_ds and \
659 714 (class_ds.startswith('function(code, globals[,') or \
660 715 class_ds.startswith('instancemethod(function, instance,') or \
661 716 class_ds.startswith('module(name[,') ):
662 717 class_ds = None
663 718 if class_ds and ds != class_ds:
664 719 out['class_docstring'] = class_ds
665 720
666 721 # Next, try to show constructor docstrings
667 722 try:
668 723 init_ds = getdoc(obj.__init__)
669 724 # Skip Python's auto-generated docstrings
670 725 if init_ds and \
671 726 init_ds.startswith('x.__init__(...) initializes'):
672 727 init_ds = None
673 728 except AttributeError:
674 729 init_ds = None
675 730 if init_ds:
676 731 out['init_docstring'] = init_ds
677 732
678 733 # Call form docstring for callable instances
679 734 if hasattr(obj, '__call__'):
680 735 call_def = self._getdef(obj.__call__, oname)
681 736 if call_def is not None:
682 737 out['call_def'] = self.format(call_def)
683 738 call_ds = getdoc(obj.__call__)
684 739 # Skip Python's auto-generated docstrings
685 740 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
686 741 call_ds = None
687 742 if call_ds:
688 743 out['call_docstring'] = call_ds
689 744
690 745 # Compute the object's argspec as a callable. The key is to decide
691 746 # whether to pull it from the object itself, from its __init__ or
692 747 # from its __call__ method.
693 748
694 749 if inspect.isclass(obj):
695 750 # Old-style classes need not have an __init__
696 751 callable_obj = getattr(obj, "__init__", None)
697 752 elif callable(obj):
698 753 callable_obj = obj
699 754 else:
700 755 callable_obj = None
701 756
702 757 if callable_obj:
703 758 try:
704 759 args, varargs, varkw, defaults = getargspec(callable_obj)
705 760 except (TypeError, AttributeError):
706 761 # For extensions/builtins we can't retrieve the argspec
707 762 pass
708 763 else:
709 764 out['argspec'] = dict(args=args, varargs=varargs,
710 765 varkw=varkw, defaults=defaults)
711 766
712 767 return object_info(**out)
713 768
714 769
715 770 def psearch(self,pattern,ns_table,ns_search=[],
716 771 ignore_case=False,show_all=False):
717 772 """Search namespaces with wildcards for objects.
718 773
719 774 Arguments:
720 775
721 776 - pattern: string containing shell-like wildcards to use in namespace
722 777 searches and optionally a type specification to narrow the search to
723 778 objects of that type.
724 779
725 780 - ns_table: dict of name->namespaces for search.
726 781
727 782 Optional arguments:
728 783
729 784 - ns_search: list of namespace names to include in search.
730 785
731 786 - ignore_case(False): make the search case-insensitive.
732 787
733 788 - show_all(False): show all names, including those starting with
734 789 underscores.
735 790 """
736 791 #print 'ps pattern:<%r>' % pattern # dbg
737 792
738 793 # defaults
739 794 type_pattern = 'all'
740 795 filter = ''
741 796
742 797 cmds = pattern.split()
743 798 len_cmds = len(cmds)
744 799 if len_cmds == 1:
745 800 # Only filter pattern given
746 801 filter = cmds[0]
747 802 elif len_cmds == 2:
748 803 # Both filter and type specified
749 804 filter,type_pattern = cmds
750 805 else:
751 806 raise ValueError('invalid argument string for psearch: <%s>' %
752 807 pattern)
753 808
754 809 # filter search namespaces
755 810 for name in ns_search:
756 811 if name not in ns_table:
757 812 raise ValueError('invalid namespace <%s>. Valid names: %s' %
758 813 (name,ns_table.keys()))
759 814
760 815 #print 'type_pattern:',type_pattern # dbg
761 816 search_result, namespaces_seen = set(), set()
762 817 for ns_name in ns_search:
763 818 ns = ns_table[ns_name]
764 819 # Normally, locals and globals are the same, so we just check one.
765 820 if id(ns) in namespaces_seen:
766 821 continue
767 822 namespaces_seen.add(id(ns))
768 823 tmp_res = list_namespace(ns, type_pattern, filter,
769 824 ignore_case=ignore_case, show_all=show_all)
770 825 search_result.update(tmp_res)
771 826
772 827 page.page('\n'.join(sorted(search_result)))
@@ -1,222 +1,243 b''
1 1 """Tests for the object inspection functionality.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2010-2011 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14 from __future__ import print_function
15 15
16 16 # Stdlib imports
17 import os
17 18
18 19 # Third-party imports
19 20 import nose.tools as nt
20 21
21 22 # Our own imports
22 23 from .. import oinspect
23 24 from IPython.core.magic import (Magics, magics_class, line_magic,
24 25 cell_magic, line_cell_magic,
25 26 register_line_magic, register_cell_magic,
26 27 register_line_cell_magic)
27 28 from IPython.utils import py3compat
28 29
29 30 #-----------------------------------------------------------------------------
30 31 # Globals and constants
31 32 #-----------------------------------------------------------------------------
32 33
33 34 inspector = oinspect.Inspector()
34 35 ip = get_ipython()
35 36
36 37 #-----------------------------------------------------------------------------
37 38 # Local utilities
38 39 #-----------------------------------------------------------------------------
39 40
41 # WARNING: since this test checks the line number where a function is
42 # defined, if any code is inserted above, the following line will need to be
43 # updated. Do NOT insert any whitespace between the next line and the function
44 # definition below.
45 THIS_LINE_NUMBER = 45 # Put here the actual number of this line
46 def test_find_source_lines():
47 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
48 THIS_LINE_NUMBER+1)
49
50
51 def test_find_file():
52 nt.assert_equal(oinspect.find_file(test_find_file),
53 os.path.abspath(__file__))
54
55
56 def test_find_file_magic():
57 run = ip.find_line_magic('run')
58 nt.assert_not_equal(oinspect.find_file(run), None)
59
60
40 61 # A few generic objects we can then inspect in the tests below
41 62
42 63 class Call(object):
43 64 """This is the class docstring."""
44 65
45 66 def __init__(self, x, y=1):
46 67 """This is the constructor docstring."""
47 68
48 69 def __call__(self, *a, **kw):
49 70 """This is the call docstring."""
50 71
51 72 def method(self, x, z=2):
52 73 """Some method's docstring"""
53 74
54 75
55 76 class OldStyle:
56 77 """An old-style class for testing."""
57 78 pass
58 79
59 80
60 81 def f(x, y=2, *a, **kw):
61 82 """A simple function."""
62 83
63 84
64 85 def g(y, z=3, *a, **kw):
65 86 pass # no docstring
66 87
67 88
68 89 @register_line_magic
69 90 def lmagic(line):
70 91 "A line magic"
71 92
72 93
73 94 @register_cell_magic
74 95 def cmagic(line, cell):
75 96 "A cell magic"
76 97
77 98
78 99 @register_line_cell_magic
79 100 def lcmagic(line, cell=None):
80 101 "A line/cell magic"
81 102
82 103
83 104 @magics_class
84 105 class SimpleMagics(Magics):
85 106 @line_magic
86 107 def Clmagic(self, cline):
87 108 "A class-based line magic"
88 109
89 110 @cell_magic
90 111 def Ccmagic(self, cline, ccell):
91 112 "A class-based cell magic"
92 113
93 114 @line_cell_magic
94 115 def Clcmagic(self, cline, ccell=None):
95 116 "A class-based line/cell magic"
96 117
97 118
98 119 def check_calltip(obj, name, call, docstring):
99 120 """Generic check pattern all calltip tests will use"""
100 121 info = inspector.info(obj, name)
101 122 call_line, ds = oinspect.call_tip(info)
102 123 nt.assert_equal(call_line, call)
103 124 nt.assert_equal(ds, docstring)
104 125
105 126 #-----------------------------------------------------------------------------
106 127 # Tests
107 128 #-----------------------------------------------------------------------------
108 129
109 130 def test_calltip_class():
110 131 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
111 132
112 133
113 134 def test_calltip_instance():
114 135 c = Call(1)
115 136 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
116 137
117 138
118 139 def test_calltip_method():
119 140 c = Call(1)
120 141 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
121 142
122 143
123 144 def test_calltip_function():
124 145 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
125 146
126 147
127 148 def test_calltip_function2():
128 149 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
129 150
130 151
131 152 def test_calltip_builtin():
132 153 check_calltip(sum, 'sum', None, sum.__doc__)
133 154
134 155
135 156 def test_calltip_line_magic():
136 157 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
137 158
138 159
139 160 def test_calltip_cell_magic():
140 161 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
141 162
142 163
143 164 def test_calltip_line_magic():
144 165 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
145 166 "A line/cell magic")
146 167
147 168
148 169 def test_class_magics():
149 170 cm = SimpleMagics(ip)
150 171 ip.register_magics(cm)
151 172 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
152 173 "A class-based line magic")
153 174 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
154 175 "A class-based cell magic")
155 176 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
156 177 "A class-based line/cell magic")
157 178
158 179
159 180 def test_info():
160 181 "Check that Inspector.info fills out various fields as expected."
161 182 i = inspector.info(Call, oname='Call')
162 183 nt.assert_equal(i['type_name'], 'type')
163 184 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
164 185 nt.assert_equal(i['base_class'], expted_class)
165 186 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
166 187 fname = __file__
167 188 if fname.endswith(".pyc"):
168 189 fname = fname[:-1]
169 190 # case-insensitive comparison needed on some filesystems
170 191 # e.g. Windows:
171 192 nt.assert_equal(i['file'].lower(), fname.lower())
172 193 nt.assert_equal(i['definition'], 'Call(self, *a, **kw)\n')
173 194 nt.assert_equal(i['docstring'], Call.__doc__)
174 195 nt.assert_equal(i['source'], None)
175 196 nt.assert_true(i['isclass'])
176 197 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
177 198 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
178 199
179 200 i = inspector.info(Call, detail_level=1)
180 201 nt.assert_not_equal(i['source'], None)
181 202 nt.assert_equal(i['docstring'], None)
182 203
183 204 c = Call(1)
184 205 c.__doc__ = "Modified instance docstring"
185 206 i = inspector.info(c)
186 207 nt.assert_equal(i['type_name'], 'Call')
187 208 nt.assert_equal(i['docstring'], "Modified instance docstring")
188 209 nt.assert_equal(i['class_docstring'], Call.__doc__)
189 210 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
190 211 nt.assert_equal(i['call_docstring'], c.__call__.__doc__)
191 212
192 213 # Test old-style classes, which for example may not have an __init__ method.
193 214 if not py3compat.PY3:
194 215 i = inspector.info(OldStyle)
195 216 nt.assert_equal(i['type_name'], 'classobj')
196 217
197 218 i = inspector.info(OldStyle())
198 219 nt.assert_equal(i['type_name'], 'instance')
199 220 nt.assert_equal(i['docstring'], OldStyle.__doc__)
200 221
201 222 def test_getdoc():
202 223 class A(object):
203 224 """standard docstring"""
204 225 pass
205 226
206 227 class B(object):
207 228 """standard docstring"""
208 229 def getdoc(self):
209 230 return "custom docstring"
210 231
211 232 class C(object):
212 233 """standard docstring"""
213 234 def getdoc(self):
214 235 return None
215 236
216 237 a = A()
217 238 b = B()
218 239 c = C()
219 240
220 241 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
221 242 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
222 243 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
General Comments 0
You need to be logged in to leave comments. Login now