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 1810 2008-03-31 03:22:51Z edloper $ 
   8   
   9  """ 
  10  Extract API documentation about python objects by directly introspecting 
  11  their values. 
  12   
  13  The function L{introspect_docs()}, which provides the main interface 
  14  of this module, examines a Python objects via introspection, and uses 
  15  the information it finds to create an L{APIDoc} objects containing the 
  16  API documentation for that objects. 
  17   
  18  The L{register_introspecter()} method can be used to extend the 
  19  functionality of C{docintrospector}, by providing methods that handle 
  20  special value types. 
  21  """ 
  22  __docformat__ = 'epytext en' 
  23   
  24  ###################################################################### 
  25  ## Imports 
  26  ###################################################################### 
  27   
  28  import inspect, re, sys, os.path, imp 
  29  # API documentation encoding: 
  30  from epydoc.apidoc import * 
  31  # Type comparisons: 
  32  from types import * 
  33  # Error reporting: 
  34  from epydoc import log 
  35  # Helper functions: 
  36  from epydoc.util import * 
  37  # For extracting encoding for docstrings: 
  38  import epydoc.docparser 
  39  # Builtin values 
  40  import __builtin__ 
  41  # Backwards compatibility 
  42  from epydoc.compat import *  
  43   
  44  ###################################################################### 
  45  ## Caches 
  46  ###################################################################### 
  47   
  48  _valuedoc_cache = {} 
  49  """A cache containing the API documentation for values that we've 
  50  already seen.  This cache is implemented as a dictionary that maps a 
  51  value's pyid to its L{ValueDoc}. 
  52   
  53  Note that if we encounter a value but decide not to introspect it 
  54  (because it's imported from another module), then C{_valuedoc_cache} 
  55  will contain an entry for the value, but the value will not be listed 
  56  in L{_introspected_values}.""" 
  57   
  58  _introspected_values = {} 
  59  """A record which values we've introspected, encoded as a dictionary from 
  60  pyid to C{bool}.""" 
  61   
62 -def clear_cache():
63 """ 64 Discard any cached C{APIDoc} values that have been computed for 65 introspected values. 66 """ 67 _valuedoc_cache.clear() 68 _introspected_values.clear()
69 70 ###################################################################### 71 ## Introspection 72 ###################################################################### 73
74 -def introspect_docs(value=None, name=None, filename=None, context=None, 75 is_script=False, module_name=None):
76 """ 77 Generate the API documentation for a specified object by 78 introspecting Python values, and return it as a L{ValueDoc}. The 79 object to generate documentation for may be specified using 80 the C{value} parameter, the C{filename} parameter, I{or} the 81 C{name} parameter. (It is an error to specify more than one 82 of these three parameters, or to not specify any of them.) 83 84 @param value: The python object that should be documented. 85 @param filename: The name of the file that contains the python 86 source code for a package, module, or script. If 87 C{filename} is specified, then C{introspect} will return a 88 C{ModuleDoc} describing its contents. 89 @param name: The fully-qualified python dotted name of any 90 value (including packages, modules, classes, and 91 functions). C{DocParser} will automatically figure out 92 which module(s) it needs to import in order to find the 93 documentation for the specified object. 94 @param context: The API documentation for the class of module 95 that contains C{value} (if available). 96 @param module_name: The name of the module where the value is defined. 97 Useful to retrieve the docstring encoding if there is no way to 98 detect the module by introspection (such as in properties) 99 """ 100 if value is None and name is not None and filename is None: 101 value = get_value_from_name(DottedName(name)) 102 elif value is None and name is None and filename is not None: 103 if is_script: 104 value = get_value_from_scriptname(filename) 105 else: 106 value = get_value_from_filename(filename, context) 107 elif name is None and filename is None: 108 # it's ok if value is None -- that's a value, after all. 109 pass 110 else: 111 raise ValueError("Expected exactly one of the following " 112 "arguments: value, name, filename") 113 114 pyid = id(value) 115 116 # If we've already introspected this value, then simply return 117 # its ValueDoc from our cache. 118 if pyid in _introspected_values: 119 # If the file is a script, then adjust its name. 120 if is_script and filename is not None: 121 _valuedoc_cache[pyid].canonical_name = DottedName( 122 munge_script_name(str(filename))) 123 return _valuedoc_cache[pyid] 124 125 # Create an initial value doc for this value & add it to the cache. 126 val_doc = _get_valuedoc(value) 127 128 # Introspect the value. 129 _introspected_values[pyid] = True 130 introspect_func = _get_introspecter(value) 131 introspect_func(value, val_doc, module_name=module_name) 132 133 # Set canonical name, if it was given 134 if val_doc.canonical_name is UNKNOWN and name is not None: 135 val_doc.canonical_name = DottedName(name) 136 137 # If the file is a script, then adjust its name. 138 if is_script and filename is not None: 139 val_doc.canonical_name = DottedName(munge_script_name(str(filename))) 140 141 if val_doc.canonical_name is UNKNOWN and filename is not None: 142 shadowed_name = DottedName(value.__name__) 143 log.warning("Module %s is shadowed by a variable with " 144 "the same name." % shadowed_name) 145 val_doc.canonical_name = DottedName(str(shadowed_name)+"'") 146 147 return val_doc
148
149 -def _get_valuedoc(value):
150 """ 151 If a C{ValueDoc} for the given value exists in the valuedoc 152 cache, then return it; otherwise, create a new C{ValueDoc}, 153 add it to the cache, and return it. When possible, the new 154 C{ValueDoc}'s C{pyval}, C{repr}, and C{canonical_name} 155 attributes will be set appropriately. 156 """ 157 pyid = id(value) 158 val_doc = _valuedoc_cache.get(pyid) 159 if val_doc is None: 160 try: canonical_name = get_canonical_name(value, strict=True) 161 except DottedName.InvalidDottedName: canonical_name = UNKNOWN 162 val_doc = ValueDoc(pyval=value, canonical_name = canonical_name, 163 docs_extracted_by='introspecter') 164 _valuedoc_cache[pyid] = val_doc 165 166 # If it's a module, then do some preliminary introspection. 167 # Otherwise, check what the containing module is (used e.g. 168 # to decide what markup language should be used for docstrings) 169 if inspect.ismodule(value): 170 introspect_module(value, val_doc, preliminary=True) 171 val_doc.defining_module = val_doc 172 else: 173 module_name = str(get_containing_module(value)) 174 module = sys.modules.get(module_name) 175 if module is not None and inspect.ismodule(module): 176 val_doc.defining_module = _get_valuedoc(module) 177 178 return val_doc
179 180 #//////////////////////////////////////////////////////////// 181 # Module Introspection 182 #//////////////////////////////////////////////////////////// 183 184 #: A list of module variables that should not be included in a 185 #: module's API documentation. 186 UNDOCUMENTED_MODULE_VARS = ( 187 '__builtins__', '__doc__', '__all__', '__file__', '__path__', 188 '__name__', '__extra_epydoc_fields__', '__docformat__') 189
190 -def introspect_module(module, module_doc, module_name=None, preliminary=False):
191 """ 192 Add API documentation information about the module C{module} 193 to C{module_doc}. 194 """ 195 module_doc.specialize_to(ModuleDoc) 196 197 # Record the module's docformat 198 if hasattr(module, '__docformat__'): 199 module_doc.docformat = unicode(module.__docformat__) 200 201 # Record the module's filename 202 if hasattr(module, '__file__'): 203 try: module_doc.filename = unicode(module.__file__) 204 except KeyboardInterrupt: raise 205 except: pass 206 if module_doc.filename is not UNKNOWN: 207 try: module_doc.filename = py_src_filename(module_doc.filename) 208 except ValueError: pass 209 210 # If this is just a preliminary introspection, then don't do 211 # anything else. (Typically this is true if this module was 212 # imported, but is not included in the set of modules we're 213 # documenting.) 214 module_doc.variables = {} 215 if preliminary: return 216 217 # Record the module's docstring 218 if hasattr(module, '__doc__'): 219 module_doc.docstring = get_docstring(module) 220 221 # If the module has a __path__, then it's (probably) a 222 # package; so set is_package=True and record its __path__. 223 if hasattr(module, '__path__'): 224 module_doc.is_package = True 225 try: module_doc.path = [unicode(p) for p in module.__path__] 226 except KeyboardInterrupt: raise 227 except: pass 228 else: 229 module_doc.is_package = False 230 231 # Make sure we have a name for the package. 232 dotted_name = module_doc.canonical_name 233 if dotted_name is UNKNOWN: 234 dotted_name = DottedName(module.__name__) 235 name_without_primes = DottedName(str(dotted_name).replace("'", "")) 236 237 # Record the module's parent package, if it has one. 238 if len(dotted_name) > 1: 239 package_name = str(dotted_name.container()) 240 package = sys.modules.get(package_name) 241 if package is not None: 242 module_doc.package = introspect_docs(package) 243 else: 244 module_doc.package = None 245 246 # Initialize the submodules property 247 module_doc.submodules = [] 248 249 # Add the module to its parent package's submodules list. 250 if module_doc.package not in (None, UNKNOWN): 251 module_doc.package.submodules.append(module_doc) 252 253 # Look up the module's __all__ attribute (public names). 254 public_names = None 255 if hasattr(module, '__all__'): 256 try: 257 public_names = set([str(name) for name in module.__all__]) 258 except KeyboardInterrupt: raise 259 except: pass 260 261 # Record the module's variables. 262 module_doc.variables = {} 263 for child_name in dir(module): 264 if child_name in UNDOCUMENTED_MODULE_VARS: continue 265 child = getattr(module, child_name) 266 267 # Create a VariableDoc for the child, and introspect its 268 # value if it's defined in this module. 269 container = get_containing_module(child) 270 if (((container is not None and 271 container == name_without_primes) or 272 (public_names is not None and 273 child_name in public_names)) 274 and not inspect.ismodule(child)): 275 # Local variable. 276 child_val_doc = introspect_docs(child, context=module_doc, 277 module_name=dotted_name) 278 child_var_doc = VariableDoc(name=child_name, 279 value=child_val_doc, 280 is_imported=False, 281 container=module_doc, 282 docs_extracted_by='introspecter') 283 elif ((container is None or module_doc.canonical_name is UNKNOWN) 284 and not inspect.ismodule(child)): 285 286 # Don't introspect stuff "from __future__" 287 if is_future_feature(child): continue 288 289 # Possibly imported variable. 290 child_val_doc = introspect_docs(child, context=module_doc) 291 child_var_doc = VariableDoc(name=child_name, 292 value=child_val_doc, 293 container=module_doc, 294 docs_extracted_by='introspecter') 295 else: 296 # Imported variable. 297 child_val_doc = _get_valuedoc(child) 298 child_var_doc = VariableDoc(name=child_name, 299 value=child_val_doc, 300 is_imported=True, 301 container=module_doc, 302 docs_extracted_by='introspecter') 303 304 # If the module's __all__ attribute is set, use it to set the 305 # variables public/private status and imported status. 306 if public_names is not None: 307 if child_name in public_names: 308 child_var_doc.is_public = True 309 if not isinstance(child_var_doc, ModuleDoc): 310 child_var_doc.is_imported = False 311 else: 312 child_var_doc.is_public = False 313 314 module_doc.variables[child_name] = child_var_doc 315 316 return module_doc
317 318 #//////////////////////////////////////////////////////////// 319 # Class Introspection 320 #//////////////////////////////////////////////////////////// 321 322 #: A list of class variables that should not be included in a 323 #: class's API documentation. 324 UNDOCUMENTED_CLASS_VARS = ( 325 '__doc__', '__module__', '__dict__', '__weakref__', '__slots__', 326 '__pyx_vtable__', '__metaclass__') 327
328 -def introspect_class(cls, class_doc, module_name=None):
329 """ 330 Add API documentation information about the class C{cls} 331 to C{class_doc}. 332 """ 333 class_doc.specialize_to(ClassDoc) 334 335 # Record the class's docstring. 336 class_doc.docstring = get_docstring(cls) 337 338 # Record the class's __all__ attribute (public names). 339 public_names = None 340 if hasattr(cls, '__all__'): 341 try: 342 public_names = set([str(name) for name in cls.__all__]) 343 except KeyboardInterrupt: raise 344 except: pass 345 346 # Record the class's metaclass 347 class_doc.metaclass = introspect_docs(type(cls)) 348 349 # Start a list of subclasses. 350 class_doc.subclasses = [] 351 352 # Sometimes users will define a __metaclass__ that copies all 353 # class attributes from bases directly into the derived class's 354 # __dict__ when the class is created. (This saves the lookup time 355 # needed to search the base tree for an attribute.) But for the 356 # docs, we only want to list these copied attributes in the 357 # parent. So only add an attribute if it is not identical to an 358 # attribute of a base class. (Unfortunately, this can sometimes 359 # cause an attribute to look like it was inherited, even though it 360 # wasn't, if it happens to have the exact same value as the 361 # corresponding base's attribute.) An example of a case where 362 # this helps is PyQt -- subclasses of QWidget get about 300 363 # methods injected into them. 364 base_children = {} 365 366 # Record the class's base classes; and add the class to its 367 # base class's subclass lists. 368 if hasattr(cls, '__bases__'): 369 try: bases = list(cls.__bases__) 370 except: 371 bases = None 372 log.warning("Class '%s' defines __bases__, but it does not " 373 "contain an iterable; ignoring base list." 374 % getattr(cls, '__name__', '??')) 375 if bases is not None: 376 class_doc.bases = [] 377 for base in bases: 378 basedoc = introspect_docs(base) 379 class_doc.bases.append(basedoc) 380 basedoc.subclasses.append(class_doc) 381 382 bases.reverse() 383 for base in bases: 384 if hasattr(base, '__dict__'): 385 base_children.update(base.__dict__) 386 387 # The module name is not defined if the class is being introspected 388 # as another class base. 389 if module_name is None and class_doc.defining_module not in (None, UNKNOWN): 390 module_name = class_doc.defining_module.canonical_name 391 392 # Record the class's local variables. 393 class_doc.variables = {} 394 if hasattr(cls, '__dict__'): 395 private_prefix = '_%s__' % getattr(cls, '__name__', '<none>') 396 for child_name, child in cls.__dict__.items(): 397 if (child_name in base_children 398 and base_children[child_name] == child): 399 continue 400 401 if child_name.startswith(private_prefix): 402 child_name = child_name[len(private_prefix)-2:] 403 if child_name in UNDOCUMENTED_CLASS_VARS: continue 404 val_doc = introspect_docs(child, context=class_doc, 405 module_name=module_name) 406 var_doc = VariableDoc(name=child_name, value=val_doc, 407 container=class_doc, 408