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_docs()} -- 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
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
83 -def build_doc(item, introspect=True, parse=True, add_submodules=True):
84 """
85 Build API documentation for a given item, and return it as
86 an L{APIDoc} object.
87
88 @rtype: L{APIDoc}
89 @param item: The item to document, specified using any of the
90 following:
91 - A string, naming a python package directory
92 (e.g., C{'epydoc/markup'})
93 - A string, naming a python file
94 (e.g., C{'epydoc/docparser.py'})
95 - A string, naming a python object
96 (e.g., C{'epydoc.docparser.DocParser'})
97 - Any (non-string) python object
98 (e.g., C{list.append})
99 @param introspect: If true, then use introspection to examine the
100 specified items. Otherwise, just use parsing.
101 @param parse: If true, then use parsing to examine the specified
102 items. Otherwise, just use introspection.
103 """
104 docindex = build_doc_index(item, introspect, parse, add_submodules)
105 return docindex.root[0]
106
107 -def build_doc_index(items, introspect=True, parse=True,
108 add_submodules=True):
109 """
110 Build API documentation for the given list of items, and
111 return it in the form of a L{DocIndex}.
112
113 @rtype: L{DocIndex}
114 @param items: The items to document, specified using any of the
115 following:
116 - A string, naming a python package directory
117 (e.g., C{'epydoc/markup'})
118 - A string, naming a python file
119 (e.g., C{'epydoc/docparser.py'})
120 - A string, naming a python object
121 (e.g., C{'epydoc.docparser.DocParser'})
122 - Any (non-string) python object
123 (e.g., C{list.append})
124 @param introspect: If true, then use introspection to examine the
125 specified items. Otherwise, just use parsing.
126 @param parse: If true, then use parsing to examine the specified
127 items. Otherwise, just use introspection.
128 """
129
130 doc_pairs = _get_docs_from_items(items, introspect, parse, add_submodules)
131
132
133 if parse and introspect:
134 log.start_progress('Merging parsed & introspected information')
135 docs = []
136 for i, (introspect_doc, parse_doc) in enumerate(doc_pairs):
137 if introspect_doc is not None and parse_doc is not None:
138 if introspect_doc.canonical_name not in (None, UNKNOWN):
139 name = introspect_doc.canonical_name
140 else:
141 name = parse_doc.canonical_name
142 log.progress(float(i)/len(doc_pairs), name)
143 docs.append(merge_docs(introspect_doc, parse_doc))
144 elif introspect_doc is not None:
145 docs.append(introspect_doc)
146 elif parse_doc is not None:
147 docs.append(parse_doc)
148 log.end_progress()
149 elif introspect:
150 docs = [doc_pair[0] for doc_pair in doc_pairs if doc_pair[0]]
151 else:
152 docs = [doc_pair[1] for doc_pair in doc_pairs if doc_pair[1]]
153
154 if len(docs) == 0:
155 log.error('Nothing left to document!')
156 return None
157
158
159 docindex = DocIndex(docs)
160
161
162
163 if parse:
164 log.start_progress('Linking imported variables')
165 valdocs = docindex.reachable_valdocs(sort_by_name=True, imports=False,
166 submodules=False, packages=False,
167 subclasses=False)
168 for i, val_doc in enumerate(valdocs):
169 _report_valdoc_progress(i, val_doc, valdocs)
170 link_imports(val_doc, docindex)
171 log.end_progress()
172
173
174 log.start_progress('Indexing documentation')
175 for i, val_doc in enumerate(docindex.root):
176 log.progress(float(i)/len(docindex.root), val_doc.canonical_name)
177 assign_canonical_names(val_doc, val_doc.canonical_name, docindex)
178 log.end_progress()
179
180
181 log.start_progress('Parsing docstrings')
182 valdocs = docindex.reachable_valdocs(sort_by_name=True, imports=False,
183 submodules=False, packages=False,
184 subclasses=False)
185 for i, val_doc in enumerate(valdocs):
186 _report_valdoc_progress(i, val_doc, valdocs)
187
188 parse_docstring(val_doc, docindex)
189
190 if (isinstance(val_doc, NamespaceDoc) and
191 val_doc.variables not in (None, UNKNOWN)):
192 for var_doc in val_doc.variables.values():
193 parse_docstring(var_doc, docindex)
194 log.end_progress()
195
196
197 log.start_progress('Inheriting documentation')
198 for i, val_doc in enumerate(valdocs):
199 if isinstance(val_doc, ClassDoc):
200 percent = float(i)/len(valdocs)
201 log.progress(percent, val_doc.canonical_name)
202 inherit_docs(val_doc)
203 log.end_progress()
204
205
206 log.start_progress('Sorting & Grouping')
207 for i, val_doc in enumerate(valdocs):
208 if isinstance(val_doc, NamespaceDoc):
209 percent = float(i)/len(valdocs)
210 log.progress(percent, val_doc.canonical_name)
211 val_doc.init_sorted_variables()
212 val_doc.init_variable_groups()
213 if isinstance(val_doc, ModuleDoc):
214 val_doc.init_submodule_groups()
215 log.end_progress()
216
217 return docindex
218
224
225
226
227
228
230
231 log.start_progress('Building documentation')
232 progress_estimator = _ProgressEstimator(items)
233
234
235 doc_pairs = []
236 for item in items:
237 if isinstance(item, basestring):
238 if is_module_file(item):
239 doc_pairs.append(_get_docs_from_module_file(
240 item, introspect, parse, progress_estimator))
241 elif is_package_dir(item):
242 pkgfile = os.path.join(item, '__init__')
243 doc_pairs.append(_get_docs_from_module_file(
244 pkgfile, introspect, parse, progress_estimator))
245 elif os.path.isfile(item):
246 doc_pairs.append(_get_docs_from_pyscript(
247 item, introspect, parse, progress_estimator))
248 elif hasattr(__builtin__, item):
249 val = getattr(__builtin__, item)
250 doc_pairs.append(_get_docs_from_pyobject(
251 val, introspect, parse, progress_estimator))
252 elif is_pyname(item):
253 doc_pairs.append(_get_docs_from_pyname(
254 item, introspect, parse, progress_estimator))
255 elif os.path.isdir(item):
256 log.error("Directory %r is not a package" % item)
257 elif os.path.isfile(item):
258 log.error("File %s is not a Python module" % item)
259 else:
260 log.error("Could not find a file or object named %s" %
261 item)
262 else:
263 doc_pairs.append(_get_docs_from_pyobject(
264 item, introspect, parse, progress_estimator))
265
266
267
268
269
270 if add_submodules and not is_module_file(item):
271 doc_pairs += _get_docs_from_submodules(
272 item, doc_pairs[-1], introspect, parse, progress_estimator)
273
274 log.end_progress()
275 return doc_pairs
276
278 progress_estimator.complete += 1
279 log.progress(progress_estimator.progress(), `obj`)
280
281 if not introspect:
282 log.error("Cannot get docs for Python objects without "
283 "introspecting them.")
284
285 introspect_doc = parse_doc = None
286 introspect_error = parse_error = None
287 try:
288 introspect_doc = introspect_docs(value=obj)
289 except ImportError, e:
290 log.error(e)
291 return (None, None)
292 if parse:
293 if introspect_doc.canonical_name is not None:
294 _, parse_docs = _get_docs_from_pyname(
295 str(introspect_doc.canonical_name), False, True,
296 progress_estimator, supress_warnings=True)
297 return (introspect_doc, parse_doc)
298
301 progress_estimator.complete += 1
302 log.progress(progress_estimator.progress(), name)
303
304 introspect_doc = parse_doc = None
305 introspect_error = parse_error = None
306 if introspect:
307 try:
308 introspect_doc = introspect_docs(name=name)
309 except ImportError, e:
310 introspect_error = str(e)
311 if parse:
312 try:
313 parse_doc = parse_docs(name=name)
314 except ParseError, e:
315 parse_error = str(e)
316 except ImportError, e:
317
318
319 pass
320
321
322 if not supress_warnings:
323 _report_errors(name, introspect_doc, parse_doc,
324 introspect_error, parse_error)
325
326
327 return (introspect_doc, parse_doc)
328
330
331
332
333 introspect_doc = parse_doc = None
334 introspect_error = parse_error = None
335 if introspect:
336 try:
337 introspect_doc = introspect_docs(filename=filename, is_script=True)
338 except ImportError, e:
339 introspect_error = str(e)
340 if parse:
341 try:
342 parse_doc = parse_docs(filename=filename, is_script=True)
343 except ParseError, e:
344 parse_error = str(e)
345 except ImportError, e:
346 parse_error = str(e)
347
348
349 _report_errors(filename, introspect_doc, parse_doc,
350 introspect_error, parse_error)
351
352
353 return (introspect_doc, parse_doc)
354
357 """
358 Construct and return the API documentation for the python
359 module with the given filename.
360
361 @param parent_doc: The C{ModuleDoc} of the containing package.
362 If C{parent_doc} is not provided, then this method will
363 check if the given filename is contained in a package; and
364 if so, it will construct a stub C{ModuleDoc} for the
365 containing package(s).
366 """
367
368 modulename = os.path.splitext(os.path.split(filename)[1])[0]
369 if modulename == '__init__':
370 modulename = os.path.split(os.path.split(filename)[0])[1]
371 if parent_docs[0]:
372 modulename = DottedName(parent_docs[0].canonical_name, modulename)
373 elif parent_docs[1]:
374 modulename = DottedName(parent_docs[1].canonical_name, modulename)
375 log.progress(progress_estimator.progress(),
376 '%s (%s)' % (modulename, filename))
377 progress_estimator.complete += 1
378
379
380 filename = os.path.normpath(os.path.abspath(filename))
381
382
383 try:
384 filename = py_src_filename(filename)
385 src_file_available = True
386 except ValueError:
387 src_file_available = False
388
389
390 introspect_doc = parse_doc = None
391 introspect_error = parse_error = None
392 if introspect:
393 try:
394 introspect_doc = introspect_docs(
395 filename=filename, context=parent_docs[0])
396 except ImportError, e:
397 introspect_error = str(e)
398 if parse and src_file_available:
399 try:
400 parse_doc = parse_docs(
401 filename=filename, context=parent_docs[1])
402 except ParseError, e:
403 parse_error = str(e)
404 except ImportError, e:
405 parse_error = str(e)
406
407
408 _report_errors(filename, introspect_doc, parse_doc,
409 introspect_error, parse_error)
410
411
412 return (introspect_doc, parse_doc)
413
416
417 if isinstance(pkg_docs[0], ModuleDoc) and pkg_docs[0].is_package:
418 pkg_path = pkg_docs[0].path
419 package_dir = os.path.split(pkg_docs[0].filename)[0]
420 elif isinstance(pkg_docs[1], ModuleDoc) and pkg_docs[1].is_package:
421 pkg_path = pkg_docs[1].path
422 package_dir = os.path.split(pkg_docs[1].filename)[0]
423 else:
424 return []
425
426 module_filenames = {}
427 subpackage_dirs = set()
428 for subdir in pkg_path:
429 if os.path.isdir(subdir):
430 for name in os.listdir(subdir):
431 filename = os.path.join(subdir, name)
432
433 if is_module_file(filename):
434 basename = os.path.splitext(filename)[0]
435 if os.path.split(basename)[1] != '__init__':
436 module_filenames[basename] = filename
437
438 if is_package_dir(filename):
439 subpackage_dirs.add(filename)
440
441
442 progress_estimator.revise_estimate(item, module_filenames.items(),
443 subpackage_dirs)
444
445 docs = [pkg_docs]
446 for module_filename in module_filenames.values():
447 d = _get_docs_from_module_file(
448 module_filename, introspect, parse, progress_estimator, pkg_docs)
449 docs.append(d)
450 for subpackage_dir in subpackage_dirs:
451 subpackage_file = os.path.join(subpackage_dir, '__init__')
452 docs.append(_get_docs_from_module_file(
453 subpackage_file, introspect, parse, progress_estimator, pkg_docs))
454 docs += _get_docs_from_submodules(
455 subpackage_dir, docs[-1], introspect, parse, progress_estimator)
456 return docs
457
458 -def _report_errors(name, introspect_doc, parse_doc,
459 introspect_error, parse_error):
460 hdr = 'In %s:\n' % name
461 if introspect_doc == parse_doc == None:
462 log.start_block('%sNo documentation available!' % hdr)
463 if introspect_error:
464 log.error('Import failed:\n%s' % introspect_error)
465 if parse_error:
466 log.error('Source code parsing failed:\n%s' % parse_error)
467 log.end_block()
468 elif introspect_error:
469 log.start_block('%sImport failed (but source code parsing '
470 'was successful).' % hdr)
471 log.error(introspect_error)
472 log.end_block()
473 elif parse_error:
474 log.start_block('%sSource code parsing failed (but '
475 'introspection was successful).' % hdr)
476 log.error(parse_error)
477 log.end_block()
478
479
480
481
482
483
485 """
486 Used to keep track of progress when generating the initial docs
487 for the given items. (It is not known in advance how many items a
488 package directory will contain, since it might depend on those
489 packages' __path__ values.)
490 """
492 self.est_totals = {}
493 self.complete = 0
494
495 for item in items:
496 if is_package_dir(item):
497 self.est_totals[item] = self._est_pkg_modules(item)
498 else:
499 self.est_totals[item] = 1
500
502 total = sum(self.est_totals.values())
503 return float(self.complete) / total
504
506 del self.est_totals[pkg_item]
507 for item in modules:
508 self.est_totals[item] = 1
509 for item in subpackages:
510 self.est_totals[item] = self._est_pkg_modules(item)
511
524
525
526
527
528
529 MERGE_PRECEDENCE = {
530 'repr': 'parse',
531
532
533 'canonical_name': 'introspect',
534
535
536
537 'is_imported': 'parse',
538
539
540 'is_alias': 'parse',
541
542
543 'docformat': 'parse',
544
545
546
547 'is_package': 'parse',
548
549
550
551 'sort_spec': 'parse',
552
553 'submodules': 'introspect',
554
555
556 'filename': 'parse',
557
558
559
560
561 'docstring': 'introspect',
562 }
563 """Indicates whether information from introspection or parsing should be
564 given precedence, for specific attributes. This dictionary maps from
565 attribute names to either C{'introspect'} or C{'parse'}."""
566
567 DEFAULT_MERGE_PRECEDENCE = 'introspect'
568 """Indicates whether information from introspection or parsing should be
569 given precedence. Should be either C{'introspect'} or C{'parse'}"""
570
571 _attribute_mergefunc_registry = {}
573 """
574 Register an attribute merge function. This function will be
575 called by L{merge_docs()} when it needs to merge the attribute
576 values of two C{APIDoc}s.
577
578 @param attrib: The name of the attribute whose values are merged
579 by C{mergefunc}.
580
581 @param mergefun: The merge function, whose sinature is:
582
583 >>> def mergefunc(introspect_val, parse_val, precedence, cyclecheck, path):
584 ... return calculate_merged_value(introspect_val, parse_val)
585
586 Where C{introspect_val} and C{parse_val} are the two values to
587 combine; C{precedence} is a string indicating which value takes
588 precedence for this attribute (C{'introspect'} or C{'parse'});
589 C{cyclecheck} is a value used by C{merge_docs()} to make sure that
590 it only visits each pair of docs once; and C{path} is a string
591 describing the path that was taken from the root to this
592 attribute (used to generate log messages).
593
594 If the merge function needs to call C{merge_docs}, then it should
595 pass C{cyclecheck} and C{path} back in. (When appropriate, a
596 suffix should be added to C{path} to describe the path taken to
597 the merged values.)
598 """
599 _attribute_mergefunc_registry[attrib] = mergefunc
600
601 -def merge_docs(introspect_doc, parse_doc, cyclecheck=None, path=None):
602 """
603 Merge the API documentation information that was obtained from
604 introspection with information that was obtained from parsing.
605 C{introspect_doc} and C{parse_doc} should be two C{APIDoc} instances
606 that describe the same object. C{merge_docs} combines the
607 information from these two instances, and returns the merged
608 C{APIDoc}.
609
610 If C{introspect_doc} and C{parse_doc} are compatible, then they will
611 be I{merged} -- i.e., they will be coerced to a common class, and
612 their state will be stored in a shared dictionary. Once they have
613 been merged, any change made to the attributes of one will affect
614 the other. The value for the each of the merged C{APIDoc}'s
615 attributes is formed by combining the values of the source
616 C{APIDoc}s' attributes, as follows:
617
618 - If either of the source attributes' value is C{UNKNOWN}, then
619 use the other source attribute's value.
620 - Otherwise, if an attribute merge function has been registered
621 for the attribute, then use that function to calculate the
622 merged value from the two source attribute values.
623 - Otherwise, if L{MERGE_PRECEDENCE} is defined for the
624 attribute, then use the attribute value from the source that
625 it indicates.
626 - Otherwise, use the attribute value from the source indicated
627 by L{DEFAULT_MERGE_PRECEDENCE}.
628
629 If C{introspect_doc} and C{parse_doc} are I{not} compatible (e.g., if
630 their values have incompatible types), then C{merge_docs()} will
631 simply return either C{introspect_doc} or C{parse_doc}, depending on
632 the value of L{DEFAULT_MERGE_PRECEDENCE}. The two input
633 C{APIDoc}s will not be merged or modified in any way.
634
635 @param cyclecheck, path: These arguments should only be provided
636 when C{merge_docs()} is called by an attribute merge
637 function. See L{register_attribute_mergefunc()} for more
638 details.
639 """
640 assert isinstance(introspect_doc, APIDoc)
641 assert isinstance(parse_doc, APIDoc)
642
643 if cyclecheck is None:
644 cyclecheck = set()
645 if introspect_doc.canonical_name not in (None, UNKNOWN):
646 path = '%s' % introspect_doc.canonical_name
647 elif parse_doc.canonical_name not in (None, UNKNOWN):
648 path = '%s' % parse_doc.canonical_name
649 else:
650 path = '??'
651
652
653
654
655
656 if (id(introspect_doc), id(parse_doc)) in cyclecheck:
657 return introspect_doc
658 cyclecheck.add( (id(introspect_doc), id(parse_doc)) )
659
660
661
662
663 if introspect_doc == parse_doc:
664 return introspect_doc
665
666
667
668
669 if type(introspect_doc) == type(parse_doc) == GenericValueDoc:
670 parse_doc.pyval = introspect_doc.pyval
671 parse_doc.docs_extracted_by = 'both'
672 return parse_doc
673
674
675
676
677 mismatch = None
678 if (introspect_doc.__class__ != parse_doc.__class__ and
679 not (issubclass(introspect_doc.__class__, parse_doc.__class__) or
680 issubclass(parse_doc.__class__, introspect_doc.__class__))):
681 mismatch = ("value types don't match -- i=%r, p=%r." %
682 (introspect_doc.__class__, parse_doc.__class__))
683 if (isinstance(introspect_doc, ValueDoc) and
684 isinstance(parse_doc, ValueDoc)):
685 if (introspect_doc.pyval is not UNKNOWN and
686 parse_doc.pyval is not UNKNOWN and
687 introspect_doc.pyval is not parse_doc.pyval):
688 mismatch = "values don't match."
689 elif (introspect_doc.canonical_name not in (None, UNKNOWN) and
690 parse_doc.canonical_name not in (None, UNKNOWN) and
691 introspect_doc.canonical_name != parse_doc.canonical_name):
692 mismatch = "canonical names don't match."
693 if mismatch is not None:
694 log.info("Not merging the parsed & introspected values of %s, "
695 "since their %s" % (path, mismatch))
696 if DEFAULT_MERGE_PRECEDENCE == 'introspect':
697 return introspect_doc
698 else:
699 return parse_doc
700
701
702
703 if introspect_doc.__class__ is not parse_doc.__class__:
704 if issubclass(introspect_doc.__class__, parse_doc.__class__):
705 parse_doc.specialize_to(introspect_doc.__class__)
706 if issubclass(parse_doc.__class__, introspect_doc.__class__):
707 introspect_doc.specialize_to(parse_doc.__class__)
708 assert introspect_doc.__class__ is parse_doc.__class__
709
710
711
712
713 if (isinstance(introspect_doc, RoutineDoc) and
714 isinstance(parse_doc, RoutineDoc)):
715 _merge_posargs_and_defaults(introspect_doc, parse_doc, path)
716
717
718 for attrib in set(introspect_doc.__dict__.keys() +
719 parse_doc.__dict__.keys()):
720
721
722 if attrib.startswith('_'): continue
723 merge_attribute(attrib, introspect_doc, parse_doc,
724 cyclecheck, path)
725
726
727 return introspect_doc.merge_and_overwrite(parse_doc)
728
751
753 precedence = MERGE_PRECEDENCE.get(attrib, DEFAULT_MERGE_PRECEDENCE)
754 if precedence not in ('parse', 'introspect'):
755 raise ValueError('Bad precedence value %r' % precedence)
756
757 if (getattr(introspect_doc, attrib) is UNKNOWN and
758 getattr(parse_doc, attrib) is not UNKNOWN):
759 setattr(introspect_doc, attrib, getattr(parse_doc, attrib))
760 elif (getattr(introspect_doc, attrib) is not UNKNOWN and
761 getattr(parse_doc, attrib) is UNKNOWN):
762 setattr(parse_doc, attrib, getattr(introspect_doc, attrib))
763 elif (getattr(introspect_doc, attrib) is UNKNOWN and
764 getattr(parse_doc, attrib) is UNKNOWN):
765 pass
766 else:
767
768 introspect_val = getattr(introspect_doc, attrib)
769 parse_val = getattr(parse_doc, attrib)
770 if attrib in _attribute_mergefunc_registry:
771 handler = _attribute_mergefunc_registry[attrib]
772 merged_val = handler(introspect_val, parse_val, precedence,
773 cyclecheck, path)
774 elif precedence == 'introspect':
775 merged_val = introspect_val
776 elif precedence == 'parse':
777 merged_val = parse_val
778
779 setattr(introspect_doc, attrib, merged_val)
780 setattr(parse_doc, attrib, merged_val)
781
783
784 for varname, var1 in varlist1.items():
785 var2 = varlist2.get(varname)
786 if var2 is not None:
787 var = merge_docs(var1, var2, cyclecheck, path+'.'+varname)
788 varlist1[varname] = var
789 varlist2[varname] = var
790
791
792 for varname, var in varlist2.items():
793 varlist1.setdefault(varname, var)
794
795 return varlist1
796
797 -def merge_value(value1, value2, precedence, cyclecheck, path):
798 assert value1 is not None and value2 is not None
799 return merge_docs(value1, value2, cyclecheck, path)
800
801
803 if v1 is None or v2 is None:
804 if precedence == 'introspect': return v1
805 else: return v2
806 return merge_value(v1, v2, precedence, cyclecheck, path+'.<package>')
808 if v1 is None or v2 is None:
809 if precedence == 'introspect': return v1
810 else: return v2
811 return merge_value(v1, v2, precedence, cyclecheck, path+'.<container>')
813 return merge_value(v1, v2, precedence, cyclecheck, path+'.<overrides>')
814 -def merge_fget(v1, v2, precedence, cyclecheck, path):
816 -def merge_fset(v1, v2, precedence, cyclecheck, path):
818 -def merge_fdel(v1, v2, precedence, cyclecheck, path):
820
822
823
824 return v1
825
826 -def merge_bases(baselist1, baselist2, precedence, cyclecheck, path):
827
828
829
830
831
832
833
834
835 if len(baselist1) != len(baselist2):
836 log.info("Not merging the introspected & parsed base lists "
837 "for %s, since their lengths don't match (%s vs %s)" %
838 (path, len(baselist1), len(baselist2)))
839 if precedence == 'introspect': return baselist1
840 else: return baselist2
841
842
843 for base1, base2 in zip(baselist1, baselist2):
844 if ((base1.canonical_name not in (None, UNKNOWN) and
845 base2.canonical_name not in (None, UNKNOWN)) and
846 base1.canonical_name != base2.canonical_name):
847 log.info("Not merging the parsed & introspected base "
848 "lists for %s, since the bases' names don't match "
849 "(%s vs %s)" % (path, base1.canonical_name,
850 base2.canonical_name))
851 if precedence == 'introspect': return baselist1
852 else: return baselist2
853
854 for i, (base1, base2) in enumerate(zip(baselist1, baselist2)):
855 base = merge_docs(base1, base2, cyclecheck,
856 '%s.__bases__[%d]' % (path, i))
857 baselist1[i] = baselist2[i] = base
858
859 return baselist1
860
862 if len(defaults1) != len(defaults2):
863 if precedence == 'introspect': return defaults1
864 else: return defaults2
865 defaults = []
866 for i, (d1, d2) in enumerate(zip(defaults1, defaults2)):
867 if d1 is not None and d2 is not None:
868 d_path = '%s.<default-arg-val>[%d]' % (path, i)
869 defaults.append(merge_docs(d1, d2, cyclecheck, d_path))
870 elif precedence == 'introspect':
871 defaults.append(d1)
872 else:
873 defaults.append(d2)
874 return defaults
875
877 if docstring1 in (None, UNKNOWN) or precedence=='parse':
878 return docstring2
879 else:
880 return docstring1
881
883 return 'both'
884
885 register_attribute_mergefunc('variables', merge_variables)
886 register_attribute_mergefunc('value', merge_value)
887
888
889
890 register_attribute_mergefunc('overrides', merge_overrides)
891 register_attribute_mergefunc('fget', merge_fget)
892 register_attribute_mergefunc('fset', merge_fset)
893 register_attribute_mergefunc('fdel', merge_fdel)
894 register_attribute_mergefunc('proxy_for', merge_proxy_for)
895 register_attribute_mergefunc('bases', merge_bases)
896 register_attribute_mergefunc('posarg_defaults', merge_posarg_defaults)
897 register_attribute_mergefunc('docstring', merge_docstring)
898 register_attribute_mergefunc('docs_extracted_by', merge_docs_extracted_by)
899
900
901
902
903
941
942
943
944
945
946 _name_scores = {}
947 """A dictionary mapping from each C{ValueDoc} to the score that has
948 been assigned to its current cannonical name. If
949 L{assign_canonical_names()} finds a canonical name with a better
950 score, then it will replace the old name."""
951
952 _unreachable_names = set(DottedName(DottedName.UNREACHABLE))
953 """The set of names that have been used for unreachable objects. This
954 is used to ensure there are no duplicate cannonical names assigned."""
955
957 """
958 Assign a canonical name to C{val_doc} (if it doesn't have one
959 already), and (recursively) to each variable in C{val_doc}.
960 In particular, C{val_doc} will be assigned the canonical name
961 C{name} iff either:
962 - C{val_doc}'s canonical name is C{UNKNOWN}; or
963 - C{val_doc}'s current canonical name was assigned by this
964 method; but the score of the new name (C{score}) is higher
965 than the score of the current name (C{score_dict[val_doc]}).
966
967 Note that canonical names will even be assigned to values
968 like integers and C{None}; but these should be harmless.
969 """
970
971
972
973
974 if val_doc in _name_scores and score <= _name_scores[val_doc]:
975 return
976
977
978 if (val_doc not in _name_scores and
979 val_doc.canonical_name is not UNKNOWN):
980
981
982 _name_scores[val_doc] = sys.maxint
983 name = val_doc.canonical_name
984 score = 0
985 else:
986
987
988 if (val_doc not in _name_scores or
989 score > _name_scores[val_doc]):
990 val_doc.canonical_name = name
991 _name_scores[val_doc] = score
992
993
994 if isinstance(val_doc, NamespaceDoc):
995 for var_doc in val_doc.variables.values():
996 if var_doc.value is UNKNOWN: continue
997 varname = DottedName(name, var_doc.name)
998
999
1000
1001 if _var_shadows_self(var_doc, varname):
1002 _fix_self_shadowing_var(var_doc, varname, docindex)
1003
1004
1005 vardoc_score = score-1
1006 if var_doc.is_imported is UNKNOWN: vardoc_score -= 10
1007 elif var_doc.is_imported: vardoc_score -= 100
1008 if var_doc.is_alias is UNKNOWN: vardoc_score -= 10
1009 elif var_doc.is_alias: vardoc_score -= 1000
1010
1011 assign_canonical_names(var_doc.value, varname,
1012 docindex, vardoc_score)
1013
1014
1015 for val_doc_2 in val_doc.apidoc_links(variables=False):
1016 val_name, val_score = _unreachable_name_for(val_doc_2, docindex)
1017 assign_canonical_names(val_doc_2, val_name, docindex, val_score)
1018
1024
1026
1027 cname = var_doc.value.canonical_name
1028 for i in range(1, len(cname)-1):
1029 new_name = cname[:i] + (cname[i]+"'") + cname[i+1:]
1030 val_doc = docindex.get_valdoc(new_name)
1031 if val_doc is not None:
1032 log.warning("%s shadows its own value -- using %s instead" %
1033 (varname, new_name))
1034 var_doc.value = val_doc
1035 return
1036
1037
1038
1039 log.warning('%s shadows itself' % varname)
1040 del var_doc.value.canonical_name
1041
1077
1078
1079
1080
1081
1119
1120 _INHERITED_ATTRIBS = [
1121 'descr', 'summary', 'metadata', 'extra_docstring_fields',
1122 'type_descr', 'arg_descrs', 'arg_types', 'return_descr',
1123 'return_type', 'exception_descrs']
1124
1126 """
1127 Copy any relevant documentation information from the variable that
1128 C{var_doc} overrides into C{var_doc} itself.
1129 """
1130
1131
1132 if var_doc.docstring not in (None, UNKNOWN):
1133 return
1134
1135 src_var = var_doc.overrides
1136 src_val = var_doc.overrides.value
1137 val_doc = var_doc.value
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 for attrib in _INHERITED_ATTRIBS:
1154 if (hasattr(var_doc, attrib) and hasattr(src_var, attrib) and
1155 getattr(src_var, attrib) not in (None, UNKNOWN)):
1156 setattr(var_doc, attrib, getattr(src_var, attrib))
1157 elif (src_val is not None and
1158 hasattr(val_doc, attrib) and hasattr(src_val, attrib) and
1159 getattr(src_val, attrib) not in (None, UNKNOWN) and
1160 getattr(val_doc, attrib) in (None, UNKNOWN)):
1161 setattr(val_doc, attrib, getattr(src_val, attrib))
1162