1
2
3
4
5
6
7
8
9 """
10 Extract API documentation about python objects by directly introspecting
11 their values.
12
13 L{DocIntrospecter} is a processing class that examines Python objects via
14 introspection, and uses the information it finds to create L{APIDoc}
15 objects containing the API documentation for those objects.
16
17 C{DocIntrospecter} can be subclassed to extend the set of object types
18 that it supports.
19 """
20 __docformat__ = 'epytext en'
21
22
23
24
25
26 import inspect, re, sys, os.path, imp
27
28 from epydoc.apidoc import *
29
30 from types import *
31
32 from epydoc import log
33
34 from epydoc.util import *
35
36 import epydoc.docparser
37
38 import __builtin__
39
40 from epydoc.compat import *
41
42
43
44
45
46 _valuedoc_cache = {}
47 """A cache containing the API documentation for values that we've
48 already seen. This cache is implemented as a dictionary that maps a
49 value's pyid to its L{ValueDoc}.
50
51 Note that if we encounter a value but decide not to introspect it
52 (because it's imported from another module), then C{_valuedoc_cache}
53 will contain an entry for the value, but the value will not be listed
54 in L{_introspected_values}."""
55
56 _introspected_values = {}
57 """A record which values we've introspected, encoded as a dictionary from
58 pyid to C{bool}."""
59
60
61
62
63
64
65 """
66 An API documentation extractor based on introspecting python values.
67 C{DocIntrospecter} examines Python objects via introspection, and uses
68 the information it finds to create L{APIDoc} objects containing
69 the API documentation for those objects. The main interface to
70 the C{DocIntrospecter} class is the L{introspect} method, which takes a
71 Python value, and returns an L{APIDoc} that describes it.
72
73 Currently, C{DocIntrospecter} can extract documentation information
74 from the following object types:
75
76 - modules
77 - classes
78 - functions
79 - methods
80 - class methods
81 - static methods
82 - builtin routines
83 - properties
84
85 Subclassing
86 ===========
87 C{DocIntrospecter} can be subclassed, to extend the set of object
88 types that it supports. C{DocIntrospecter} can be extended in
89 several different ways:
90
91 - A subclass can override one of the existing introspection methods
92 to modify the behavior for a currently supported object type.
93
94 - A subclass can add support for a new type by adding a new
95 introspection method; and extending L{introspecter_method()} to
96 return that method for values of the new type.
97 """
98
99 -def introspect_docs(value=None, name=None, filename=None, context=None,
100 is_script=False):
101 """
102 Generate the API documentation for a specified object by
103 introspecting Python values, and return it as a L{ValueDoc}. The
104 object to generate documentation for may be specified using
105 the C{value} parameter, the C{filename} parameter, I{or} the
106 C{name} parameter. (It is an error to specify more than one
107 of these three parameters, or to not specify any of them.)
108
109 @param value: The python object that should be documented.
110 @param filename: The name of the file that contains the python
111 source code for a package, module, or script. If
112 C{filename} is specified, then C{introspect} will return a
113 C{ModuleDoc} describing its contents.
114 @param name: The fully-qualified python dotted name of any
115 value (including packages, modules, classes, and
116 functions). C{DocParser} will automatically figure out
117 which module(s) it needs to import in order to find the
118 documentation for the specified object.
119 @param context: The API documentation for the class of module
120 that contains C{value} (if available).
121 """
122 if value is None and name is not None and filename is None:
123 value = get_value_from_name(DottedName(name))
124 elif value is None and name is None and filename is not None:
125 if is_script:
126 value = get_value_from_scriptname(filename)
127 else:
128 value = get_value_from_filename(filename, context)
129 elif name is None and filename is None:
130
131 pass
132 else:
133 raise ValueError("Expected exactly one of the following "
134 "arguments: value, name, filename")
135
136 pyid = id(value)
137
138
139
140 if pyid in _introspected_values:
141 return _valuedoc_cache[pyid]
142
143
144 val_doc = _get_valuedoc(value)
145
146
147 _introspected_values[pyid] = True
148 introspect_func = _get_introspecter(value)
149 introspect_func(value, val_doc)
150
151
152 if val_doc.canonical_name == UNKNOWN and name is not None:
153 val_doc.canonical_name = DottedName(name)
154
155
156
157
158
159
160 if is_script and filename is not None:
161 val_doc.canonical_name = DottedName(munge_script_name(str(filename)))
162
163 if val_doc.canonical_name == UNKNOWN and filename is not None:
164 shadowed_name = DottedName(value.__name__)
165 log.warning("Module %s is shadowed by a variable with "
166 "the same name." % shadowed_name)
167 val_doc.canonical_name = DottedName(str(shadowed_name)+"'")
168
169 return val_doc
170
172 """
173 If a C{ValueDoc} for the given value exists in the valuedoc
174 cache, then return it; otherwise, create a new C{ValueDoc},
175 add it to the cache, and return it. When possible, the new
176 C{ValueDoc}'s C{pyval}, C{repr}, and C{canonical_name}
177 attributes will be set appropriately.
178 """
179 pyid = id(value)
180 val_doc = _valuedoc_cache.get(pyid)
181 if val_doc is None:
182 try: canonical_name = get_canonical_name(value)
183 except DottedName.InvalidDottedName: canonical_name = UNKNOWN
184 val_doc = ValueDoc(pyval=value, canonical_name = canonical_name,
185 docs_extracted_by='introspecter')
186 _valuedoc_cache[pyid] = val_doc
187
188
189
190
191 if inspect.ismodule(value):
192 introspect_module(value, val_doc, preliminary=True)
193 val_doc.defining_module = val_doc
194 else:
195 module_name = str(get_containing_module(value))
196 module = sys.modules.get(module_name)
197 if module is not None and inspect.ismodule(module):
198 val_doc.defining_module = _get_valuedoc(module)
199
200 return val_doc
201
202
203
204
205
206
207
208 UNDOCUMENTED_MODULE_VARS = (
209 '__builtins__', '__doc__', '__all__', '__file__', '__path__',
210 '__name__', '__extra_epydoc_fields__', '__docformat__')
211
213 """
214 Add API documentation information about the module C{module}
215 to C{module_doc}.
216 """
217 module_doc.specialize_to(ModuleDoc)
218
219
220 if hasattr(module, '__docformat__'):
221 module_doc.docformat = unicode(module.__docformat__)
222
223
224 if hasattr(module, '__file__'):
225 try: module_doc.filename = unicode(module.__file__)
226 except KeyboardInterrupt: raise
227 except: pass
228
229
230
231
232
233 if preliminary: return
234
235
236 if hasattr(module, '__doc__'):
237 module_doc.docstring = get_docstring(module)
238
239
240
241 if hasattr(module, '__path__'):
242 module_doc.is_package = True
243 try: module_doc.path = [unicode(p) for p in module.__path__]
244 except KeyboardInterrupt: raise
245 except: pass
246 else:
247 module_doc.is_package = False
248
249
250 dotted_name = module_doc.canonical_name
251 if dotted_name is UNKNOWN:
252 dotted_name = DottedName(module.__name__)
253
254
255 if len(dotted_name) > 1:
256 package_name = str(dotted_name.container())
257 package = sys.modules.get(package_name)
258 if package is not None:
259 module_doc.package = introspect_docs(package)
260 else:
261 module_doc.package = None
262
263
264 module_doc.submodules = []
265
266
267 if module_doc.package not in (None, UNKNOWN):
268 module_doc.package.submodules.append(module_doc)
269
270
271 module_doc.variables = {}
272 for child_name in dir(module):
273 if child_name in UNDOCUMENTED_MODULE_VARS: continue
274 child = getattr(module, child_name)
275
276
277
278 container = get_containing_module(child)
279 if container != None and container == module_doc.canonical_name:
280
281 child_val_doc = introspect_docs(child, context=module_doc)
282 child_var_doc = VariableDoc(name=child_name,
283 value=child_val_doc,
284 is_imported=False,
285 container=module_doc,
286 docs_extracted_by='introspecter')
287 elif container is None or module_doc.canonical_name is UNKNOWN:
288
289 child_val_doc = introspect_docs(child, context=module_doc)
290 child_var_doc = VariableDoc(name=child_name,
291 value=child_val_doc,
292 container=module_doc,
293 docs_extracted_by='introspecter')
294 else:
295
296 child_val_doc = _get_valuedoc(child)
297 child_var_doc = VariableDoc(name=child_name,
298 value=child_val_doc,
299 is_imported=True,
300 container=module_doc,
301 docs_extracted_by='introspecter')
302
303 module_doc.variables[child_name] = child_var_doc
304
305
306 if hasattr(module, '__all__'):
307 try:
308 public_names = set([str(name) for name in module.__all__])
309 for name, var_doc in module_doc.variables.items():
310 if name in public_names:
311 var_doc.is_public = True
312 if not isinstance(var_doc, ModuleDoc):
313 var_doc.is_imported = False
314 else:
315 var_doc.is_public = False
316 except KeyboardInterrupt: raise
317 except: pass
318
319 return module_doc
320
321
322
323
324
325
326
327 UNDOCUMENTED_CLASS_VARS = (
328 '__doc__', '__module__', '__dict__', '__weakref__')
329
331 """
332 Add API documentation information about the class C{cls}
333 to C{class_doc}.
334 """
335 class_doc.specialize_to(ClassDoc)
336
337
338 class_doc.docstring = get_docstring(cls)
339
340
341 if hasattr(cls, '__all__'):
342 try:
343 public_names = [str(name) for name in cls.__all__]
344 class_doc.public_names = public_names
345 except KeyboardInterrupt: raise
346 except: pass
347
348
349 class_doc.subclasses = []
350
351
352
353
354
355
356
357
358
359
360
361
362
363 base_children = {}
364
365
366
367 if hasattr(cls, '__bases__'):
368 class_doc.bases = []
369 for base in cls.__bases__:
370 basedoc = introspect_docs(base)
371 class_doc.bases.append(basedoc)
372 basedoc.subclasses.append(class_doc)
373
374 bases = list(cls.__bases__)
375 bases.reverse()
376 for base in bases:
377 if hasattr(base, '__dict__'):
378 base_children.update(base.__dict__)
379
380
381 class_doc.variables = {}
382 private_prefix = '_%s__' % cls.__name__
383 if hasattr(cls, '__dict__'):
384 for child_name, child in cls.__dict__.items():
385 if (child_name in base_children
386 and base_children[child_name] == child):
387 continue
388
389 if child_name.startswith(private_prefix):
390 child_name = child_name[len(private_prefix)-2:]
391 if child_name in UNDOCUMENTED_CLASS_VARS: continue
392
393
394 val_doc = introspect_docs(child, context=class_doc)
395 var_doc = VariableDoc(name=child_name, value=val_doc,
396 container=class_doc,
397 docs_extracted_by='introspecter')
398 class_doc.variables[child_name] = var_doc
399
400 return class_doc
401
402
403
404
405
407 """Add API documentation information about the function
408 C{routine} to C{routine_doc} (specializing it to C{Routine_doc})."""
409 routine_doc.specialize_to(RoutineDoc)
410
411
412 if isinstance(routine, MethodType):
413 func = routine.im_func
414 elif isinstance(routine, staticmethod):
415 func = routine.__get__(0)
416 elif isinstance(routine, classmethod):
417 func = routine.__get__(0).im_func
418 else:
419 func = routine
420
421
422 routine_doc.docstring = get_docstring(func)
423
424
425 if isinstance(func, FunctionType):
426 (args, vararg, kwarg, defaults) = inspect.getargspec(func)
427
428
429 routine_doc.posargs = args
430 routine_doc.vararg = vararg
431 routine_doc.kwarg = kwarg
432
433
434 routine_doc.posarg_defaults = [None]*len(args)
435 if defaults is not None:
436 offset = len(args)-len(defaults)
437 for i in range(len(defaults)):
438 default_val = introspect_docs(defaults[i])
439 routine_doc.posarg_defaults[i+offset] = default_val
440
441
442 if isinstance(routine, MethodType) and routine.im_self is not None:
443 routine_doc.posargs = routine_doc.posargs[1:]
444 routine_doc.posarg_defaults = routine_doc.posarg_defaults[1:]
445
446
447 if hasattr(func, 'func_code'):
448 routine_doc.lineno = func.func_code.co_firstlineno
449
450 else:
451
452 routine_doc.posargs = ['...']
453 routine_doc.posarg_defaults = [None]
454 routine_doc.kwarg = None
455 routine_doc.vararg = None
456
457
458 if isinstance(routine, staticmethod):
459 routine_doc.specialize_to(StaticMethodDoc)
460 if isinstance(routine, classmethod):
461 routine_doc.specialize_to(ClassMethodDoc)
462
463 return routine_doc
464
465
466
467
468
483
484
485
486
487
492
493
494
495
496
498 """
499 Return the docstring for the given value; or C{None} if it
500 does not have a docstring.
501 @rtype: C{unicode}
502 """
503 docstring = getattr(value, '__doc__', None)
504 if docstring is None:
505 return None
506 elif isinstance(docstring, unicode):
507 return docstring
508 elif isinstance(docstring, str):
509 try: return unicode(docstring, 'ascii')
510 except UnicodeDecodeError:
511 module_name = get_containing_module(value)
512 if module_name is not None:
513 try:
514 module = get_value_from_name(module_name)
515 filename = py_src_filename(module.__file__)
516 encoding = epydoc.docparser.get_module_encoding(filename)
517 return unicode(docstring, encoding)
518 except KeyboardInterrupt: raise
519 except Exception: pass
520 if hasattr(value, '__name__'): name = value.__name__
521 else: name = `value`
522 log.warning("%s's docstring is not a unicode string, but it "
523 "contains non-ascii data -- treating it as "
524 "latin-1." % name)
525 return unicode(docstring, 'latin-1')
526 return None
527 elif value is BuiltinMethodType:
528
529 return None
530 else:
531 if hasattr(value, '__name__'): name = value.__name__
532 else: name = `value`
533 log.warning("%s's docstring is not a string -- ignoring it." %
534 name)
535 return None
536
538 """
539 @return: the canonical name for C{value}, or C{UNKNOWN} if no
540 canonical name can be found. Currently, C{get_canonical_name}
541 can find canonical names for: modules; functions; non-nested
542 classes; methods of non-nested classes; and some class methods
543 of non-nested classes.
544
545 @rtype: L{DottedName} or C{None}
546 """
547 if not hasattr(value, '__name__'): return UNKNOWN
548
549
550 if isinstance(value, ModuleType):
551 dotted_name = DottedName(value.__name__)
552
553 elif isinstance(value, (ClassType, TypeType)):
554 if value.__module__ == '__builtin__':
555 dotted_name = DottedName(value.__name__)
556 else:
557 dotted_name = DottedName(value.__module__, value.__name__)
558
559 elif (inspect.ismethod(value) and value.im_self is not None and
560 value.im_class is ClassType and
561 not value.__name__.startswith('<')):
562 class_name = get_canonical_name(value.im_self)
563 if class_name is None: return UNKNOWN
564 dotted_name = DottedName(class_name, value.__name__)
565 elif (inspect.ismethod(value) and
566 not value.__name__.startswith('<')):
567 class_name = get_canonical_name(value.im_class)
568 if class_name is None: return UNKNOWN
569 dotted_name = DottedName(class_name, value.__name__)
570 elif (isinstance(value, FunctionType) and
571 not value.__name__.startswith('<')):
572 module_name = _find_function_module(value)
573 if module_name is None: return UNKNOWN
574 dotted_name = DottedName(module_name, value.__name__)
575 else:
576 return UNKNOWN
577
578 return verify_name(value, dotted_name)
579
581 """
582 Verify the name. E.g., if it's a nested class, then we won't be
583 able to find it with the name we constructed.
584 """
585 if dotted_name == UNKNOWN: return UNKNOWN
586 if len(dotted_name) == 1 and hasattr(__builtin__, dotted_name[0]):
587 return dotted_name
588 named_value = sys.modules.get(dotted_name[0])
589 if named_value is None: return UNKNOWN
590 for identifier in dotted_name[1:]:
591 try: named_value = getattr(named_value, identifier)
592 except: return UNKNOWN
593 if value is named_value:
594 return dotted_name
595 else:
596 return UNKNOWN
597
598
607
609 """
610 Return the name of the module containing the given value, or
611 C{None} if the module name can't be determined.
612 @rtype: L{DottedName}
613 """
614 if inspect.ismodule(value):
615 return DottedName(value.__name__)
616 elif inspect.isclass(value):
617 return DottedName(value.__module__)
618 elif (inspect.ismethod(value) and value.im_self is not None and
619 value.im_class is ClassType):
620 return DottedName(value.im_self.__module__)
621 elif inspect.ismethod(value):
622 return DottedName(value.im_class.__module__)
623 elif inspect.isroutine(value):
624 module = _find_function_module(value)
625 if module is None: return None
626 return DottedName(module)
627 else:
628 return None
629
631 """
632 @return: The module that defines the given function.
633 @rtype: C{module}
634 @param func: The function whose module should be found.
635 @type func: C{function}
636 """
637 if hasattr(func, '__module__'):
638 return func.__module__
639 try:
640 module = inspect.getmodule(func)
641 if module: return module.__name__
642 except KeyboardInterrupt: raise
643 except: pass
644
645
646
647
648
649 for module in sys.modules.values():
650 if (hasattr(module, '__dict__') and
651 hasattr(func, 'func_globals') and
652 func.func_globals is module.__dict__):
653 return module.__name__
654 return None
655
656
657
658
659
660 _introspecter_registry = []
662 """
663 Register an introspecter function. Introspecter functions take
664 two arguments, a python value and a C{ValueDoc} object, and should
665 add information about the given value to the the C{ValueDoc}.
666 Usually, the first line of an inspecter function will specialize
667 it to a sublass of C{ValueDoc}, using L{ValueDoc.specialize_to()}:
668
669 >>> def typical_introspecter(value, value_doc):
670 ... value_doc.specialize_to(SomeSubclassOfValueDoc)
671 ... <add info to value_doc>
672
673 @param priority: The priority of this introspecter, which determines
674 the order in which introspecters are tried -- introspecters with lower
675 numbers are tried first. The standard introspecters have priorities
676 ranging from 20 to 30. The default priority (10) will place new
677 introspecters before standard introspecters.
678 """
679 _introspecter_registry.append( (priority, applicability_test,
680 introspecter) )
681 _introspecter_registry.sort()
682
689
690
694 register_introspecter(inspect.ismodule, introspect_module, priority=20)
695 register_introspecter(inspect.isclass, introspect_class, priority=24)
696 register_introspecter(inspect.isroutine, introspect_routine, priority=28)
697 register_introspecter(is_property, introspect_property, priority=30)
698
699
700
701
702
754
758
760 """
761 Given a name, return the corresponding value.
762
763 @param globals: A namespace to check for the value, if there is no
764 module containing the named value. Defaults to __builtin__.
765 """
766 name = DottedName(name)
767
768
769
770 try:
771 module = _import(name[0])
772 except ImportError, e:
773 if globs is None: globs = __builtin__.__dict__
774 if name[0] in globs:
775 try: return _lookup(globs[name[0]], name[1:])
776 except: raise e
777 else:
778 raise
779
780
781 for i in range(1, len(name)):
782 try: return _lookup(module, name[i:])
783 except ImportError: pass
784 module = _import('.'.join(name[:i+1]))
785 module = _lookup(module, name[1:i+1])
786 return module
787
789 val = module
790 for i, identifier in enumerate(name):
791 try: val = getattr(val, identifier)
792 except AttributeError:
793 exc_msg = ('no variable named %s in %s' %
794 (identifier, '.'.join(name[:1+i])))
795 raise ImportError(exc_msg)
796 return val
797
799 """
800 Run the given callable in a 'sandboxed' environment.
801 Currently, this includes saving and restoring the contents of
802 sys and __builtins__; and supressing stdin, stdout, and stderr.
803 """
804
805
806
807 old_sys = sys.__dict__.copy()
808 old_sys_path = sys.path[:]
809 old_builtins = __builtin__.__dict__.copy()
810
811
812
813 sys.path.insert(0, '')
814
815
816
817 sys.stdin = sys.stdout = sys.stderr = _dev_null
818 sys.__stdin__ = sys.__stdout__ = sys.__stderr__ = _dev_null
819
820
821 sys.argv = ['(imported)']
822
823 try:
824 try:
825 if filename is None:
826 return __import__(name)
827 else:
828
829 return imp.load_source(name, filename)
830 except KeyboardInterrupt: raise
831 except:
832 exc_typ, exc_val, exc_tb = sys.exc_info()
833 if exc_val is None:
834 estr = '%s' % (exc_typ,)
835 else:
836 estr = '%s: %s' % (exc_typ.__name__, exc_val)
837 if exc_tb.tb_next is not None:
838 estr += ' (line %d)' % (exc_tb.tb_next.tb_lineno,)
839 raise ImportError(estr)
840 finally:
841
842 __builtin__.__dict__.clear()
843 __builtin__.__dict__.update(old_builtins)
844 sys.__dict__.clear()
845 sys.__dict__.update(old_sys)
846 sys.path = old_sys_path
847
849 """
850 Try to determine the line number on which the given item's
851 docstring begins. Return the line number, or C{None} if the line
852 number can't be determined. The line number of the first line in
853 the file is 1.
854 """
855 if api_doc.docstring_lineno is not UNKNOWN:
856 return api_doc.docstring_lineno
857 if isinstance(api_doc, ValueDoc) and api_doc.pyval != UNKNOWN:
858 try:
859 lines, lineno = inspect.findsource(api_doc.pyval)
860 if not isinstance(api_doc, ModuleDoc): lineno += 1
861 for lineno in range(lineno, len(lines)):
862 if lines[lineno].split('#', 1)[0].strip():
863 api_doc.docstring_lineno = lineno + 1
864 return lineno + 1
865 except IOError: pass
866 except TypeError: pass
867 return None
868
870 """
871 A "file-like" object that discards anything that is written and
872 always reports end-of-file when read. C{_DevNull} is used by
873 L{_import()} to discard output when importing modules; and to
874 ensure that stdin appears closed.
875 """
877 self.closed = 1
878 self.mode = 'r+'
879 self.softspace = 0
880 self.name='</dev/null>'
883 - def read(self, size=0): return ''
886 - def seek(self, offset, whence=0): pass
887 - def tell(self): return 0L
889 - def write(self, str): pass
891 xreadlines = readlines
892 _dev_null = _DevNull()
893
894
895
896
897
898
899
900 0
901 """
902 ######################################################################
903 ## Zope Extension...
904 ######################################################################
905 class ZopeIntrospecter(Introspecter):
906 VALUEDOC_CLASSES = Introspecter.VALUEDOC_CLASSES.copy()
907 VALUEDOC_CLASSES.update({
908 'module': ZopeModuleDoc,
909 'class': ZopeClassDoc,
910 'interface': ZopeInterfaceDoc,
911 'attribute': ZopeAttributeDoc,
912 })
913
914 def add_module_child(self, child, child_name, module_doc):
915 if isinstance(child, zope.interfaces.Interface):
916 module_doc.add_zope_interface(child_name)
917 else:
918 Introspecter.add_module_child(self, child, child_name, module_doc)
919
920 def add_class_child(self, child, child_name, class_doc):
921 if isinstance(child, zope.interfaces.Interface):
922 class_doc.add_zope_interface(child_name)
923 else:
924 Introspecter.add_class_child(self, child, child_name, class_doc)
925
926 def introspect_zope_interface(self, interface, interfacename):
927 pass # etc...
928 """
929