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

Source Code for Module epydoc.docbuilder

   1  # epydoc -- Documentation Builder 
   2  # 
   3  # Copyright (C) 2005 Edward Loper 
   4  # Author: Edward Loper <edloper@loper.org> 
   5  # URL: <http://epydoc.sf.net> 
   6  # 
   7  # $Id: docbuilder.py 1775 2008-02-24 06:09:50Z edloper $ 
   8   
   9  """ 
  10  Construct data structures that encode the API documentation for Python 
  11  objects.  These data structures are created using a series of steps: 
  12   
  13    1. B{Building docs}: Extract basic information about the objects, 
  14       and objects that are related to them.  This can be done by 
  15       introspecting the objects' values (with L{epydoc.docintrospecter}; or 
  16       by parsing their source code (with L{epydoc.docparser}. 
  17   
  18    2. B{Merging}: Combine the information obtained from introspection & 
  19       parsing each object into a single structure. 
  20   
  21    3. B{Linking}: Replace any 'pointers' that were created for imported 
  22       variables by their target (if it's available). 
  23     
  24    4. B{Naming}: Chose a unique 'canonical name' for each 
  25       object. 
  26     
  27    5. B{Docstring Parsing}: Parse the docstring of each object, and 
  28       extract any pertinant information. 
  29     
  30    6. B{Inheritance}: Add information about variables that classes 
  31       inherit from their base classes. 
  32   
  33  The documentation information for each individual object is 
  34  represented using an L{APIDoc}; and the documentation for a collection 
  35  of objects is represented using a L{DocIndex}. 
  36   
  37  The main interface to C{epydoc.docbuilder} consists of two functions: 
  38   
  39    - L{build_doc()} -- Builds documentation for a single item, and 
  40      returns it as an L{APIDoc} object. 
  41    - L{build_doc_index()} -- Builds documentation for a collection of 
  42      items, and returns it as a L{DocIndex} object. 
  43   
  44  The remaining functions are used by these two main functions to 
  45  perform individual steps in the creation of the documentation. 
  46   
  47  @group Documentation Construction: build_doc, build_doc_index, 
  48      _get_docs_from_*, _report_valdoc_progress 
  49  @group Merging: *MERGE*, *merge* 
  50  @group Linking: link_imports 
  51  @group Naming: _name_scores, _unreachable_names, assign_canonical_names, 
  52      _var_shadows_self, _fix_self_shadowing_var, _unreachable_name_for 
  53  @group Inheritance: inherit_docs, _inherit_info 
  54  """ 
  55  __docformat__ = 'epytext en' 
  56   
  57  ###################################################################### 
  58  ## Contents 
  59  ###################################################################### 
  60  ## 1. build_doc() & build_doc_index() -- the main interface. 
  61  ## 2. merge_docs() -- helper, used to merge parse & introspect info 
  62  ## 3. link_imports() -- helper, used to connect imported vars w/ values 
  63  ## 4. assign_canonical_names() -- helper, used to set canonical names 
  64  ## 5. inherit_docs() -- helper, used to inherit docs from base classes 
  65   
  66  ###################################################################### 
  67  ## Imports 
  68  ###################################################################### 
  69   
  70  import sys, os, os.path, __builtin__, imp, re, inspect 
  71  from epydoc.apidoc import * 
  72  from epydoc.docintrospecter import introspect_docs 
  73  from epydoc.docintrospecter import get_value_from_filename, get_value_from_name 
  74  from epydoc.docparser import parse_docs, ParseError 
  75  from epydoc.docstringparser import parse_docstring 
  76  from epydoc import log 
  77  from epydoc.util import * 
  78  from epydoc.compat import * # Backwards compatibility 
  79   
  80  ###################################################################### 
  81  ## 1. build_doc() 
  82  ###################################################################### 
  83   
84 -class BuildOptions:
85 """ 86 Holds the parameters for a documentation building process. 87 """
88 - def __init__(self, introspect=True, parse=True, 89 exclude_introspect=None, exclude_parse=None, 90 add_submodules=True):
91 self.introspect = introspect 92 self.parse = parse 93 self.exclude_introspect = exclude_introspect 94 self.exclude_parse = exclude_parse 95 self.add_submodules = add_submodules 96 97 # Test for pattern syntax and compile them into pattern objects. 98 try: 99 self._introspect_regexp = (exclude_introspect 100 and re.compile(exclude_introspect) or None) 101 self._parse_regexp = (exclude_parse 102 and re.compile(exclude_parse) or None) 103 except Exception, exc: 104 log.error('Error in regular expression pattern: %s' % exc) 105 raise
106
107 - def must_introspect(self, name):
108 """ 109 Return C{True} if a module is to be introsepcted with the current 110 settings. 111 112 @param name: The name of the module to test 113 @type name: L{DottedName} or C{str} 114 """ 115 return self.introspect \ 116 and not self._matches_filter(name, self._introspect_regexp)
117
118 - def must_parse(self, name):
119 """ 120 Return C{True} if a module is to be parsed with the current settings. 121 122 @param name: The name of the module to test 123 @type name: L{DottedName} or C{str} 124 """ 125 return self.parse \ 126 and not self._matches_filter(name, self._parse_regexp)
127
128 - def _matches_filter(self, name, regexp):
129 """ 130 Test if a module name matches a pattern. 131 132 @param name: The name of the module to test 133 @type name: L{DottedName} or C{str} 134 @param regexp: The pattern object to match C{name} against. 135 If C{None}, return C{False} 136 @type regexp: C{pattern} 137 @return: C{True} if C{name} in dotted format matches C{regexp}, 138 else C{False} 139 @rtype: C{bool} 140 """ 141 if regexp is None: return False 142 143 if isinstance(name, DottedName): 144 name = str(name) 145 146 return bool(regexp.search(name))
147 148
149 -def build_doc(item, introspect=True, parse=True, add_submodules=True, 150 exclude_introspect=None, exclude_parse=None, 151 inherit_from_object=False):
152 """ 153 Build API documentation for a given item, and return it as 154 an L{APIDoc} object. 155 156 @rtype: L{APIDoc} 157 @param item: The item to document, specified using any of the 158 following: 159 - A string, naming a python package directory 160 (e.g., C{'epydoc/markup'}) 161 - A string, naming a python file 162 (e.g., C{'epydoc/docparser.py'}) 163 - A string, naming a python object 164 (e.g., C{'epydoc.docparser.DocParser'}) 165 - Any (non-string) python object 166 (e.g., C{list.append}) 167 @param introspect: If true, then use introspection to examine the 168 specified items. Otherwise, just use parsing. 169 @param parse: If true, then use parsing to examine the specified 170 items. Otherwise, just use introspection. 171 """ 172 docindex = build_doc_index([item], introspect, parse, add_submodules, 173 exclude_introspect=exclude_introspect, 174 exclude_parse=exclude_parse, 175 inherit_from_object=inherit_from_object) 176 return docindex.root[0]
177
178 -def build_doc_index(items, introspect=True, parse=True, add_submodules=True, 179 exclude_introspect=None, exclude_parse=None, 180 inherit_from_object=False):
181 """ 182 Build API documentation for the given list of items, and 183 return it in the form of a L{DocIndex}. 184 185 @rtype: L{DocIndex} 186 @param items: The items to document, specified using any of the 187 following: 188 - A string, naming a python package directory 189 (e.g., C{'epydoc/markup'}) 190 - A string, naming a python file 191 (e.g., C{'epydoc/docparser.py'}) 192 - A string, naming a python object 193 (e.g., C{'epydoc.docparser.DocParser'}) 194 - Any (non-string) python object 195 (e.g., C{list.append}) 196 @param introspect: If true, then use introspection to examine the 197 specified items. Otherwise, just use parsing. 198 @param parse: If true, then use parsing to examine the specified 199 items. Otherwise, just use introspection. 200 """ 201 try: 202 options = BuildOptions(parse=parse, introspect=introspect, 203 exclude_introspect=exclude_introspect, exclude_parse=exclude_parse, 204 add_submodules=add_submodules) 205 except Exception, e: 206 # log.error already reported by constructor. 207 return None 208 209 # Get the basic docs for each item. 210 log.start_progress('Building documentation') 211 if introspect: 212 # Import everything before we introspect anything. 213 _import_docs_from_items(items, options) 214 doc_pairs = _get_docs_from_items(items, options) 215 log.end_progress() 216 217 # Merge the introspection & parse docs. 218 if options.parse and options.introspect: 219 log.start_progress('Merging parsed & introspected information') 220 docs = [] 221 for i, (introspect_doc, parse_doc) in enumerate(doc_pairs): 222 if introspect_doc is not None and parse_doc is not None: 223 if introspect_doc.canonical_name not in (None, UNKNOWN): 224 name = introspect_doc.canonical_name 225 else: 226 name = parse_doc.canonical_name 227 log.progress(float(i)/len(doc_pairs), name) 228 docs.append(merge_docs(introspect_doc, parse_doc)) 229 elif introspect_doc is not None: 230 docs.append(introspect_doc) 231 elif parse_doc is not None: 232 docs.append(parse_doc) 233 log.end_progress() 234 elif options.introspect: 235 docs = [doc_pair[0] for doc_pair in doc_pairs if doc_pair[0]] 236 else: 237 docs = [doc_pair[1] for doc_pair in doc_pairs if doc_pair[1]] 238 239 if len(docs) == 0: 240 log.error('Nothing left to document!') 241 return None 242 243 # Collect the docs into a single index. 244 docindex = DocIndex(docs) 245 246 # Replace any proxy valuedocs that we got from importing with 247 # their targets. 248 if options.parse: 249 log.start_progress('Linking imported variables') 250 valdocs = sorted(docindex.reachable_valdocs( 251 imports=False, submodules=False, packages=False, subclasses=False)) 252 for i, val_doc in enumerate(valdocs): 253 _report_valdoc_progress(i, val_doc, valdocs) 254 link_imports(val_doc, docindex) 255 log.end_progress() 256 257 # Assign canonical names. 258 log.start_progress('Indexing documentation') 259 for i, val_doc in enumerate(docindex.root): 260 log.progress(float(i)/len(docindex.root), val_doc.canonical_name) 261 assign_canonical_names(val_doc, val_doc.canonical_name, docindex) 262 log.end_progress() 263 264 # Set overrides pointers 265 log.start_progress('Checking for overridden methods') 266 valdocs = sorted(docindex.reachable_valdocs( 267 imports=False, submodules=False, packages=False, subclasses=False)) 268 for i, val_doc in enumerate(valdocs): 269 if isinstance(val_doc, ClassDoc): 270 percent = float(i)/len(valdocs) 271 log.progress(percent, val_doc.canonical_name) 272 find_overrides(val_doc) 273 log.end_progress() 274 275 # Parse the docstrings for each object. 276 log.start_progress('Parsing docstrings') 277 suppress_warnings = set(valdocs).difference( 278 docindex.reachable_valdocs( 279 imports=False, submodules=False, packages=False, subclasses=False, 280 bases=False, overrides=True)) 281 for i, val_doc in enumerate(valdocs): 282 _report_valdoc_progress(i, val_doc, valdocs) 283 # the value's docstring 284 parse_docstring(val_doc, docindex, suppress_warnings) 285 # the value's variables' docstrings 286 if (isinstance(val_doc, NamespaceDoc) and 287 val_doc.variables not in (None, UNKNOWN)): 288 for var_doc in val_doc.variables.values(): 289 # Now we have a chance to propagate the defining module 290 # to objects for which introspection is not possible, 291 # such as properties. 292 if (isinstance(var_doc.value, ValueDoc) 293 and var_doc.value.defining_module is UNKNOWN): 294 var_doc.value.defining_module = val_doc.defining_module 295 parse_docstring(var_doc, docindex, suppress_warnings) 296 log.end_progress() 297 298 # Take care of inheritance. 299 log.start_progress('Inheriting documentation') 300 for i, val_doc in enumerate(valdocs): 301 if isinstance(val_doc, ClassDoc): 302 percent = float(i)/len(valdocs) 303 log.progress(percent, val_doc.canonical_name) 304 inherit_docs(val_doc, inherit_from_object) 305 log.end_progress() 306 307 # Initialize the groups & sortedvars attributes. 308 log.start_progress('Sorting & Grouping') 309 for i, val_doc in enumerate(valdocs): 310 if isinstance(val_doc, NamespaceDoc): 311 percent = float(i)/len(valdocs) 312 log.progress(percent, val_doc.canonical_name) 313 val_doc.init_sorted_variables() 314 val_doc.init_variable_groups() 315 if isinstance(val_doc, ModuleDoc): 316 val_doc.init_submodule_groups() 317 val_doc.report_unused_groups() 318 log.end_progress() 319 320 return docindex
321
322 -def _report_valdoc_progress(i, val_doc, val_docs):
323 if (isinstance(val_doc, (ModuleDoc, ClassDoc)) and 324 val_doc.canonical_name is not UNKNOWN and 325 not val_doc.canonical_name[0].startswith('??')): 326 log.progress(float(i)/len(val_docs), val_doc.canonical_name)
327 328 #///////////////////////////////////////////////////////////////// 329 # Pre-Import 330 #///////////////////////////////////////////////////////////////// 331
332 -def _import_docs_from_items(items, options):
333 for item in items: 334 # Make sure the item's module is imported. 335 if isinstance(item, basestring): 336 if os.path.isfile(item): 337 _do_import(item, options) 338 elif is_package_dir(item): 339 pkg = os.path.abspath(os.path.join(item, '__init__.py')) 340 val = _do_import(pkg, options) 341 if options.add_submodules and inspect.ismodule(val): 342 _import_docs_from_package(val, options) 343 elif is_pyname(item): 344 if options.must_introspect(item): 345 try: 346 val = get_value_from_name(item) 347 if options.add_submodules and inspect.ismodule(val): 348 _import_docs_from_package(val, options) 349 except ImportError, e: pass
350
351 -def _import_docs_from_package(pkg, options):
352 subpackage_filenames = set() 353 module_filenames = {} 354 pkg_path = getattr(pkg, '__path__', ()) 355 for subdir in pkg_path: 356 if os.path.isdir(subdir): 357 for name in os.listdir(subdir): 358 filename = os.path.join(subdir, name) 359 if is_module_file(filename): 360 basename = os.path.splitext(filename)[0] 361 if os.path.split(basename)[1] != '__init__': 362 module_filenames[basename]