Package epydoc :: Module docintrospecter
[hide private]
[frames] | no frames]

Source Code for Module epydoc.docintrospecter

  1  # epydoc -- Introspection 
  2  # 
  3  # Copyright (C) 2005 Edward Loper 
  4  # Author: Edward Loper <edloper@loper.org> 
  5  # URL: <http://epydoc.sf.net> 
  6  # 
  7  # $Id: docintrospecter.py 1168 2006-04-05 16:52:56Z edloper $ 
  8   
  9  """ 
 10  Extract API documentation about python objects by directly introspecting 
 11  their values. 
 12   
 13  L{DocIntrospecter} is a processing class that examines Python objects via 
 14  introspection, and uses the information it finds to create L{APIDoc} 
 15  objects containing the API documentation for those objects. 
 16   
 17  C{DocIntrospecter} can be subclassed to extend the set of object types 
 18  that it supports. 
 19  """ 
 20  __docformat__ = 'epytext en' 
 21   
 22  ###################################################################### 
 23  ## Imports 
 24  ###################################################################### 
 25   
 26  import inspect, re, sys, os.path, imp 
 27  # API documentation encoding: 
 28  from epydoc.apidoc import * 
 29  # Type comparisons: 
 30  from types import * 
 31  # Error reporting: 
 32  from epydoc import log 
 33  # Helper functions: 
 34  from epydoc.util import * 
 35  # For extracting encoding for docstrings: 
 36  import epydoc.docparser 
 37  # Builtin values 
 38  import __builtin__ 
 39  # Backwards compatibility 
 40  from epydoc.compat import *  
 41   
 42  ###################################################################### 
 43  ## Caches 
 44  ###################################################################### 
 45   
 46  _valuedoc_cache = {} 
 47  """A cache containing the API documentation for values that we've 
 48  already seen.  This cache is implemented as a dictionary that maps a 
 49  value's pyid to its L{ValueDoc}. 
 50   
 51  Note that if we encounter a value but decide not to introspect it 
 52  (because it's imported from another module), then C{_valuedoc_cache} 
 53  will contain an entry for the value, but the value will not be listed 
 54  in L{_introspected_values}.""" 
 55   
 56  _introspected_values = {} 
 57  """A record which values we've introspected, encoded as a dictionary from 
 58  pyid to C{bool}.""" 
 59   
 60  ###################################################################### 
 61  ## Introspection 
 62  ###################################################################### 
 63   
 64  # [xx] old: 
 65  """ 
 66  An API documentation extractor based on introspecting python values. 
 67  C{DocIntrospecter} examines Python objects via introspection, and uses 
 68  the information it finds to create L{APIDoc} objects containing 
 69  the API documentation for those objects.  The main interface to 
 70  the C{DocIntrospecter} class is the L{introspect} method, which takes a 
 71  Python value, and returns an L{APIDoc} that describes it. 
 72   
 73  Currently, C{DocIntrospecter} can extract documentation information 
 74  from the following object types: 
 75   
 76    - modules 
 77    - classes 
 78    - functions 
 79    - methods 
 80    - class methods 
 81    - static methods 
 82    - builtin routines 
 83    - properties 
 84   
 85  Subclassing 
 86  =========== 
 87  C{DocIntrospecter} can be subclassed, to extend the set of object 
 88  types that it supports.  C{DocIntrospecter} can be extended in 
 89  several different ways: 
 90   
 91    - A subclass can override one of the existing introspection methods 
 92      to modify the behavior for a currently supported object type. 
 93   
 94    - A subclass can add support for a new type by adding a new 
 95      introspection method; and extending L{introspecter_method()} to 
 96      return that method for values of the new type. 
 97  """ 
 98   
99 -def introspect_docs(value=None, name=None, filename=None, context=None, 100 is_script=False):
101 """ 102 Generate the API documentation for a specified object by 103 introspecting Python values, and return it as a L{ValueDoc}. The 104 object to generate documentation for may be specified using 105 the C{value} parameter, the C{filename} parameter, I{or} the 106 C{name} parameter. (It is an error to specify more than one 107 of these three parameters, or to not specify any of them.) 108 109 @param value: The python object that should be documented. 110 @param filename: The name of the file that contains the python 111 source code for a package, module, or script. If 112 C{filename} is specified, then C{introspect} will return a 113 C{ModuleDoc} describing its contents. 114 @param name: The fully-qualified python dotted name of any 115 value (including packages, modules, classes, and 116 functions). C{DocParser} will automatically figure out 117 which module(s) it needs to import in order to find the 118 documentation for the specified object. 119 @param context: The API documentation for the class of module 120 that contains C{value} (if available). 121 """ 122 if value is None and name is not None and filename is None: 123 value = get_value_from_name(DottedName(name)) 124 elif value is None and name is None and filename is not None: 125 if is_script: 126 value = get_value_from_scriptname(filename) 127 else: 128 value = get_value_from_filename(filename, context) 129 elif name is None and filename is None: 130 # it's ok if value is None -- that's a value, after all. 131 pass 132 else: 133 raise ValueError("Expected exactly one of the following " 134 "arguments: value, name, filename") 135 136 pyid = id(value) 137 138 # If we've already introspected this value, then simply return 139 # its ValueDoc from our cache. 140 if pyid in _introspected_values: 141 return _valuedoc_cache[pyid] 142 143 # Create an initial value doc for this value & add it to the cache. 144 val_doc = _get_valuedoc(value) 145 146 # Introspect the value. 147 _introspected_values[pyid] = True 148 introspect_func = _get_introspecter(value) 149 introspect_func(value, val_doc) 150 151 # Set canonical name, if it was given 152 if val_doc.canonical_name == UNKNOWN and name is not None: 153 val_doc.canonical_name = DottedName(name) 154 155 # If we were given a filename, but didn't manage to get a 156 # canonical name, then the module defined by the given file 157 # must be shadowed by a variable in its parent package(s). 158 # E.g., this happens with `curses.wrapper`. Add a "'" to 159 # the end of the name to distinguish it from the variable. 160 if is_script and filename is not None: 161 val_doc.canonical_name = DottedName(munge_script_name(str(filename))) 162 163 if val_doc.canonical_name == UNKNOWN and filename is not None: 164 shadowed_name = DottedName(value.__name__) 165 log.warning("Module %s is shadowed by a variable with " 166 "the same name." % shadowed_name) 167 val_doc.canonical_name = DottedName(str(shadowed_name)+"'") 168 169 return val_doc
170
171 -def _get_valuedoc(value):
172 """ 173 If a C{ValueDoc} for the given value exists in the valuedoc 174 cache, then return it; otherwise, create a new C{ValueDoc}, 175 add it to the cache, and return it. When possible, the new 176 C{ValueDoc}'s C{pyval}, C{repr}, and C{canonical_name} 177 attributes will be set appropriately. 178 """ 179 pyid = id(value) 180 val_doc = _valuedoc_cache.get(pyid) 181 if val_doc is None: 182 try: canonical_name = get_canonical_name(value) 183 except DottedName.InvalidDottedName: canonical_name = UNKNOWN 184 val_doc = ValueDoc(pyval=value, canonical_name = canonical_name, 185 docs_extracted_by='introspecter') 186 _valuedoc_cache[pyid] = val_doc 187 188 # If it's a module, then do some preliminary introspection. 189 # Otherwise, check what the containing module is (used e.g. 190 # to decide what markup language should be used for docstrings) 191 if inspect.ismodule(value): 192 introspect_module(value, val_doc, preliminary=True) 193 val_doc.defining_module = val_doc 194 else: 195 module_name = str(get_containing_module(value)) 196 module = sys.modules.get(module_name) 197 if module is not None and inspect.ismodule(module): 198 val_doc.defining_module = _get_valuedoc(module) 199 200 return val_doc
201 202 #//////////////////////////////////////////////////////////// 203 # Module Introspection 204 #//////////////////////////////////////////////////////////// 205 206 #: A list of module variables that should not be included in a 207 #: module's API documentation. 208 UNDOCUMENTED_MODULE_VARS = ( 209 '__builtins__', '__doc__', '__all__', '__file__', '__path__', 210 '__name__', '__extra_epydoc_fields__', '__docformat__') 211
212 -def introspect_module(module, module_doc, preliminary=False):
213 """ 214 Add API documentation information about the module C{module} 215 to C{module_doc}. 216 """ 217 module_doc.specialize_to(ModuleDoc) 218 219 # Record the module's docformat 220 if hasattr(module, '__docformat__'): 221 module_doc.docformat = unicode(module.__docformat__) 222 223 # Record the module's filename 224 if hasattr(module, '__file__'): 225 try: module_doc.filename = unicode(module.__file__) 226 except KeyboardInterrupt: raise 227 except: pass 228 229 # If this is just a preliminary introspection, then don't do 230 # anything else. (Typically this is true if this module was 231 # imported, but is not included in the set of modules we're 232 # documenting.) 233 if preliminary: return 234 235 # Record the module's docstring 236 if hasattr(module, '__doc__'): 237 module_doc.docstring = get_docstring(module) 238 239 # If the module has a __path__, then it's (probably) a 240 # package; so set is_package=True and record its __path__. 241 if hasattr(module, '__path__'): 242 module_doc.is_package = True 243 try: module_doc.path = [unicode(p) for p in module.__path__] 244 except KeyboardInterrupt: raise 245 except: pass 246 else: 247 module_doc.is_package = False 248 249 # Make sure we have a name for the package. 250 dotted_name = module_doc.canonical_name 251 if dotted_name is UNKNOWN: 252 dotted_name = DottedName(module.__name__) 253 254 # Record the module's parent package, if it has one. 255 if len(dotted_name) > 1: 256 package_name = str(dotted_name.container()) 257 package = sys.modules.get(package_name) 258 if package is not None: 259 module_doc.package = introspect_docs(package) 260 else: 261 module_doc.package = None 262 263 # Initialize the submodules property 264 module_doc.submodules = [] 265 266 # Add the module to its parent package's submodules list. 267 if module_doc.package not in (None, UNKNOWN): 268 module_doc.package.submodules.append(module_doc) 269 270 # Record the module's variables. 271 module_doc.variables = {} 272 for child_name in dir(module): 273 if child_name in UNDOCUMENTED_MODULE_VARS: continue 274 child = getattr(module, child_name) 275 276 # Create a VariableDoc for the child, and introspect its 277 # value if it's defined in this module. 278 container = get_containing_module(child) 279 if container != None and container == module_doc.canonical_name: 280 # Local variable. 281 child_val_doc = introspect_docs(child, context=module_doc) 282 child_var_doc = VariableDoc(name=child_name, 283 value=child_val_doc, 284 is_imported=False, 285 container=module_doc, 286 docs_extracted_by='introspecter') 287 elif container is None or module_doc.canonical_name is UNKNOWN: 288 # Possibly imported variable. 289 child_val_doc = introspect_docs(child, context=module_doc) 290 child_var_doc = VariableDoc(name=child_name, 291 value=child_val_doc, 292 container=module_doc, 293 docs_extracted_by='introspecter') 294 else: 295 # Imported variable. 296 child_val_doc = _get_valuedoc(child) 297 child_var_doc = VariableDoc(name=child_name, 298 value=child_val_doc, 299 is_imported=True, 300 container=module_doc, 301 docs_extracted_by='introspecter') 302 303 module_doc.variables[child_name] = child_var_doc 304 305 # Record the module's __all__ attribute (public names). 306 if hasattr(module, '__all__'): 307 try: 308 public_names = set([str(name) for name in module.__all__]) 309 for name, var_doc in module_doc.variables.items(): 310 if name in public_names: 311 var_doc.is_public = True 312 if not isinstance(var_doc, ModuleDoc): 313 var_doc.is_imported = False 314 else: 315 var_doc.is_public = False 316 except KeyboardInterrupt: raise 317 except: pass 318 319 return module_doc
320 321 #//////////////////////////////////////////////////////////// 322 # Class Introspection 323 #//////////////////////////////////////////////////////////// 324 325 #: A list of class variables that should not be included in a 326 #: class's API documentation. 327 UNDOCUMENTED_CLASS_VARS = ( 328 '__doc__', '__module__', '__dict__', '__weakref__') 329
330 -def introspect_class(cls, class_doc):
331 """ 332 Add API documentation information about the class C{cls} 333 to C{class_doc}. 334 """ 335 class_doc.specialize_to(ClassDoc) 336 337 # Record the class's docstring. 338 class_doc.docstring = get_docstring(cls) 339 340 # Record the class's __all__ attribute (public names). 341 if hasattr(cls, '__all__'): 342 try: 343 public_names = [str(name) for name in cls.__all__] 344 class_doc.public_names = public_names 345 except KeyboardInterrupt: raise 346 except: pass 347 348 # Start a list of subclasses. 349 class_doc.subclasses = [] 350 351 # Sometimes users will define a __metaclass__ that copies all 352 # class attributes from bases directly into the derived class's 353 # __dict__ when the class is created. (This saves the lookup time 354 # needed to search the base tree for an attribute.) But for the 355 # docs, we only want to list these copied attributes in the 356 # parent. So only add an attribute if it is not identical to an 357 # attribute of a base class. (Unfortunately, this can sometimes 358 # cause an attribute to look like it was inherited, even though it 359 # wasn't, if it happens to have the exact same value as the 360 # corresponding base's attribute.) An example of a case where 361 # this helps is PyQt -- subclasses of QWidget get about 300 362 # methods injected into them. 363 base_children = {} 364 365 # Record the class's base classes; and add the class to its 366 # base class's subclass lists. 367 if hasattr(cls, '__bases__'): 368 class_doc.bases = [] 369 for base in cls.__bases__: 370 basedoc = introspect_docs(base) 371 class_doc.bases.append(basedoc) 372 basedoc.subclasses.append(class_doc) 373 374 bases = list(cls.__bases__) 375 bases.reverse() 376 for base in bases: 377 if hasattr(base, '__dict__'): 378 base_children.update(base.__dict__) 379 380 # Record the class's local variables. 381 class_doc.variables = {} 382 private_prefix = '_%s__' % cls.__name__ 383 if hasattr(cls, '__dict__'): 384 for child_name, child in cls.__dict__.items(): 385 if (child_name in base_children 386 and base_children[child_name] == child): 387 continue 388 389 if child_name.startswith(private_prefix): 390 child_name = child_name[len(private_prefix)-2:] 391 if child_name in UNDOCUMENTED_CLASS_VARS: continue 392 #try: child = getattr(cls, child_name) 393 #except: continue 394 val_doc = introspect_docs(child, context=class_doc) 395 var_doc = VariableDoc(name=child_name, value=val_doc, 396 container=class_doc, 397 docs_extracted_by='introspecter') 398 class_doc.variables[child_name] = var_doc 399 400 return class_doc
401 402 #//////////////////////////////////////////////////////////// 403 # Routine Introspection 404 #//////////////////////////////////////////////////////////// 405
406 -def introspect_routine(routine, routine_doc):
407 """Add API documentation information about the function 408 C{routine} to C{routine_doc} (specializing it to C{Routine_doc}).""" 409 routine_doc.specialize_to(RoutineDoc) 410 411 # Extract the underying function 412 if isinstance(routine, MethodType): 413 func = routine.im_func 414 elif isinstance(routine, staticmethod): 415 func = routine.__get__(0) 416 elif isinstance(routine, classmethod): 417 func = routine.__get__(0).im_func 418 else: 419 func = routine 420 421 # Record the function's docstring. 422 routine_doc.docstring = get_docstring(func) 423 424 # Record the function's signature. 425 if isinstance(func, FunctionType): 426 (args, vararg, kwarg, defaults) = inspect.getargspec(func) 427 428 # Add the arguments. 429 routine_doc.posargs = args 430 routine_doc.vararg = vararg 431 routine_doc.kwarg = kwarg 432 433 # Set default values for positional arguments. 434 routine_doc.posarg_defaults = [None]*len(args) 435 if defaults is not None: 436 offset = len(args)-len(defaults) 437 for i in range(len(defaults)): 438 default_val = introspect_docs(defaults[i]) 439 routine_doc.posarg_defaults[i+offset] = default_val 440 441 # If it's a bound method, then strip off the first argument. 442 if isinstance(routine, MethodType) and routine.im_self is not None: 443 routine_doc.posargs = routine_doc.posargs[1:] 444 routine_doc.posarg_defaults = routine_doc.posarg_defaults[1:] 445 446 # Set the routine's line number. 447 if hasattr(func, 'func_code'): 448 routine_doc.lineno = func.func_code.co_firstlineno 449 450 else: 451 # [XX] I should probably use UNKNOWN here?? 452 routine_doc.posargs = ['...'] 453 routine_doc.posarg_defaults = [None] 454 routine_doc.kwarg = None 455 routine_doc.vararg = None 456 457 # Change type, if appropriate. 458 if isinstance(routine, staticmethod): 459 routine_doc.specialize_to(StaticMethodDoc) 460 if isinstance(routine, classmethod): 461 routine_doc.specialize_to(ClassMethodDoc) 462 463 return routine_doc
464 465 #//////////////////////////////////////////////////////////// 466 # Property Introspection 467 #//////////////////////////////////////////////////////////// 468
469 -def introspect_property(prop, prop_doc):
470 """Add API documentation information about the property 471 C{prop} to C{prop_doc} (specializing it to C{PropertyDoc}).""" 472 prop_doc.specialize_to(PropertyDoc) 473 474 # Record the property's docstring. 475 prop_doc.docstring = get_docstring(prop) 476 477 # Record the property's access functions. 478 prop_doc.fget = introspect_docs(prop.fget) 479 prop_doc.fset = introspect_docs(prop.fset) 480 prop_doc.fdel = introspect_docs(prop.fdel) 481 482 return prop_doc
483 484 #//////////////////////////////////////////////////////////// 485 # Generic Value Introspection 486 #//////////////////////////////////////////////////////////// 487
488 -def introspect_other(val, val_doc):
489 """Specialize val_doc to a C{GenericValueDoc} and return it.""" 490 val_doc.specialize_to(GenericValueDoc) 491 return val_doc
492 493 #//////////////////////////////////////////////////////////// 494 # Helper functions 495 #//////////////////////////////////////////////////////////// 496
497 -def get_docstring(value):
498 """ 499 Return the docstring for the given value; or C{None} if it 500 does not have a docstring. 501 @rtype: C{unicode} 502 """ 503 docstring = getattr(value, '__doc__', None) 504 if docstring is None: 505 return None 506 elif isinstance(docstring, unicode): 507 return docstring 508 elif isinstance(docstring, str): 509 try: return unicode(docstring, 'ascii') 510 except UnicodeDecodeError: 511 module_name = get_containing_module(value) 512 if module_name is not None: 513 try: 514 module = get_value_from_name(module_name) 515 filename = py_src_filename(module.__file__) 516 encoding = epydoc.docparser.get_module_encoding(filename) 517 return unicode(docstring, encoding) 518 except KeyboardInterrupt: raise 519 except Exception: pass 520 if hasattr(value, '__name__'): name = value.__name__ 521 else: name = `value` 522 log.warning("%s's docstring is not a unicode string, but it " 523 "contains non-ascii data -- treating it as " 524 "latin-1." % name) 525 return unicode(docstring, 'latin-1') 526 return None 527 elif value is BuiltinMethodType: 528 # Don't issue a warning for this special case. 529 return None 530 else: 531 if hasattr(value, '__name__'): name = value.__name__ 532 else: name = `value` 533 log.warning("%s's docstring is not a string -- ignoring it." % 534 name) 535 return None
536
537 -def get_canonical_name(value):
538 """ 539 @return: the canonical name for C{value}, or C{UNKNOWN} if no 540 canonical name can be found. Currently, C{get_canonical_name} 541 can find canonical names for: modules; functions; non-nested 542 classes; methods of non-nested classes; and some class methods 543 of non-nested classes. 544 545 @rtype: L{DottedName} or C{None} 546 """ 547 if not hasattr(value, '__name__'): return UNKNOWN 548 549 # Get the name via introspection. 550 if isinstance(value, ModuleType): 551 dotted_name = DottedName(value.__name__) 552 553 elif isinstance(value, (ClassType, TypeType)): 554 if value.__module__ == '__builtin__': 555 dotted_name = DottedName(value.__name__) 556 else: 557 dotted_name = DottedName(value.__module__, value.__name__) 558 559 elif (inspect.ismethod(value) and value.im_self is not None and 560 value.im_class is ClassType and 561 not value.__name__.startswith('<')): # class method. 562 class_name = get_canonical_name(value.im_self) 563 if class_name is None: return UNKNOWN 564 dotted_name = DottedName(class_name, value.__name__) 565 elif (inspect.ismethod(value) and 566 not value.__name__.startswith('<')): 567 class_name = get_canonical_name(value.im_class) 568 if class_name is None: return UNKNOWN 569 dotted_name = DottedName(class_name, value.__name__) 570 elif (isinstance(value, FunctionType) and 571 not value.__name__.startswith('<')): 572 module_name = _find_function_module(value) 573 if module_name is None: return UNKNOWN 574 dotted_name = DottedName(module_name, value.__name__) 575 else: 576 return UNKNOWN 577 578 return verify_name(value, dotted_name)
579
580 -def verify_name(value, dotted_name):
581 """ 582 Verify the name. E.g., if it's a nested class, then we won't be 583 able to find it with the name we constructed. 584 """ 585 if dotted_name == UNKNOWN: return UNKNOWN 586 if len(dotted_name) == 1 and hasattr(__builtin__, dotted_name[0]): 587 return dotted_name 588 named_value = sys.modules.get(dotted_name[0]) 589 if named_value is None: return UNKNOWN 590 for identifier in dotted_name[1:]: 591 try: named_value = getattr(named_value, identifier) 592 except: return UNKNOWN 593 if value is named_value: 594 return dotted_name 595 else: 596 return UNKNOWN
597 598 # [xx] not used:
599 -def value_repr(value):
600 try: 601 s = '%r' % value 602 if isinstance(s, str): 603 s = decode_with_backslashreplace(s) 604 return s 605 except: 606 return UNKNOWN
607
608 -def get_containing_module(value):
609 """ 610 Return the name of the module containing the given value, or 611 C{None} if the module name can't be determined. 612 @rtype: L{DottedName} 613 """ 614 if inspect.ismodule(value): 615 return DottedName(value.__name__) 616 elif inspect.isclass(value): 617 return DottedName(value.__module__) 618 elif (inspect.ismethod(value) and value.im_self is not None and 619 value.im_class is ClassType): # class method. 620 return DottedName(value.im_self.__module__) 621 elif inspect.ismethod(value): 622 return DottedName(value.im_class.__module__) 623 elif inspect.isroutine(value): 624 module = _find_function_module(value) 625 if module is None: return None 626 return DottedName(module) 627 else: 628 return None
629
630 -def _find_function_module(func):
631 """ 632 @return: The module that defines the given function. 633 @rtype: C{module} 634 @param func: The function whose module should be found. 635 @type func: C{function} 636 """ 637 if hasattr(func, '__module__'): 638 return func.__module__ 639 try: 640 module = inspect.getmodule(func) 641 if module: return module.__name__ 642 except KeyboardInterrupt: raise 643 except: pass 644 645 # This fallback shouldn't usually be needed. But it is needed in 646 # a couple special cases (including using epydoc to document 647 # itself). In particular, if a module gets loaded twice, using 648 # two different names for the same file, then this helps. 649 for module in sys.modules.values(): 650 if (hasattr(module, '__dict__') and 651 hasattr(func, 'func_globals') and 652 func.func_globals is module.__dict__): 653 return module.__name__ 654 return None
655 656 #//////////////////////////////////////////////////////////// 657 # Introspection Dispatch Table 658 #//////////////////////////////////////////////////////////// 659 660 _introspecter_registry = []
661 -def register_introspecter(applicability_test, introspecter, priority=10):
662 """ 663 Register an introspecter function. Introspecter functions take 664 two arguments, a python value and a C{ValueDoc} object, and should 665 add information about the given value to the the C{ValueDoc}. 666 Usually, the first line of an inspecter function will specialize 667 it to a sublass of C{ValueDoc}, using L{ValueDoc.specialize_to()}: 668 669 >>> def typical_introspecter(value, value_doc): 670 ... value_doc.specialize_to(SomeSubclassOfValueDoc) 671 ... <add info to value_doc> 672 673 @param priority: The priority of this introspecter, which determines 674 the order in which introspecters are tried -- introspecters with lower 675 numbers are tried first. The standard introspecters have priorities 676 ranging from 20 to 30. The default priority (10) will place new 677 introspecters before standard introspecters. 678 """ 679 _introspecter_registry.append( (priority, applicability_test, 680 introspecter) ) 681 _introspecter_registry.sort()
682
683 -def _get_introspecter(value):
684 for (priority, applicability_test, introspecter) in _introspecter_registry: 685 if applicability_test(value): 686 return introspecter 687 else: 688 return introspect_other
689 690 # Register the standard introspecter functions.
691 -def is_classmethod(v): return isinstance(v, classmethod)
692 -def is_staticmethod(v): return isinstance(v, staticmethod)
693 -def is_property(v): return isinstance(v, property)
694 register_introspecter(inspect.ismodule, introspect_module, priority=20) 695 register_introspecter(inspect.isclass, introspect_class, priority=24) 696 register_introspecter(inspect.isroutine, introspect_routine, priority=28) 697 register_introspecter(is_property, introspect_property, priority=30) 698 699 #//////////////////////////////////////////////////////////// 700 # Import support 701 #//////////////////////////////////////////////////////////// 702
703 -def get_value_from_filename(filename, context=None):
704 # Normalize the filename. 705 filename = os.path.normpath(os.path.abspath(filename)) 706 707 # Divide the filename into a base directory and a name. (For 708 # packages, use the package's parent directory as the base, and 709 # the directory name as its name). 710 basedir = os.path.split(filename)[0] 711 name = os.path.splitext(os.path.split(filename)[1])[0] 712 if name == '__init__': 713 basedir, name = os.path.split(basedir) 714 name = DottedName(name) 715 716 # If the context wasn't provided, then check if the file is in a 717 # package directory. If so, then update basedir & name to contain 718 # the topmost package's directory and the fully qualified name for 719 # this file. (This update assume the default value of __path__ 720 # for the parent packages; if the parent packages override their 721 # __path__s, then this can cause us not to find the value.) 722 if context is None: 723 while is_package_dir(basedir): 724 basedir, pkg_name = os.path.split(basedir) 725 name = DottedName(pkg_name, name) 726 727 # If a parent package was specified, then find the directory of 728 # the topmost package, and the fully qualified name for this file. 729 if context is not None: 730 # Combine the name. 731 name = DottedName(context.canonical_name, name) 732 # Find the directory of the base package. 733 while context not in (None, UNKNOWN): 734 pkg_dir = os.path.split(context.filename)[0] 735 basedir = os.path.split(pkg_dir)[0] 736 context = context.package 737 738 # Import the module. (basedir is the directory of the module's 739 # topmost package, or its own directory if it's not in a package; 740 # and name is the fully qualified dotted name for the module.) 741 old_sys_path = sys.path[:] 742 try: 743 sys.path.insert(0, basedir) 744 # This will make sure that we get the module itself, even 745 # if it is shadowed by a variable. (E.g., curses.wrapper): 746 _import(str(name)) 747 if str(name) in sys.modules: 748 return sys.modules[str(name)] 749 else: 750 # Use this as a fallback -- it *shouldn't* ever be needed. 751 return get_value_from_name(name) 752 finally: 753 sys.path = old_sys_path
754
755 -def get_value_from_scriptname(filename):
758
759 -def get_value_from_name(name, globs=None):
760 """ 761 Given a name, return the corresponding value. 762 763 @param globals: A namespace to check for the value, if there is no 764 module containing the named value. Defaults to __builtin__. 765 """ 766 name = DottedName(name) 767 768 # Import the topmost module/package. If we fail, then check if 769 # the requested name refers to a builtin. 770 try: 771 module = _import(name[0]) 772 except ImportError, e: 773 if globs is None: globs = __builtin__.__dict__ 774 if name[0] in globs: 775 try: return _lookup(globs[name[0]], name[1:]) 776 except: raise e 777 else: 778 raise 779 780 # Find the requested value in the module/package or its submodules. 781 for i in range(1, len(name)): 782 try: return _lookup(module, name[i:]) 783 except ImportError: pass 784 module = _import('.'.join(name[:i+1])) 785 module = _lookup(module, name[1:i+1]) 786 return module
787
788 -def _lookup(module, name):
789 val = module 790 for i, identifier in enumerate(name): 791 try: val = getattr(val, identifier) 792 except AttributeError: 793 exc_msg = ('no variable named %s in %s' % 794 (identifier, '.'.join(name[:1+i]))) 795 raise ImportError(exc_msg) 796 return val
797
798 -def _import(name, filename=None):
799 """ 800 Run the given callable in a 'sandboxed' environment. 801 Currently, this includes saving and restoring the contents of 802 sys and __builtins__; and supressing stdin, stdout, and stderr. 803 """ 804 # Note that we just do a shallow copy of sys. In particular, 805 # any changes made to sys.modules will be kept. But we do 806 # explicitly store sys.path. 807 old_sys = sys.__dict__.copy() 808 old_sys_path = sys.path[:] 809 old_builtins = __builtin__.__dict__.copy() 810 811 # Add the current directory to sys.path, in case they're trying to 812 # import a module by name that resides in the current directory. 813 sys.path.insert(0, '') 814 815 # Supress input and output. (These get restored when we restore 816 # sys to old_sys). 817 sys.stdin = sys.stdout = sys.stderr = _dev_null 818 sys.__stdin__ = sys.__stdout__ = sys.__stderr__ = _dev_null 819 820 # Remove any command-line arguments 821 sys.argv = ['(imported)'] 822 823 try: 824 try: 825 if filename is None: 826 return __import__(name) 827 else: 828 # For importing scripts: 829 return imp.load_source(name, filename) 830 except KeyboardInterrupt: raise 831 except: 832 exc_typ, exc_val, exc_tb = sys.exc_info() 833 if exc_val is None: 834 estr = '%s' % (exc_typ,) 835 else: 836 estr = '%s: %s' % (exc_typ.__name__, exc_val) 837 if exc_tb.tb_next is not None: 838 estr += ' (line %d)' % (exc_tb.tb_next.tb_lineno,) 839 raise ImportError(estr) 840 finally: 841 # Restore the important values that we saved. 842 __builtin__.__dict__.clear() 843 __builtin__.__dict__.update(old_builtins) 844 sys.__dict__.clear() 845 sys.__dict__.update(old_sys) 846 sys.path = old_sys_path
847
848 -def introspect_docstring_lineno(api_doc):
849 """ 850 Try to determine the line number on which the given item's 851 docstring begins. Return the line number, or C{None} if the line 852 number can't be determined. The line number of the first line in 853 the file is 1. 854 """ 855 if api_doc.docstring_lineno is not UNKNOWN: 856 return api_doc.docstring_lineno 857 if isinstance(api_doc, ValueDoc) and api_doc.pyval != UNKNOWN: 858 try: 859 lines, lineno = inspect.findsource(api_doc.pyval) 860 if not isinstance(api_doc, ModuleDoc): lineno += 1 861 for lineno in range(lineno, len(lines)): 862 if lines[lineno].split('#', 1)[0].strip(): 863 api_doc.docstring_lineno = lineno + 1 864 return lineno + 1 865 except IOError: pass 866 except TypeError: pass 867 return None
868
869 -class _DevNull:
870 """ 871 A "file-like" object that discards anything that is written and 872 always reports end-of-file when read. C{_DevNull} is used by 873 L{_import()} to discard output when importing modules; and to 874 ensure that stdin appears closed. 875 """
876 - def __init__(self):
877 self.closed = 1 878 self.mode = 'r+' 879 self.softspace = 0 880 self.name='</dev/null>'
881 - def close(self): pass
882 - def flush(self): pass
883 - def read(self, size=0): return ''
884 - def readline(self, size=0): return ''
885 - def readlines(self, sizehint=0): return []
886 - def seek(self, offset, whence=0): pass
887 - def tell(self): return 0L
888 - def truncate(self, size=0): pass
889 - def write(self, str): pass
890 - def writelines(self, sequence): pass
891 xreadlines = readlines
892 _dev_null = _DevNull() 893 894 895 896 897 898 899 # [xx] 900 0 # hm.. otherwise the following gets treated as a docstring! ouch! 901 """ 902 ###################################################################### 903 ## Zope Extension... 904 ###################################################################### 905 class ZopeIntrospecter(Introspecter): 906 VALUEDOC_CLASSES = Introspecter.VALUEDOC_CLASSES.copy() 907 VALUEDOC_CLASSES.update({ 908 'module': ZopeModuleDoc, 909 'class': ZopeClassDoc, 910 'interface': ZopeInterfaceDoc, 911 'attribute': ZopeAttributeDoc, 912 }) 913 914 def add_module_child(self, child, child_name, module_doc): 915 if isinstance(child, zope.interfaces.Interface): 916 module_doc.add_zope_interface(child_name) 917 else: 918 Introspecter.add_module_child(self, child, child_name, module_doc) 919 920 def add_class_child(self, child, child_name, class_doc): 921 if isinstance(child, zope.interfaces.Interface): 922 class_doc.add_zope_interface(child_name) 923 else: 924 Introspecter.add_class_child(self, child, child_name, class_doc) 925 926 def introspect_zope_interface(self, interface, interfacename): 927 pass # etc... 928 """ 929