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
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:
202 return None
203
204
205 doc_pairs = _get_docs_from_items(items, options)
206
207
208 if options.parse and options.introspect:
209 log.start_progress('Merging parsed & introspected information')
210 docs = []
211 for i, (introspect_doc, parse_doc) in enumerate(doc_pairs):
212 if introspect_doc is not None and parse_doc is not None:
213 if introspect_doc.canonical_name not in (None, UNKNOWN):
214 name = introspect_doc.canonical_name
215 else:
216 name = parse_doc.canonical_name
217 log.progress(float(i)/len(doc_pairs), name)
218 docs.append(merge_docs(introspect_doc, parse_doc))
219 elif introspect_doc is not None:
220 docs.append(introspect_doc)
221 elif parse_doc is not None:
222 docs.append(parse_doc)
223 log.end_progress()
224 elif options.introspect:
225 docs = [doc_pair[0] for doc_pair in doc_pairs if doc_pair[0]]
226 else:
227 docs = [doc_pair[1] for doc_pair in doc_pairs if doc_pair[1]]
228
229 if len(docs) == 0:
230 log.error('Nothing left to document!')
231 return None
232
233
234 docindex = DocIndex(docs)
235
236
237
238 if options.parse:
239 log.start_progress('Linking imported variables')
240 valdocs = sorted(docindex.reachable_valdocs(
241 imports=False, submodules=False, packages=False, subclasses=False))
242 for i, val_doc in enumerate(valdocs):
243 _report_valdoc_progress(i, val_doc, valdocs)
244 link_imports(val_doc, docindex)
245 log.end_progress()
246
247
248 log.start_progress('Indexing documentation')
249 for i, val_doc in enumerate(docindex.root):
250 log.progress(float(i)/len(docindex.root), val_doc.canonical_name)
251 assign_canonical_names(val_doc, val_doc.canonical_name, docindex)
252 log.end_progress()
253
254
255 log.start_progress('Parsing docstrings')
256 valdocs = sorted(docindex.reachable_valdocs(
257 imports=False, submodules=False, packages=False, subclasses=False))
258 for i, val_doc in enumerate(valdocs):
259 _report_valdoc_progress(i, val_doc, valdocs)
260
261 parse_docstring(val_doc, docindex)
262
263 if (isinstance(val_doc, NamespaceDoc) and
264 val_doc.variables not in (None, UNKNOWN)):
265 for var_doc in val_doc.variables.values():
266
267
268
269 if (isinstance(var_doc.value, ValueDoc)
270 and var_doc.value.defining_module is UNKNOWN):
271 var_doc.value.defining_module = val_doc.defining_module
272 parse_docstring(var_doc, docindex)
273 log.end_progress()
274
275
276 log.start_progress('Inheriting documentation')
277 for i, val_doc in enumerate(valdocs):
278 if isinstance(val_doc, ClassDoc):
279 percent = float(i)/len(valdocs)
280 log.progress(percent, val_doc.canonical_name)
281 inherit_docs(val_doc)
282 log.end_progress()
283
284
285 log.start_progress('Sorting & Grouping')
286 for i, val_doc in enumerate(valdocs):
287 if isinstance(val_doc, NamespaceDoc):
288 percent = float(i)/len(valdocs)
289 log.progress(percent, val_doc.canonical_name)
290 val_doc.init_sorted_variables()
291 val_doc.init_variable_groups()
292 if isinstance(val_doc, ModuleDoc):
293 val_doc.init_submodule_groups()
294 log.end_progress()
295
296 return docindex
297
303
304
305
306
307
309
310
311 log.start_progress('Building documentation')
312 progress_estimator = _ProgressEstimator(items)
313
314
315 item_set = set()
316 for item in items[:]:
317 if item in item_set:
318 log.warning("Name %r given multiple times" % item)
319 items.remove(item)
320 item_set.add(item)
321
322
323
324
325
326 canonical_names = {}
327
328
329 doc_pairs = []
330 for item in items:
331 if isinstance(item, basestring):
332 if is_module_file(item):
333 doc_pairs.append(_get_docs_from_module_file(
334 item, options, progress_estimator))
335 elif is_package_dir(item):
336 pkgfile = os.path.abspath(os.path.join(item, '__init__'))
337 doc_pairs.append(_get_docs_from_module_file(
338 pkgfile, options, progress_estimator))
339 elif os.path.isfile(item):
340 doc_pairs.append(_get_docs_from_pyscript(
341 item, options, progress_estimator))
342 elif hasattr(__builtin__, item):
343 val = getattr(__builtin__, item)
344 doc_pairs.append(_get_docs_from_pyobject(
345 val, options, progress_estimator))
346 elif is_pyname(item):
347 doc_pairs.append(_get_docs_from_pyname(
348 item, options, progress_estimator))
349 elif os.path.isdir(item):
350 log.error("Directory %r is not a package" % item)
351 continue
352 elif os.path.isfile(item):
353 log.error("File %s is not a Python module" % item)
354 continue
355 else:
356 log.error("Could not find a file or object named %s" %
357 item)
358 continue
359 else:
360 doc_pairs.append(_get_docs_from_pyobject(
361 item, options, progress_estimator))
362
363
364 name = (getattr(doc_pairs[-1][0], 'canonical_name', None) or
365 getattr(doc_pairs[-1][1], 'canonical_name', None))
366 if name in canonical_names:
367 log.error(
368 'Two of the specified items, %r and %r, have the same '
369 'canonical name ("%s"). This may mean that you specified '
370 'two different files that both use the same module name. '
371 'Ignoring the second item (%r)' %
372 (canonical_names[name], item, name, canonical_names[name]))
373 doc_pairs.pop()
374 else:
375 canonical_names[name] = item
376
377
378
379
380
381 if options.add_submodules and not is_module_file(item):
382 doc_pairs += _get_docs_from_submodules(
383 item, doc_pairs[-1], options, progress_estimator)
384
385 log.end_progress()
386 return doc_pairs
387
389 progress_estimator.complete += 1
390 log.progress(progress_estimator.progress(), repr(obj))
391
392 if not options.introspect:
393 log.error("Cannot get docs for Python objects without "
394 "introspecting them.")
395
396 introspect_doc = parse_doc = None
397 introspect_error = parse_error = None
398 try:
399 introspect_doc = introspect_docs(value=obj)
400 except ImportError, e:
401 log.error(e)
402 return (None, None)
403 if options.parse:
404 if introspect_doc.canonical_name is not None:
405 prev_introspect = options.introspect
406 options.introspect = False
407 try:
408 _, parse_docs = _get_docs_from_pyname(
409 str(introspect_doc.canonical_name), options,
410 progress_estimator, supress_warnings=True)
411 finally:
412 options.introspect = prev_introspect
413
414
415 if introspect_doc.canonical_name in (None, UNKNOWN):
416 if hasattr(obj, '__name__'):
417 introspect_doc.canonical_name = DottedName(
418 DottedName.UNREACHABLE, obj.__name__)
419 else:
420 introspect_doc.canonical_name = DottedName(
421 DottedName.UNREACHABLE)
422 return (introspect_doc, parse_doc)
423
454
456
457
458
459 introspect_doc = parse_doc = None
460 introspect_error = parse_error = None
461 if options.introspect:
462 try:
463 introspect_doc = introspect_docs(filename=filename, is_script=True)
464 if introspect_doc.canonical_name is UNKNOWN:
465 introspect_doc.canonical_name = munge_script_name(filename)
466 except ImportError, e:
467 introspect_error = str(e)
468 if options.parse:
469 try:
470 parse_doc = parse_docs(filename=filename, is_script=True)
471 except ParseError, e:
472 parse_error = str(e)
473 except ImportError, e:
474 parse_error = str(e)
475
476
477 _report_errors(filename, introspect_doc, parse_doc,
478 introspect_error, parse_error)
479
480
481 return (introspect_doc, parse_doc)
482
485 """
486 Construct and return the API documentation for the python
487 module with the given filename.
488
489 @param parent_docs: The C{ModuleDoc} of the containing package.
490 If C{parent_docs} is not provided, then this method will
491 check if the given filename is contained in a package; and
492 if so, it will construct a stub C{ModuleDoc} for the
493 containing package(s). C{parent_docs} is a tuple, where
494 the first element is the parent from introspection, and
495 the second element is the parent from parsing.
496 """
497
498 modulename = os.path.splitext(os.path.split(filename)[1])[0]
499 if modulename == '__init__':
500 modulename = os.path.split(os.path.split(filename)[0])[1]
501 if parent_docs[0]:
502 modulename = DottedName(parent_docs[0].canonical_name, modulename)
503 elif parent_docs[1]:
504 modulename = DottedName(parent_docs[1].canonical_name, modulename)
505 if options.must_introspect(modulename) or options.must_parse(modulename):
506 log.progress(progress_estimator.progress(),
507 '%s (%s)' % (modulename, filename))
508 progress_estimator.complete += 1
509
510
511 filename = os.path.normpath(os.path.abspath(filename))
512
513
514 try:
515 filename = py_src_filename(filename)
516 src_file_available = True
517 except ValueError:
518 src_file_available = False
519
520
521 introspect_doc = parse_doc = None
522 introspect_error = parse_error = None
523 if options.must_introspect(modulename):
524 try:
525 introspect_doc = introspect_docs(
526 filename=filename, context=parent_docs[0])
527 if introspect_doc.canonical_name is UNKNOWN:
528 introspect_doc.canonical_name = modulename
529 except ImportError, e:
530 introspect_error = str(e)
531 if src_file_available and options.must_parse(modulename):
532 try:
533 parse_doc = parse_docs(
534 filename=filename, context=parent_docs[1])
535 except ParseError, e:
536 parse_error = str(e)
537 except ImportError, e:
538 parse_error = str(e)
539
540
541 _report_errors(filename, introspect_doc, parse_doc,
542 introspect_error, parse_error)
543
544
545 return (introspect_doc, parse_doc)
546
548
549 if isinstance(pkg_docs[0], ModuleDoc) and pkg_docs[0].is_package:
550 pkg_path = pkg_docs[0].path
551 package_dir = os.path.split(pkg_docs[0].filename)[0]
552 elif isinstance(pkg_docs[1], ModuleDoc) and pkg_docs[1].is_package:
553 pkg_path = pkg_docs[1].path
554 package_dir = os.path.split(pkg_docs[1].filename)[0]
555 else:
556 return []
557
558 module_filenames = {}
559 subpackage_dirs = set()
560 for subdir in pkg_path:
561 if os.path.isdir(subdir):
562 for name in os.listdir(subdir):
563 filename = os.path.join(subdir, name)
564
565 if is_module_file(filename):
566 basename = os.path.splitext(filename)[0]
567 if os.path.split(basename)[1] != '__init__':
568 module_filenames[basename] = filename
569
570 if is_package_dir(filename):
571 subpackage_dirs.add(filename)
572
573
574 progress_estimator.revise_estimate(item, module_filenames.items(),
575 subpackage_dirs)
576
577 docs = [pkg_docs]
578 for module_filename in module_filenames.values():
579 d = _get_docs_from_module_file(
580 module_filename, options, progress_estimator, pkg_docs)
581 docs.append(d)
582 for subpackage_dir in subpackage_dirs:
583 subpackage_file = os.path.join(subpackage_dir, '__init__')
584 docs.append(_get_docs_from_module_file(
585 subpackage_file, options, progress_estimator, pkg_docs))
586 docs += _get_docs_from_submodules(
587 subpackage_dir, docs[-1], options, progress_estimator)
588 return docs
589
590 -def _report_errors(name, introspect_doc, parse_doc,
591 introspect_error, parse_error):
592 hdr = 'In %s:\n' % name
593 if introspect_doc == parse_doc == None:
594 log.start_block('%sNo documentation available!' % hdr)
595 if introspect_error:
596 log.error('Import failed:\n%s' % introspect_error)
597 if parse_error:
598 log.error('Source code parsing failed:\n%s' % parse_error)
599 log.end_block()
600 elif introspect_error:
601 log.start_block('%sImport failed (but source code parsing '
602 'was successful).' % hdr)
603 log.error(introspect_error)
604 log.end_block()
605 elif parse_error:
606 log.start_block('%sSource code parsing failed (but '
607 'introspection was successful).' % hdr)
608 log.error(parse_error)
609 log.end_block()
610
611
612
613
614
615
617 """
618 Used to keep track of progress when generating the initial docs
619 for the given items. (It is not known in advance how many items a
620 package directory will contain, since it might depend on those
621 packages' __path__ values.)
622 """
624 self.est_totals = {}
625 self.complete = 0
626
627 for item in items:
628 if is_package_dir(item):
629 self.est_totals[item] = self._est_pkg_modules(item)
630 else:
631 self.est_totals[item] = 1
632
634 total = sum(self.est_totals.values())
635 return float(self.complete) / total
636
638 del self.est_totals[pkg_item]
639 for item in modules:
640 self.est_totals[item] = 1
641 for item in subpackages:
642 self.est_totals[item] = self._est_pkg_modules(item)
643
656
657
658
659
660
661 MERGE_PRECEDENCE = {
662 'repr': 'parse',
663
664
665 'canonical_name': 'introspect',
666
667
668
669
670
671 'is_imported': 'introspect',
672
673
674 'is_alias': 'parse',
675
676
677 'docformat': 'parse',
678
679
680
681 'is_package': 'parse',
682
683
684
685 'sort_spec': 'parse',
686
687 'submodules': 'introspect',
688
689
690 'filename': 'parse',
691
692
693
694
695 'docstring': 'introspect',
696 }
697 """Indicates whether information from introspection or parsing should be
698 given precedence, for specific attributes. This dictionary maps from
699 attribute names to either C{'introspect'} or C{'parse'}."""
700
701 DEFAULT_MERGE_PRECEDENCE = 'introspect'
702 """Indicates whether information from introspection or parsing should be
703 given precedence. Should be either C{'introspect'} or C{'parse'}"""
704
705 _attribute_mergefunc_registry = {}
707 """
708 Register an attribute merge function. This function will be
709 called by L{merge_docs()} when it needs to merge the attribute
710 values of two C{APIDoc}s.
711
712 @param attrib: The name of the attribute whose values are merged
713 by C{mergefunc}.
714
715 @param mergefunc: The merge function, whose sinature is:
716
717 >>> def mergefunc(introspect_val, parse_val, precedence, cyclecheck, path):
718 ... return calculate_merged_value(introspect_val, parse_val)
719
720 Where C{introspect_val} and C{parse_val} are the two values to
721 combine; C{precedence} is a string indicating which value takes
722 precedence for this attribute (C{'introspect'} or C{'parse'});
723 C{cyclecheck} is a value used by C{merge_docs()} to make sure that
724 it only visits each pair of docs once; and C{path} is a string
725 describing the path that was taken from the root to this
726 attribute (used to generate log messages).
727
728 If the merge function needs to call C{merge_docs}, then it should
729 pass C{cyclecheck} and C{path} back in. (When appropriate, a
730 suffix should be added to C{path} to describe the path taken to
731 the merged values.)
732 """
733 _attribute_mergefunc_registry[attrib] = mergefunc
734
735 -def merge_docs(introspect_doc, parse_doc, cyclecheck=None, path=None):
736 """
737 Merge the API documentation information that was obtained from
738 introspection with information that was obtained from parsing.
739 C{introspect_doc} and C{parse_doc} should be two C{APIDoc} instances
740 that describe the same object. C{merge_docs} combines the
741 information from these two instances, and returns the merged
742 C{APIDoc}.
743
744 If C{introspect_doc} and C{parse_doc} are compatible, then they will
745 be I{merged} -- i.e., they will be coerced to a common class, and
746 their state will be stored in a shared dictionary. Once they have
747 been merged, any change made to the attributes of one will affect
748 the other. The value for the each of the merged C{APIDoc}'s
749 attributes is formed by combining the values of the source
750 C{APIDoc}s' attributes, as follows:
751
752 - If either of the source attributes' value is C{UNKNOWN}, then
753 use the other source attribute's value.
754 - Otherwise, if an attribute merge function has been registered
755 for the attribute, then use that function to calculate the
756 merged value from the two source attribute values.
757 - Otherwise, if L{MERGE_PRECEDENCE} is defined for the
758 attribute, then use the attribute value from the source that
759 it indicates.
760 - Otherwise, use the attribute value from the source indicated
761 by L{DEFAULT_MERGE_PRECEDENCE}.
762
763 If C{introspect_doc} and C{parse_doc} are I{not} compatible (e.g., if
764 their values have incompatible types), then C{merge_docs()} will
765 simply return either C{introspect_doc} or C{parse_doc}, depending on
766 the value of L{DEFAULT_MERGE_PRECEDENCE}. The two input
767 C{APIDoc}s will not be merged or modified in any way.
768
769 @param cyclecheck, path: These arguments should only be provided
770 when C{merge_docs()} is called by an attribute merge
771 function. See L{register_attribute_mergefunc()} for more
772 details.
773 """
774 assert isinstance(introspect_doc, APIDoc)
775 assert isinstance(parse_doc, APIDoc)
776
777 if cyclecheck is None:
778 cyclecheck = set()
779 if introspect_doc.canonical_name not in (None, UNKNOWN):
780 path = '%s' % introspect_doc.canonical_name
781 elif parse_doc.canonical_name not in (None, UNKNOWN):
782 path = '%s' % parse_doc.canonical_name
783 else:
784 path = '??'
785
786
787
788
789
790 if (id(introspect_doc), id(parse_doc)) in cyclecheck:
791 return introspect_doc
792 cyclecheck.add( (id(introspect_doc), id(parse_doc)) )
793
794
795
796
797 if introspect_doc == parse_doc:
798 return introspect_doc
799
800
801
802
803 if type(introspect_doc) == type(parse_doc) == GenericValueDoc:
804 if introspect_doc.pyval is not UNKNOWN:
805 parse_doc.pyval = introspect_doc.pyval
806 if introspect_doc.parse_repr is not UNKNOWN:
807 parse_doc.parse_repr = introspect_doc.parse_repr
808 parse_doc.docs_extracted_by = 'both'
809 return parse_doc.merge_and_overwrite(introspect_doc)
810
811
812
813
814 mismatch = None
815 if (introspect_doc.__class__ != parse_doc.__class__ and
816 not (issubclass(introspect_doc.__class__, parse_doc.__class__) or
817 issubclass(parse_doc.__class__, introspect_doc.__class__))):
818 mismatch = ("value types don't match -- i=%r, p=%r." %
819 (introspect_doc.__class__, parse_doc.__class__))
820 if (isinstance(introspect_doc, ValueDoc) and
821 isinstance(parse_doc, ValueDoc)):
822 if (introspect_doc.pyval is not UNKNOWN and
823 parse_doc.pyval is not UNKNOWN and
824 introspect_doc.pyval is not parse_doc.pyval):
825 mismatch = "values don't match."
826 elif (introspect_doc.canonical_name not in (None, UNKNOWN) and
827 parse_doc.canonical_name not in (None, UNKNOWN) and
828 introspect_doc.canonical_name != parse_doc.canonical_name):
829 mismatch = "canonical names don't match."
830 if mismatch is not None:
831 log.info("Not merging the parsed & introspected values of %s, "
832 "since their %s" % (path, mismatch))
833 if DEFAULT_MERGE_PRECEDENCE == 'introspect':
834 return introspect_doc
835 else:
836 return parse_doc
837
838
839
840 if introspect_doc.__class__ is not parse_doc.__class__:
841 if issubclass(introspect_doc.__class__, parse_doc.__class__):
842 parse_doc.specialize_to(introspect_doc.__class__)
843 if issubclass(parse_doc.__class__, introspect_doc.__class__):
844 introspect_doc.specialize_to(parse_doc.__class__)
845 assert introspect_doc.__class__ is parse_doc.__class__
846
847
848
849
850 if (isinstance(introspect_doc, RoutineDoc) and
851 isinstance(parse_doc, RoutineDoc)):
852 _merge_posargs_and_defaults(introspect_doc, parse_doc, path)
853
854
855 for attrib in set(introspect_doc.__dict__.keys() +
856 parse_doc.__dict__.keys()):
857
858
859 if attrib.startswith('_'): continue
860 merge_attribute(attrib, introspect_doc, parse_doc,
861 cyclecheck, path)
862
863
864 return introspect_doc.merge_and_overwrite(parse_doc)
865
888
890 precedence = MERGE_PRECEDENCE.get(attrib, DEFAULT_MERGE_PRECEDENCE)
891 if precedence not in ('parse', 'introspect'):
892 raise ValueError('Bad precedence value %r' % precedence)
893
894 if (getattr(introspect_doc, attrib) is UNKNOWN and
895 getattr(parse_doc, attrib) is not UNKNOWN):
896 setattr(introspect_doc, attrib, getattr(parse_doc, attrib))
897 elif (getattr(introspect_doc, attrib) is not UNKNOWN and
898 getattr(parse_doc, attrib) is UNKNOWN):
899 setattr(parse_doc, attrib, getattr(introspect_doc, attrib))
900 elif (getattr(introspect_doc, attrib) is UNKNOWN and
901 getattr(parse_doc, attrib) is UNKNOWN):
902 pass
903 else:
904
905 introspect_val = getattr(introspect_doc, attrib)
906 parse_val = getattr(parse_doc, attrib)
907 if attrib in _attribute_mergefunc_registry:
908 handler = _attribute_mergefunc_registry[attrib]
909 merged_val = handler(introspect_val, parse_val, precedence,
910 cyclecheck, path)
911 elif precedence == 'introspect':
912 merged_val = introspect_val
913 elif precedence == 'parse':
914 merged_val = parse_val
915
916 setattr(introspect_doc, attrib, merged_val)
917 setattr(parse_doc, attrib, merged_val)
918
920
921 for varname, var1 in varlist1.items():
922 var2 = varlist2.get(varname)
923 if var2 is not None:
924 var = merge_docs(var1, var2, cyclecheck, path+'.'+varname)
925 varlist1[varname] = var
926 varlist2[varname] = var
927
928
929 for varname, var in varlist2.items():
930 varlist1.setdefault(varname, var)
931
932 return varlist1
933
934 -def merge_value(value1, value2, precedence, cyclecheck, path):
935 assert value1 is not None and value2 is not None
936 return merge_docs(value1, value2, cyclecheck, path)
937
938
940 if v1 is None or v2 is None:
941 if precedence == 'introspect': return v1
942 else: return v2
943 return merge_value(v1, v2, precedence, cyclecheck, path+'.<package>')
945 if v1 is None or v2 is None:
946 if precedence == 'introspect': return v1
947 else: return v2
948 return merge_value(v1, v2, precedence, cyclecheck, path+'.<container>')
950 return merge_value(v1, v2, precedence, cyclecheck, path+'.<overrides>')
951 -def merge_fget(v1, v2, precedence, cyclecheck, path):
953 -def merge_fset(v1, v2, precedence, cyclecheck, path):
955 -def merge_fdel(v1, v2, precedence, cyclecheck, path):
957
962
963 -def merge_bases(baselist1, baselist2, precedence, cyclecheck, path):
964
965
966
967
968
969
970
971
972 if len(baselist1) != len(baselist2):
973 log.info("Not merging the introspected & parsed base lists "
974 "for %s, since their lengths don't match (%s vs %s)" %
975 (path, len(baselist1), len(baselist2)))
976 if precedence == 'introspect': return baselist1
977 else: return baselist2
978
979
980 for base1, base2 in zip(baselist1, baselist2):
981 if ((base1.canonical_name not in (None, UNKNOWN) and
982 base2.canonical_name not in (None, UNKNOWN)) and
983 base1.canonical_name != base2.canonical_name):
984 log.info("Not merging the parsed & introspected base "
985 "lists for %s, since the bases' names don't match "
986 "(%s vs %s)" % (path, base1.canonical_name,
987 base2.canonical_name))
988 if precedence == 'introspect': return baselist1
989 else: return baselist2
990
991 for i, (base1, base2) in enumerate(zip(baselist1, baselist2)):
992 base = merge_docs(base1, base2, cyclecheck,
993 '%s.__bases__[%d]' % (path, i))
994 baselist1[i] = baselist2[i] = base
995
996 return baselist1
997
999 if len(defaults1) != len(defaults2):
1000 if precedence == 'introspect': return defaults1
1001 else: return defaults2
1002 defaults = []
1003 for i, (d1, d2) in enumerate(zip(defaults1, defaults2)):
1004 if d1 is not None and d2 is not None:
1005 d_path = '%s.<default-arg-val>[%d]' % (path, i)
1006 defaults.append(merge_docs(d1, d2, cyclecheck, d_path))
1007 elif precedence == 'introspect':
1008 defaults.append(d1)
1009 else:
1010 defaults.append(d2)
1011 return defaults
1012
1013 -def merge_docstring(docstring1, docstring2, precedence, cyclecheck, path):
1014 if docstring1 is None or docstring1 is UNKNOWN or precedence=='parse':
1015 return docstring2
1016 else:
1017 return docstring1
1018
1021
1022 register_attribute_mergefunc('variables', merge_variables)
1023 register_attribute_mergefunc('value', merge_value)
1024
1025
1026
1027 register_attribute_mergefunc('overrides', merge_overrides)
1028 register_attribute_mergefunc('fget', merge_fget)
1029 register_attribute_mergefunc('fset', merge_fset)
1030 register_attribute_mergefunc('fdel', merge_fdel)
1031 register_attribute_mergefunc('proxy_for', merge_proxy_for)
1032 register_attribute_mergefunc('bases', merge_bases)
1033 register_attribute_mergefunc('posarg_defaults', merge_posarg_defaults)
1034 register_attribute_mergefunc('docstring', merge_docstring)
1035 register_attribute_mergefunc('docs_extracted_by', merge_docs_extracted_by)
1036
1037
1038
1039
1040
1078
1079
1080
1081
1082
1083 _name_scores = {}
1084 """A dictionary mapping from each C{ValueDoc} to the score that has
1085 been assigned to its current cannonical name. If
1086 L{assign_canonical_names()} finds a canonical name with a better
1087 score, then it will replace the old name."""
1088
1089 _unreachable_names = {DottedName(DottedName.UNREACHABLE):1}
1090 """The set of names that have been used for unreachable objects. This
1091 is used to ensure there are no duplicate cannonical names assigned.
1092 C{_unreachable_names} is a dictionary mapping from dotted names to
1093 integer ids, where the next unused unreachable name derived from
1094 dotted name C{n} is
1095 C{DottedName('%s-%s' % (n, str(_unreachable_names[n]+1))}"""
1096
1098 """
1099 Assign a canonical name to C{val_doc} (if it doesn't have one
1100 already), and (recursively) to each variable in C{val_doc}.
1101 In particular, C{val_doc} will be assigned the canonical name
1102 C{name} iff either:
1103 - C{val_doc}'s canonical name is C{UNKNOWN}; or
1104 - C{val_doc}'s current canonical name was assigned by this
1105 method; but the score of the new name (C{score}) is higher
1106 than the score of the current name (C{score_dict[val_doc]}).
1107
1108 Note that canonical names will even be assigned to values
1109 like integers and C{None}; but these should be harmless.
1110 """
1111
1112
1113
1114
1115 if val_doc in _name_scores and score <= _name_scores[val_doc]:
1116 return
1117
1118
1119 if (val_doc not in _name_scores and
1120 val_doc.canonical_name is not UNKNOWN):
1121
1122
1123 _name_scores[val_doc] = sys.maxint
1124 name = val_doc.canonical_name
1125 score = 0
1126 else:
1127
1128
1129 if (val_doc not in _name_scores or
1130 score > _name_scores[val_doc]):
1131 val_doc.canonical_name = name
1132 _name_scores[val_doc] = score
1133
1134
1135 if isinstance(val_doc, NamespaceDoc):
1136 for var_doc in val_doc.variables.values():
1137
1138 varname = DottedName(name, var_doc.name)
1139 var_doc.canonical_name = varname
1140
1141
1142
1143 if (var_doc.value is UNKNOWN
1144 or isinstance(var_doc.value, GenericValueDoc)):
1145 continue
1146
1147
1148
1149 if _var_shadows_self(var_doc, varname):
1150 _fix_self_shadowing_var(var_doc, varname, docindex)
1151
1152
1153 vardoc_score = score-1
1154 if var_doc.is_imported is UNKNOWN: vardoc_score -= 10
1155 elif var_doc.is_imported: vardoc_score -= 100
1156 if var_doc.is_alias is UNKNOWN: vardoc_score -= 10
1157 elif var_doc.is_alias: vardoc_score -= 1000
1158
1159 assign_canonical_names(var_doc.value, varname,
1160 docindex, vardoc_score)
1161
1162
1163 for val_doc_2 in val_doc.apidoc_links(variables=False):
1164 val_name, val_score = _unreachable_name_for(val_doc_2, docindex)
1165 assign_canonical_names(val_doc_2, val_name, docindex, val_score)
1166
1172
1174
1175 cname = var_doc.value.canonical_name
1176 for i in range(1, len(cname)-1):
1177 new_name = cname[:i] + (cname[i]+"'") + cname[i+1:]
1178 val_doc = docindex.get_valdoc(new_name)
1179 if val_doc is not None:
1180 log.warning("%s shadows its own value -- using %s instead" %
1181 (varname, new_name))
1182 var_doc.value = val_doc
1183 return
1184
1185
1186
1187 log.warning('%s shadows itself' % varname)
1188 del var_doc.value.canonical_name
1189
1224
1225
1226
1227
1228
1266
1267 _INHERITED_ATTRIBS = [
1268 'descr', 'summary', 'metadata', 'extra_docstring_fields',
1269 'type_descr', 'arg_descrs', 'arg_types', 'return_descr',
1270 'return_type', 'exception_descrs']
1271
1273 """
1274 Copy any relevant documentation information from the variable that
1275 C{var_doc} overrides into C{var_doc} itself.
1276 """
1277
1278
1279 if var_doc.docstring not in (None, UNKNOWN):
1280 return
1281
1282 src_var = var_doc.overrides
1283 src_val = var_doc.overrides.value
1284 val_doc = var_doc.value
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300 for attrib in _INHERITED_ATTRIBS:
1301 if (hasattr(var_doc, attrib) and hasattr(src_var, attrib) and
1302 getattr(src_var, attrib) not in (None, UNKNOWN)):
1303 setattr(var_doc, attrib, getattr(src_var, attrib))
1304 elif (src_val is not None and
1305 hasattr(val_doc, attrib) and hasattr(src_val, attrib) and
1306 getattr(src_val, attrib) not in (None, UNKNOWN) and
1307 getattr(val_doc, attrib) in (None, UNKNOWN)):
1308 setattr(val_doc, attrib, getattr(src_val, attrib))
1309