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.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 *
79
80
81
82
83
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
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
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
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
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
207 return None
208
209
210 log.start_progress('Building documentation')
211 if introspect:
212
213 _import_docs_from_items(items, options)
214 doc_pairs = _get_docs_from_items(items, options)
215 log.end_progress()
216
217
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
244 docindex = DocIndex(docs)
245
246
247
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
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
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
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
284 parse_docstring(val_doc, docindex, suppress_warnings)
285
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
290
291
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
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
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
327
328
329
330
331
350
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] = filename
363 elif is_package_dir(filename):
364 subpackage_filenames.add(os.path.join(filename,
365 '__init__.py'))
366
367 for filename in module_filenames.values():
368 _do_import(filename, options, pkg.__name__)
369 for subpackage_filename in subpackage_filenames:
370 subpackage = _do_import(subpackage_filename, options, pkg.__name__)
371 if inspect.ismodule(subpackage):
372 _import_docs_from_package(subpackage, options)
373
386
387
388
389
390
392
393 progress_estimator = _ProgressEstimator(items)
394
395
396 item_set = set()
397 for item in items[:]:
398 if item in item_set:
399 log.warning("Name %r given multiple times" % item)
400 items.remove(item)
401 item_set.add(item)
402
403
404
405
406
407 canonical_names = {}
408
409
410 doc_pairs = []
411 for item in items:
412 if isinstance(item, basestring):
413 if is_module_file(item):
414 doc_pairs.append(_get_docs_from_module_file(
415 item, options, progress_estimator))
416 elif is_package_dir(item):
417 pkgfile = os.path.abspath(os.path.join(item, '__init__'))
418 doc_pairs.append(_get_docs_from_module_file(
419 pkgfile, options, progress_estimator))
420 elif os.path.isfile(item):
421 doc_pairs.append(_get_docs_from_pyscript(
422 item, options, progress_estimator))
423 elif hasattr(__builtin__, item):
424 val = getattr(__builtin__, item)
425 doc_pairs.append(_get_docs_from_pyobject(
426 val, options, progress_estimator))
427 elif is_pyname(item):
428 doc_pairs.append(_get_docs_from_pyname(
429 item, options, progress_estimator))
430 elif os.path.isdir(item):
431 log.error("Directory %r is not a package" % item)
432 continue
433 elif os.path.isfile(item):
434 log.error("File %s is not a Python module" % item)
435 continue
436 else:
437 log.error("Could not find a file or object named %s" %
438 item)
439 continue
440 else:
441 doc_pairs.append(_get_docs_from_pyobject(
442 item, options, progress_estimator))
443
444
445 name = (getattr(doc_pairs[-1][0], 'canonical_name', None) or
446 getattr(doc_pairs[-1][1], 'canonical_name', None))
447 if name in canonical_names:
448 log.error(
449 'Two of the specified items, %r and %r, have the same '
450 'canonical name ("%s"). This may mean that you specified '
451 'two different files that both use the same module name. '
452 'Ignoring the second item (%r)' %
453 (canonical_names[name], item, name, canonical_names[name]))
454 doc_pairs.pop()
455 else:
456 canonical_names[name] = item
457
458
459
460
461
462 if options.add_submodules and not is_module_file(item):
463 doc_pairs += _get_docs_from_submodules(
464 item, doc_pairs[-1], options, progress_estimator)
465
466 return doc_pairs
467
469 progress_estimator.complete += 1
470 log.progress(progress_estimator.progress(), repr(obj))
471
472 if not options.introspect:
473 log.error("Cannot get docs for Python objects without "
474 "introspecting them.")
475
476 introspect_doc = parse_doc = None
477 introspect_error = parse_error = None
478 try:
479 introspect_doc = introspect_docs(value=obj)
480 except ImportError, e:
481 log.error(e)
482 return (None, None)
483 if options.parse:
484 if introspect_doc.canonical_name is not None:
485 prev_introspect = options.introspect
486 options.introspect = False
487 try:
488 _, parse_docs = _get_docs_from_pyname(
489 str(introspect_doc.canonical_name), options,
490 progress_estimator, suppress_warnings=True)
491 finally:
492 options.introspect = prev_introspect
493
494
495 if introspect_doc.canonical_name in (None, UNKNOWN):
496 if hasattr(obj, '__name__'):
497 introspect_doc.canonical_name = DottedName(
498 DottedName.UNREACHABLE, obj.__name__)
499 else:
500 introspect_doc.canonical_name = DottedName(
501 DottedName.UNREACHABLE)
502 return (introspect_doc, parse_doc)
503
534
536
537
538
539 introspect_doc = parse_doc = None
540 introspect_error = parse_error = None
541 if options.introspect:
542 try:
543 introspect_doc = introspect_docs(filename=filename, is_script=True)
544 if introspect_doc.canonical_name is UNKNOWN:
545 introspect_doc.canonical_name = munge_script_name(filename)
546 except ImportError, e:
547 introspect_error = str(e)
548 if options.parse:
549 try:
550 parse_doc = parse_docs(filename=filename, is_script=True)
551 except ParseError, e:
552 parse_error = str(e)
553 except ImportError, e:
554 parse_error = str(e)
555
556
557 _report_errors(filename, introspect_doc, parse_doc,
558 introspect_error, parse_error)
559
560
561 return (introspect_doc, parse_doc)
562
565 """
566 Construct and return the API documentation for the python
567 module with the given filename.
568
569 @param parent_docs: The C{ModuleDoc} of the containing package.
570 If C{parent_docs} is not provided, then this method will
571 check if the given filename is contained in a package; and
572 if so, it will construct a stub C{ModuleDoc} for the
573 containing package(s). C{parent_docs} is a tuple, where
574 the first element is the parent from introspection, and
575 the second element is the parent from parsing.
576 """
577
578 modulename = os.path.splitext(os.path.split(filename)[1])[0]
579 if modulename == '__init__':
580 modulename = os.path.split(os.path.split(filename)[0])[1]
581 if parent_docs[0]:
582 modulename = DottedName(parent_docs[0].canonical_name, modulename)
583 elif parent_docs[1]:
584 modulename = DottedName(parent_docs[1].canonical_name, modulename)
585 if options.must_introspect(modulename) or options.must_parse(modulename):
586 log.progress(progress_estimator.progress(),
587 '%s (%s)' % (modulename, filename))
588 progress_estimator.complete += 1
589
590
591 filename = os.path.normpath(os.path.abspath(filename))
592
593
594 try:
595 filename = py_src_filename(filename)
596 src_file_available = True
597 except ValueError:
598 src_file_available = False
599
600
601 introspect_doc = parse_doc = None
602 introspect_error = parse_error = None
603 if options.must_introspect(modulename):
604 try:
605 introspect_doc = introspect_docs(
606 filename=filename, context=parent_docs[0])
607 if introspect_doc.canonical_name is UNKNOWN:
608 introspect_doc.canonical_name = modulename
609 except ImportError, e:
610 introspect_error = str(e)
611 if src_file_available and options.must_parse(modulename):
612 try:
613 parse_doc = parse_docs(
614 filename=filename, context=parent_docs[1])
615 except (ParseError, ImportError, IOError, OSError), e:
616 parse_error = str(e)
617
618
619 _report_errors(filename, introspect_doc, parse_doc,
620 introspect_error, parse_error)
621
622
623 return (introspect_doc, parse_doc)
624
626
627 if isinstance(pkg_docs[0], ModuleDoc) and pkg_docs[0].is_package:
628 pkg_path = pkg_docs[0].path
629 package_dir = os.path.split(pkg_docs[0].filename)[0]
630 elif isinstance(pkg_docs[1], ModuleDoc) and pkg_docs[1].is_package:
631 pkg_path = pkg_docs[1].path
632 package_dir = os.path.split(pkg_docs[1].filename)[0]
633 else:
634 return []
635
636 module_filenames = {}
637 subpackage_dirs = set()
638 for subdir in pkg_path:
639 if os.path.isdir(subdir):
640 for name in os.listdir(subdir):
641 filename = os.path.join(subdir, name)
642
643 if is_module_file(filename):
644 basename = os.path.splitext(filename)[0]
645 if os.path.split(basename)[1] != '__init__':
646 module_filenames[basename] = filename
647
648 if is_package_dir(filename):
649 subpackage_dirs.add(filename)
650
651
652 progress_estimator.revise_estimate(item, module_filenames.items(),
653 subpackage_dirs)
654
655 docs = [pkg_docs]
656 for module_filename in module_filenames.values():
657 d = _get_docs_from_module_file(
658 module_filename, options, progress_estimator, pkg_docs)
659 docs.append(d)
660 for subpackage_dir in subpackage_dirs:
661 subpackage_file = os.path.join(subpackage_dir, '__init__')
662 docs.append(_get_docs_from_module_file(
663 subpackage_file, options, progress_estimator, pkg_docs))
664 docs += _get_docs_from_submodules(
665 subpackage_dir, docs[-1], options, progress_estimator)
666 return docs
667
668 -def _report_errors(name, introspect_doc, parse_doc,
669 introspect_error, parse_error):
670 hdr = 'In %s:\n' % name
671 if introspect_doc == parse_doc == None:
672 log.start_block('%sNo documentation available!' % hdr)
673 if introspect_error:
674 log.error('Import failed:\n%s' % introspect_error)
675 if parse_error:
676 log.error('Source code parsing failed:\n%s' % parse_error)
677 log.end_block()
678 elif introspect_error:
679 log.start_block('%sImport failed (but source code parsing '
680 'was successful).' % hdr)
681 log.error(introspect_error)
682 log.end_block()
683 elif parse_error:
684 log.start_block('%sSource code parsing failed (but '
685 'introspection was successful).' % hdr)
686 log.error(parse_error)
687 log.end_block()
688
689
690
691
692
693
695 """
696 Used to keep track of progress when generating the initial docs
697 for the given items. (It is not known in advance how many items a
698 package directory will contain, since it might depend on those
699 packages' __path__ values.)
700 """
702 self.est_totals = {}
703 self.complete = 0
704
705 for item in items:
706 if is_package_dir(item):
707 self.est_totals[item] = self._est_pkg_modules(item)
708 else:
709 self.est_totals[item] = 1
710
712 total = sum(self.est_totals.values())
713 return float(self.complete) / total
714
716 del self.est_totals[pkg_item]
717 for item in modules:
718 self.est_totals[item] = 1
719 for item in subpackages:
720 self.est_totals[item] = self._est_pkg_modules(item)
721
734
735
736
737
738
739 MERGE_PRECEDENCE = {
740 'repr': 'parse',
741
742
743
744 'canonical_name': 'introspect',
745
746
747
748
749
750 'is_imported': 'introspect',
751
752
753 'is_alias': 'parse',
754
755
756
757 'docformat': 'parse',
758
759
760
761 'is_package': 'parse',
762
763
764
765 'sort_spec': 'parse',
766
767 'submodules': 'introspect',
768
769
770 'filename': 'parse',
771
772
773
774
775 'docstring': 'introspect',
776 }
777 """Indicates whether information from introspection or parsing should be
778 given precedence, for specific attributes. This dictionary maps from
779 attribute names to either C{'introspect'} or C{'parse'}."""
780
781 DEFAULT_MERGE_PRECEDENCE = 'introspect'
782 """Indicates whether information from introspection or parsing should be
783 given precedence. Should be either C{'introspect'} or C{'parse'}"""
784
785 _attribute_mergefunc_registry = {}
787 """
788 Register an attribute merge function. This function will be
789 called by L{merge_docs()} when it needs to merge the attribute
790 values of two C{APIDoc}s.
791
792 @param attrib: The name of the attribute whose values are merged
793 by C{mergefunc}.
794
795 @param mergefunc: The merge function, whose sinature is:
796
797 >>> def mergefunc(introspect_val, parse_val, precedence, cyclecheck, path):
798 ... return calculate_merged_value(introspect_val, parse_val)
799
800 Where C{introspect_val} and C{parse_val} are the two values to
801 combine; C{precedence} is a string indicating which value takes
802 precedence for this attribute (C{'introspect'} or C{'parse'});
803 C{cyclecheck} is a value used by C{merge_docs()} to make sure that
804 it only visits each pair of docs once; and C{path} is a string
805 describing the path that was taken from the root to this
806 attribute (used to generate log messages).
807
808 If the merge function needs to call C{merge_docs}, then it should
809 pass C{cyclecheck} and C{path} back in. (When appropriate, a
810 suffix should be added to C{path} to describe the path taken to
811 the merged values.)
812 """
813 _attribute_mergefunc_registry[attrib] = mergefunc
814
815 -def merge_docs(introspect_doc, parse_doc, cyclecheck=None, path=None):
816 """
817 Merge the API documentation information that was obtained from
818 introspection with information that was obtained from parsing.
819 C{introspect_doc} and C{parse_doc} should be two C{APIDoc} instances
820 that describe the same object. C{merge_docs} combines the
821 information from these two instances, and returns the merged
822 C{APIDoc}.
823
824 If C{introspect_doc} and C{parse_doc} are compatible, then they will
825 be I{merged} -- i.e., they will be coerced to a common class, and
826 their state will be stored in a shared dictionary. Once they have
827 been merged, any change made to the attributes of one will affect
828 the other. The value for the each of the merged C{APIDoc}'s
829 attributes is formed by combining the values of the source
830 C{APIDoc}s' attributes, as follows:
831
832 - If either of the source attributes' value is C{UNKNOWN}, then
833 use the other source attribute's value.
834 - Otherwise, if an attribute merge function has been registered
835 for the attribute, then use that function to calculate the
836 merged value from the two source attribute values.
837 - Otherwise, if L{MERGE_PRECEDENCE} is defined for the
838 attribute, then use the attribute value from the source that
839 it indicates.
840 - Otherwise, use the attribute value from the source indicated
841 by L{DEFAULT_MERGE_PRECEDENCE}.
842
843 If C{introspect_doc} and C{parse_doc} are I{not} compatible (e.g., if
844 their values have incompatible types), then C{merge_docs()} will
845 simply return either C{introspect_doc} or C{parse_doc}, depending on
846 the value of L{DEFAULT_MERGE_PRECEDENCE}. The two input
847 C{APIDoc}s will not be merged or modified in any way.
848
849 @param cyclecheck, path: These arguments should only be provided
850 when C{merge_docs()} is called by an attribute merge
851 function. See L{register_attribute_mergefunc()} for more
852 details.
853 """
854 assert isinstance(introspect_doc, APIDoc)
855 assert isinstance(parse_doc, APIDoc)
856
857 if cyclecheck is None:
858 cyclecheck = set()
859 if introspect_doc.canonical_name not in (None, UNKNOWN):
860 path = '%s' % introspect_doc.canonical_name
861 elif parse_doc.canonical_name not in (None, UNKNOWN):
862 path = '%s' % parse_doc.canonical_name
863 else:
864 path = '??'
865
866
867
868
869
870 if (id(introspect_doc), id(parse_doc)) in cyclecheck:
871 return introspect_doc
872 cyclecheck.add( (id(introspect_doc), id(parse_doc)) )
873
874
875
876
877 if introspect_doc == parse_doc:
878 return introspect_doc
879
880
881
882
883
884 if type(introspect_doc) == type(parse_doc) == GenericValueDoc:
885 if parse_doc.parse_repr is not UNKNOWN:
886 introspect_doc.parse_repr = parse_doc.parse_repr
887 introspect_doc.docs_extracted_by = 'both'
888 return introspect_doc
889
890
891
892
893 mismatch = None
894 if (introspect_doc.__class__ != parse_doc.__class__ and
895 not (issubclass(introspect_doc.__class__, parse_doc.__class__) or
896 issubclass(parse_doc.__class__, introspect_doc.__class__))):
897 mismatch = ("value types don't match -- i=%r, p=%r." %
898 (introspect_doc.__class__, parse_doc.__class__))
899 if (isinstance(introspect_doc, ValueDoc) and
900 isinstance(parse_doc, ValueDoc)):
901 if (introspect_doc.pyval is not UNKNOWN and
902 parse_doc.pyval is not UNKNOWN and
903 introspect_doc.pyval is not parse_doc.pyval):
904 mismatch = "values don't match."
905 elif (introspect_doc.canonical_name not in (None, UNKNOWN) and
906 parse_doc.canonical_name not in (None, UNKNOWN) and
907 introspect_doc.canonical_name != parse_doc.canonical_name):
908 mismatch = "canonical names don't match."
909 if mismatch is not None:
910 log.info("Not merging the parsed & introspected values of %s, "
911 "since their %s" % (path, mismatch))
912 if DEFAULT_MERGE_PRECEDENCE == 'introspect':
913 return introspect_doc
914 else:
915 return parse_doc
916
917
918
919 if introspect_doc.__class__ is not parse_doc.__class__:
920 if issubclass(introspect_doc.__class__, parse_doc.__class__):
921 parse_doc.specialize_to(introspect_doc.__class__)
922 if issubclass(parse_doc.__class__, introspect_doc.__class__):
923 introspect_doc.specialize_to(parse_doc.__class__)
924 assert introspect_doc.__class__ is parse_doc.__class__
925
926
927
928
929 if (isinstance(introspect_doc, RoutineDoc) and
930 isinstance(parse_doc, RoutineDoc)):
931 _merge_posargs_and_defaults(introspect_doc, parse_doc, path)
932
933
934 for attrib in set(introspect_doc.__dict__.keys() +
935 parse_doc.__dict__.keys()):
936
937
938 if attrib.startswith('_'): continue
939 merge_attribute(attrib, introspect_doc, parse_doc,
940 cyclecheck, path)
941
942
943 return introspect_doc.merge_and_overwrite(parse_doc)
944
967
969 precedence = MERGE_PRECEDENCE.get(attrib, DEFAULT_MERGE_PRECEDENCE)
970 if precedence not in ('parse', 'introspect'):
971 raise ValueError('Bad precedence value %r' % precedence)
972
973 if (getattr(introspect_doc, attrib) is UNKNOWN and
974 getattr(parse_doc, attrib) is not UNKNOWN):
975 setattr(introspect_doc, attrib, getattr(parse_doc, attrib))
976 elif (getattr(introspect_doc, attrib) is not UNKNOWN and
977 getattr(parse_doc, attrib) is UNKNOWN):
978 setattr(parse_doc, attrib, getattr(introspect_doc, attrib))
979 elif (getattr(introspect_doc, attrib) is UNKNOWN and
980 getattr(parse_doc, attrib) is UNKNOWN):
981 pass
982 else:
983
984 introspect_val = getattr(introspect_doc, attrib)
985 parse_val = getattr(parse_doc, attrib)
986 if attrib in _attribute_mergefunc_registry:
987 handler = _attribute_mergefunc_registry[attrib]
988 merged_val = handler(introspect_val, parse_val, precedence,
989 cyclecheck, path)
990 elif precedence == 'introspect':
991 merged_val = introspect_val
992 elif precedence == 'parse':
993 merged_val = parse_val
994
995 setattr(introspect_doc, attrib, merged_val)
996 setattr(parse_doc, attrib, merged_val)
997
999
1000 for varname, var1 in varlist1.items():
1001 var2 = varlist2.get(varname)
1002 if var2 is not None:
1003 var = merge_docs(var1, var2, cyclecheck, path+'.'+varname)
1004 varlist1[varname] = var
1005 varlist2[varname] = var
1006
1007
1008 for varname, var in varlist2.items():
1009 varlist1.setdefault(varname, var)
1010
1011 return varlist1
1012
1013 -def merge_value(value1, value2, precedence, cyclecheck, path):
1014 assert value1 is not None and value2 is not None
1015 return merge_docs(value1, value2, cyclecheck, path)
1016
1018 return merge_value(v1, v2, precedence, cyclecheck, path+'.<overrides>')
1019 -def merge_fget(v1, v2, precedence, cyclecheck, path):
1021 -def merge_fset(v1, v2, precedence, cyclecheck, path):
1023 -def merge_fdel(v1, v2, precedence, cyclecheck, path):
1025
1030
1031 -def merge_bases(baselist1, baselist2, precedence, cyclecheck, path):
1032
1033
1034
1035
1036
1037
1038
1039
1040 if len(baselist1) != len(baselist2):
1041 log.info("Not merging the introspected & parsed base lists "
1042 "for %s, since their lengths don't match (%s vs %s)" %
1043 (path, len(baselist1), len(baselist2)))
1044 if precedence == 'introspect': return baselist1
1045 else: return baselist2
1046
1047
1048 for base1, base2 in zip(baselist1, baselist2):
1049 if ((base1.canonical_name not in (None, UNKNOWN) and
1050 base2.canonical_name not in (None, UNKNOWN)) and
1051 base1.canonical_name != base2.canonical_name):
1052 log.info("Not merging the parsed & introspected base "
1053 "lists for %s, since the bases' names don't match "
1054 "(%s vs %s)" % (path, base1.canonical_name,
1055 base2.canonical_name))
1056 if precedence == 'introspect': return baselist1
1057 else: return baselist2
1058
1059 for i, (base1, base2) in enumerate(zip(baselist1, baselist2)):
1060 base = merge_docs(base1, base2, cyclecheck,
1061 '%s.__bases__[%d]' % (path, i))
1062 baselist1[i] = baselist2[i] = base
1063
1064 return baselist1
1065
1067 if len(defaults1) != len(defaults2):
1068 if precedence == 'introspect': return defaults1
1069 else: return defaults2
1070 defaults = []
1071 for i, (d1, d2) in enumerate(zip(defaults1, defaults2)):
1072 if d1 is not None and d2 is not None:
1073 d_path = '%s.<default-arg-val>[%d]' % (path, i)
1074 defaults.append(merge_docs(d1, d2, cyclecheck, d_path))
1075 elif precedence == 'introspect':
1076 defaults.append(d1)
1077 else:
1078 defaults.append(d2)
1079 return defaults
1080
1081 -def merge_docstring(docstring1, docstring2, precedence, cyclecheck, path):
1082 if docstring1 is None or docstring1 is UNKNOWN or precedence=='parse':
1083 return docstring2
1084 else:
1085 return docstring1
1086
1089
1091 n1 = sorted([m.canonical_name for m in v1])
1092 n2 = sorted([m.canonical_name for m in v2])
1093 if (n1 != n2) and (n2 != []):
1094 log.info('Introspector & parser disagree about submodules '
1095 'for %s: (%s) vs (%s)' % (path,
1096 ', '.join([str(n) for n in n1]),
1097 ', '.join([str(n) for n in n2])))
1098 return v1 + [m for m in v2 if m.canonical_name not in n1]
1099
1100 return v1
1101
1102 register_attribute_mergefunc('variables', merge_variables)
1103 register_attribute_mergefunc('value', merge_value)
1104 register_attribute_mergefunc('overrides', merge_overrides)
1105 register_attribute_mergefunc('fget', merge_fget)
1106 register_attribute_mergefunc('fset', merge_fset)
1107 register_attribute_mergefunc('fdel', merge_fdel)
1108 register_attribute_mergefunc('proxy_for', merge_proxy_for)
1109 register_attribute_mergefunc('bases', merge_bases)
1110 register_attribute_mergefunc('posarg_defaults', merge_posarg_defaults)
1111 register_attribute_mergefunc('docstring', merge_docstring)
1112 register_attribute_mergefunc('docs_extracted_by', merge_docs_extracted_by)
1113 register_attribute_mergefunc('submodules', merge_submodules)
1114
1115
1116
1117
1118
1156
1157
1158
1159
1160
1161 _name_scores = {}
1162 """A dictionary mapping from each C{ValueDoc} to the score that has
1163 been assigned to its current cannonical name. If
1164 L{assign_canonical_names()} finds a canonical name with a better
1165 score, then it will replace the old name."""
1166
1167 _unreachable_names = {DottedName(DottedName.UNREACHABLE):1}
1168 """The set of names that have been used for unreachable objects. This
1169 is used to ensure there are no duplicate cannonical names assigned.
1170 C{_unreachable_names} is a dictionary mapping from dotted names to
1171 integer ids, where the next unused unreachable name derived from
1172 dotted name C{n} is
1173 C{DottedName('%s-%s' % (n, str(_unreachable_names[n]+1))}"""
1174
1176 """
1177 Assign a canonical name to C{val_doc} (if it doesn't have one
1178 already), and (recursively) to each variable in C{val_doc}.
1179 In particular, C{val_doc} will be assigned the canonical name
1180 C{name} iff either:
1181 - C{val_doc}'s canonical name is C{UNKNOWN}; or
1182 - C{val_doc}'s current canonical name was assigned by this
1183 method; but the score of the new name (C{score}) is higher
1184 than the score of the current name (C{score_dict[val_doc]}).
1185
1186 Note that canonical names will even be assigned to values
1187 like integers and C{None}; but these should be harmless.
1188 """
1189
1190
1191
1192
1193 if val_doc in _name_scores and score <= _name_scores[val_doc]:
1194 return
1195
1196
1197 if (val_doc not in _name_scores and
1198 val_doc.canonical_name is not UNKNOWN):
1199
1200
1201 _name_scores[val_doc] = sys.maxint
1202 name = val_doc.canonical_name
1203 score = 0
1204 else:
1205
1206
1207 if (val_doc not in _name_scores or
1208 score > _name_scores[val_doc]):
1209 val_doc.canonical_name = name
1210 _name_scores[val_doc] = score
1211
1212
1213 if isinstance(val_doc, NamespaceDoc):
1214 for var_doc in val_doc.variables.values():
1215
1216 varname = DottedName(name, var_doc.name)
1217 var_doc.canonical_name = varname
1218
1219
1220
1221 if (var_doc.value is UNKNOWN
1222 or isinstance(var_doc.value, GenericValueDoc)):
1223 continue
1224
1225
1226
1227
1228
1229 if _var_shadows_self(var_doc, varname):
1230 _fix_self_shadowing_var(var_doc, varname, docindex)
1231
1232
1233 vardoc_score = score-1
1234 if var_doc.is_imported is UNKNOWN: vardoc_score -= 10
1235 elif var_doc.is_imported: vardoc_score -= 100
1236 if var_doc.is_alias is UNKNOWN: vardoc_score -= 10
1237 elif var_doc.is_alias: vardoc_score -= 1000
1238
1239 assign_canonical_names(var_doc.value, varname,
1240 docindex, vardoc_score)
1241
1242
1243 for val_doc_2 in val_doc.apidoc_links(variables=False):
1244 val_name, val_score = _unreachable_name_for(val_doc_2, docindex)
1245 assign_canonical_names(val_doc_2, val_name, docindex, val_score)
1246
1252
1269
1304
1305
1306
1307
1308
1310 """
1311 Set the C{overrides} attribute for all variables in C{class_doc}.
1312 This needs to be done early (before docstring parsing), so we can
1313 know which docstrings to suppress warnings for.
1314 """
1315 for base_class in list(class_doc.mro(warn_about_bad_bases=True)):
1316 if base_class == class_doc: continue
1317 if base_class.variables is UNKNOWN: continue
1318 for name, var_doc in base_class.variables.items():
1319 if ( not (name.startswith('__') and not name.endswith('__')) and
1320 base_class == var_doc.container and
1321 name in class_doc.variables and
1322 class_doc.variables[name].container==class_doc and
1323 class_doc.variables[name].overrides is UNKNOWN ):
1324 class_doc.variables[name].overrides = var_doc
1325
1326
1364
1365 _INHERITED_ATTRIBS = [
1366 'descr', 'summary', 'metadata', 'extra_docstring_fields',
1367 'type_descr', 'arg_descrs', 'arg_types', 'return_descr',
1368 'return_type', 'exception_descrs']
1369
1370 _method_descriptor = type(list.append)
1371
1373 """
1374 Copy any relevant documentation information from the variable that
1375 C{var_doc} overrides into C{var_doc} itself.
1376 """
1377 src_var = var_doc.overrides
1378 src_val = var_doc.overrides.value
1379 val_doc = var_doc.value
1380
1381
1382
1383
1384 if (isinstance(val_doc, RoutineDoc) and
1385 isinstance(src_val, RoutineDoc) and
1386 (inspect.isbuiltin(val_doc.pyval) or
1387 isinstance(val_doc.pyval, _method_descriptor)) and
1388 (inspect.isbuiltin(src_val.pyval) or
1389 isinstance(src_val.pyval, _method_descriptor)) and
1390 val_doc.all_args() in (['...'], UNKNOWN) and
1391 src_val.all_args() not in (['...'], UNKNOWN)):
1392 for attrib in ['posargs', 'posarg_defaults', 'vararg',
1393 'kwarg', 'return_type']:
1394 setattr(val_doc, attrib, getattr(src_val, attrib))
1395
1396
1397
1398 if var_doc.docstring not in (None, UNKNOWN):
1399 return
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414 for attrib in _INHERITED_ATTRIBS:
1415 if (hasattr(var_doc, attrib) and hasattr(src_var, attrib) and
1416 getattr(src_var, attrib) not in (None, UNKNOWN)):
1417 setattr(var_doc, attrib, getattr(src_var, attrib))
1418 elif (src_val is not None and
1419 hasattr(val_doc, attrib) and hasattr(src_val, attrib) and
1420 getattr(src_val, attrib) not in (None, UNKNOWN) and
1421 getattr(val_doc, attrib) in (None, UNKNOWN, [])):
1422 setattr(val_doc, attrib, getattr(src_val, attrib))
1423