1
2
3
4
5
6
7
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
59
60
61
62
63
64
65
66
67
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.docparser import parse_docs, ParseError
74 from epydoc.docstringparser import parse_docstring
75 from epydoc import log
76 from epydoc.util import *
77 from epydoc.compat import *
78
79
80
81
82
84 """
85 Holds the parameters for a documentation building process.
86 """
87 - def __init__(self, introspect=True, parse=True,
88 exclude_introspect=None, exclude_parse=None,
89 add_submodules=True):
90 self.introspect = introspect
91 self.parse = parse
92 self.exclude_introspect = exclude_introspect
93 self.exclude_parse = exclude_parse
94 self.add_submodules = add_submodules
95
96
97 try:
98 self._introspect_regexp = (exclude_introspect
99 and re.compile(exclude_introspect) or None)
100 self._parse_regexp = (exclude_parse
101 and re.compile(exclude_parse) or None)
102 except Exception, exc:
103 log.error('Error in regular expression pattern: %s' % exc)
104 raise
105
107 """
108 Return C{True} if a module is to be introsepcted with the current
109 settings.
110
111 @param name: The name of the module to test
112 @type name: L{DottedName} or C{str}
113 """
114 return self.introspect \
115 and not self._matches_filter(name, self._introspect_regexp)
116
118 """
119 Return C{True} if a module is to be parsed with the current settings.
120
121 @param name: The name of the module to test
122 @type name: L{DottedName} or C{str}
123 """
124 return self.parse \
125 and not self._matches_filter(name, self._parse_regexp)
126
128 """
129 Test if a module name matches a pattern.
130
131 @param name: The name of the module to test
132 @type name: L{DottedName} or C{str}
133 @param regexp: The pattern object to match C{name} against.
134 If C{None}, return C{False}
135 @type regexp: C{pattern}
136 @return: C{True} if C{name} in dotted format matches C{regexp},
137 else C{False}
138 @rtype: C{bool}
139 """
140 if regexp is None: return False
141
142 if isinstance(name, DottedName):
143 name = str(name)
144
145 return bool(regexp.search(name))
146
147
148 -def build_doc(item, introspect=True, parse=True, add_submodules=True,
149 exclude_introspect=None, exclude_parse=None):
150 """
151 Build API documentation for a given item, and return it as
152 an L{APIDoc} object.
153
154 @rtype: L{APIDoc}
155 @param item: The item to document, specified using any of the
156 following:
157 - A string, naming a python package directory
158 (e.g., C{'epydoc/markup'})
159 - A string, naming a python file
160 (e.g., C{'epydoc/docparser.py'})
161 - A string, naming a python object
162 (e.g., C{'epydoc.docparser.DocParser'})
163 - Any (non-string) python object
164 (e.g., C{list.append})
165 @param introspect: If true, then use introspection to examine the
166 specified items. Otherwise, just use parsing.
167 @param parse: If true, then use parsing to examine the specified
168 items. Otherwise, just use introspection.
169 """
170 docindex = build_doc_index([item], introspect, parse, add_submodules,
171 exclude_introspect=exclude_introspect,
172 exclude_parse=exclude_parse)
173 return docindex.root[0]
174
175 -def build_doc_index(items, introspect=True, parse=True, add_submodules=True,
176 exclude_introspect=None, exclude_parse=None):
177 """
178 Build API documentation for the given list of items, and
179 return it in the form of a L{DocIndex}.
180
181 @rtype: L{DocIndex}
182 @param items: The items to document, specified using any of the
183 following:
184 - A string, naming a python package directory
185 (e.g., C{'epydoc/markup'})
186 - A string, naming a python file
187 (e.g., C{'epydoc/docparser.py'})
188 - A string, naming a python object
189 (e.g., C{'epydoc.docparser.DocParser'})
190 - Any (non-string) python object
191 (e.g., C{list.append})
192 @param introspect: If true, then use introspection to examine the
193 specified items. Otherwise, just use parsing.
194 @param parse: If true, then use parsing to examine the specified
195 items. Otherwise, just use introspection.
196 """
197 try:
198 options = BuildOptions(parse=parse, introspect=introspect,
199 exclude_introspect=exclude_introspect, exclude_parse=exclude_parse,
200 add_submodules=add_submodules)
201 except Exception, e:
202
203 return None
204
205
206 doc_pairs = _get_docs_from_items(items, options)
207
208
209 if options.parse and options.introspect:
210 log.start_progress('Merging parsed & introspected information')
211 docs = []
212 for i, (introspect_doc, parse_doc) in enumerate(doc_pairs):
213 if introspect_doc is not None and parse_doc is not None:
214 if introspect_doc.canonical_name not in (None, UNKNOWN):
215 name = introspect_doc.canonical_name
216 else:
217 name = parse_doc.canonical_name
218 log.progress(float(i)/len(doc_pairs), name)
219 docs.append(merge_docs(introspect_doc, parse_doc))
220 elif introspect_doc is not None:
221 docs.append(introspect_doc)
222 elif parse_doc is not None:
223 docs.append(parse_doc)
224 log.end_progress()
225 elif options.introspect:
226 docs = [doc_pair[0] for doc_pair in doc_pairs if doc_pair[0]]
227 else:
228 docs = [doc_pair[1] for doc_pair in doc_pairs if doc_pair[1]]
229
230 if len(docs) == 0:
231 log.error('Nothing left to document!')
232 return None
233
234
235 docindex = DocIndex(docs)
236
237
238
239 if options.parse:
240 log.start_progress('Linking imported variables')
241 valdocs = sorted(docindex.reachable_valdocs(
242 imports=False, submodules=False, packages=False, subclasses=False))
243 for i, val_doc in enumerate(valdocs):
244 _report_valdoc_progress(i, val_doc, valdocs)
245 link_imports(val_doc, docindex)
246 log.end_progress()
247
248
249 log.start_progress('Indexing documentation')
250 for i, val_doc in enumerate(docindex.root):
251 log.progress(float(i)/len(docindex.root), val_doc.canonical_name)
252 assign_canonical_names(val_doc, val_doc.canonical_name, docindex)
253 log.end_progress()
254
255
256 log.start_progress('Checking for overridden methods')
257 valdocs = sorted(docindex.reachable_valdocs(
258 imports=False, submodules=False, packages=False, subclasses=False))
259 for i, val_doc in enumerate(valdocs):
260 if isinstance(val_doc, ClassDoc):
261 percent = float(i)/len(valdocs)
262 log.progress(percent, val_doc.canonical_name)
263 find_overrides(val_doc)
264 log.end_progress()
265
266
267 log.start_progress('Parsing docstrings')
268 suppress_warnings = set(valdocs).difference(
269 docindex.reachable_valdocs(
270 imports=False, submodules=False, packages=False, subclasses=False,
271 bases=False, overrides=True))
272 for i, val_doc in enumerate(valdocs):
273 _report_valdoc_progress(i, val_doc, valdocs)
274
275 parse_docstring(val_doc, docindex, suppress_warnings)
276
277 if (isinstance(val_doc, NamespaceDoc) and
278 val_doc.variables not in (None, UNKNOWN)):
279 for var_doc in val_doc.variables.values():
280
281
282
283 if (isinstance(var_doc.value, ValueDoc)
284 and var_doc.value.defining_module is UNKNOWN):
285 var_doc.value.defining_module = val_doc.defining_module
286 parse_docstring(var_doc, docindex, suppress_warnings)
287 log.end_progress()
288
289
290 log.start_progress('Inheriting documentation')
291 for i, val_doc in enumerate(valdocs):
292 if isinstance(val_doc, ClassDoc):
293 percent = float(i)/len(valdocs)
294 log.progress(percent, val_doc.canonical_name)
295 inherit_docs(val_doc)
296 log.end_progress()
297
298
299 log.start_progress('Sorting & Grouping')
300 for i, val_doc in enumerate(valdocs):
301 if isinstance(val_doc, NamespaceDoc):
302 percent = float(i)/len(valdocs)
303 log.progress(percent, val_doc.canonical_name)
304 val_doc.init_sorted_variables()
305 val_doc.init_variable_groups()
306 if isinstance(val_doc, ModuleDoc):
307 val_doc.init_submodule_groups()
308 val_doc.report_unused_groups()
309 log.end_progress()
310
311 return docindex
312
318
319
320
321
322
324
325
326 log.start_progress('Building documentation')
327 progress_estimator = _ProgressEstimator(items)
328
329
330 item_set = set()
331 for item in items[:]:
332 if item in item_set:
333 log.warning("Name %r given multiple times" % item)
334 items.remove(item)
335 item_set.add(item)
336
337
338
339
340
341 canonical_names = {}
342
343
344 doc_pairs = []
345 for item in items:
346 if isinstance(item, basestring):
347 if is_module_file(item):
348 doc_pairs.append(_get_docs_from_module_file(
349 item, options, progress_estimator))
350 elif is_package_dir(item):
351 pkgfile = os.path.abspath(os.path.join(item, '__init__'))
352 doc_pairs.append(_get_docs_from_module_file(
353 pkgfile, options, progress_estimator))
354 elif os.path.isfile(item):
355 doc_pairs.append(_get_docs_from_pyscript(
356 item, options, progress_estimator))
357 elif hasattr(__builtin__, item):
358 val = getattr(__builtin__, item)
359 doc_pairs.append(_get_docs_from_pyobject(
360 val, options, progress_estimator))
361 elif is_pyname(item):
362 doc_pairs.append(_get_docs_from_pyname(
363 item, options, progress_estimator))
364 elif os.path.isdir(item):
365 log.error("Directory %r is not a package" % item)
366 continue
367 elif os.path.isfile(item):
368 log.error("File %s is not a Python module" % item)
369 continue
370 else:
371 log.error("Could not find a file or object named %s" %
372 item)
373 continue
374 else:
375 doc_pairs.append(_get_docs_from_pyobject(
376 item, options, progress_estimator))
377
378
379 name = (getattr(doc_pairs[-1][0], 'canonical_name', None) or
380 getattr(doc_pairs[-1][1], 'canonical_name', None))
381 if name in canonical_names:
382 log.error(
383 'Two of the specified items, %r and %r, have the same '
384 'canonical name ("%s"). This may mean that you specified '
385 'two different files that both use the same module name. '
386 'Ignoring the second item (%r)' %
387 (canonical_names[name], item, name, canonical_names[name]))
388 doc_pairs.pop()
389 else:
390 canonical_names[name] = item
391
392
393
394
395
396 if options.add_submodules and not is_module_file(item):
397 doc_pairs += _get_docs_from_submodules(
398 item, doc_pairs[-1], options, progress_estimator)
399
400 log.end_progress()
401 return doc_pairs
402
404 progress_estimator.complete += 1
405 log.progress(progress_estimator.progress(), repr(obj))
406
407 if not options.introspect:
408 log.error("Cannot get docs for Python objects without "
409 "introspecting them.")
410
411 introspect_doc = parse_doc = None
412 introspect_error = parse_error = None
413 try:
414 introspect_doc = introspect_docs(value=obj)
415 except ImportError, e:
416 log.error(e)
417 return (None, None)
418 if options.parse:
419 if introspect_doc.canonical_name is not None:
420 prev_introspect = options.introspect
421 options.introspect = False
422 try:
423 _, parse_docs = _get_docs_from_pyname(
424 str(introspect_doc.canonical_name), options,
425 progress_estimator, suppress_warnings=True)
426 finally:
427 options.introspect = prev_introspect
428
429
430 if introspect_doc.canonical_name in (None, UNKNOWN):
431 if hasattr(obj, '__name__'):
432 introspect_doc.canonical_name = DottedName(
433 DottedName.UNREACHABLE, obj.__name__)
434 else:
435 introspect_doc.canonical_name = DottedName(
436 DottedName.UNREACHABLE)
437 return (introspect_doc, parse_doc)
438
469
471
472
473
474 introspect_doc = parse_doc = None
475 introspect_error = parse_error = None
476 if options.introspect:
477 try:
478 introspect_doc = introspect_docs(filename=filename, is_script=True)
479 if introspect_doc.canonical_name is UNKNOWN:
480 introspect_doc.canonical_name = munge_script_name(filename)
481 except ImportError, e:
482 introspect_error = str(e)
483 if options.parse:
484 try:
485 parse_doc = parse_docs(filename=filename, is_script=True)
486 except ParseError, e:
487 parse_error = str(e)
488 except ImportError, e:
489 parse_error = str(e)
490
491
492 _report_errors(filename, introspect_doc, parse_doc,
493 introspect_error, parse_error)
494
495
496 return (introspect_doc, parse_doc)
497
500 """
501 Construct and return the API documentation for the python
502 module with the given filename.
503
504 @param parent_docs: The C{ModuleDoc} of the containing package.
505 If C{parent_docs} is not provided, then this method will
506 check if the given filename is contained in a package; and
507 if so, it will construct a stub C{ModuleDoc} for the
508 containing package(s). C{parent_docs} is a tuple, where
509 the first element is the parent from introspection, and
510 the second element is the parent from parsing.
511 """
512
513 modulename = os.path.splitext(os.path.split(filename)[1])