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