1
2
3
4
5
6
7
8
9 """
10 Extract API documentation about python objects by directly introspecting
11 their values.
12
13 The function L{introspect_docs()}, which provides the main interface
14 of this module, examines a Python objects via introspection, and uses
15 the information it finds to create an L{APIDoc} objects containing the
16 API documentation for that objects.
17
18 The L{register_introspecter()} method can be used to extend the
19 functionality of C{docintrospector}, by providing methods that handle
20 special value types.
21 """
22 __docformat__ = 'epytext en'
23
24
25
26
27
28 import inspect, re, sys, os.path, imp
29
30 from epydoc.apidoc import *
31
32 from types import *
33
34 from epydoc import log
35
36 from epydoc.util import *
37
38 import epydoc.docparser
39
40 import __builtin__
41
42 from epydoc.compat import *
43
44
45
46
47
48 _valuedoc_cache = {}
49 """A cache containing the API documentation for values that we've
50 already seen. This cache is implemented as a dictionary that maps a
51 value's pyid to its L{ValueDoc}.
52
53 Note that if we encounter a value but decide not to introspect it
54 (because it's imported from another module), then C{_valuedoc_cache}
55 will contain an entry for the value, but the value will not be listed
56 in L{_introspected_values}."""
57
58 _introspected_values = {}
59 """A record which values we've introspected, encoded as a dictionary from
60 pyid to C{bool}."""
61
69
70
71
72
73
74 -def introspect_docs(value=None, name=None, filename=None, context=None,
75 is_script=False, module_name=None):
76 """
77 Generate the API documentation for a specified object by
78 introspecting Python values, and return it as a L{ValueDoc}. The
79 object to generate documentation for may be specified using
80 the C{value} parameter, the C{filename} parameter, I{or} the
81 C{name} parameter. (It is an error to specify more than one
82 of these three parameters, or to not specify any of them.)
83
84 @param value: The python object that should be documented.
85 @param filename: The name of the file that contains the python
86 source code for a package, module, or script. If
87 C{filename} is specified, then C{introspect} will return a
88 C{ModuleDoc} describing its contents.
89 @param name: The fully-qualified python dotted name of any
90 value (including packages, modules, classes, and
91 functions). C{DocParser} will automatically figure out
92 which module(s) it needs to import in order to find the
93 documentation for the specified object.
94 @param context: The API documentation for the class of module
95 that contains C{value} (if available).
96 @param module_name: The name of the module where the value is defined.
97 Useful to retrieve the docstring encoding if there is no way to
98 detect the module by introspection (such as in properties)
99 """
100 if value is None and name is not None and filename is None:
101 value = get_value_from_name(DottedName(name))
102 elif value is None and name is None and filename is not None:
103 if is_script:
104 value = get_value_from_scriptname(filename)
105 else:
106 value = get_value_from_filename(filename, context)
107 elif name is None and filename is None:
108
109 pass
110 else:
111 raise ValueError("Expected exactly one of the following "
112 "arguments: value, name, filename")
113
114 pyid = id(value)
115
116
117
118 if pyid in _introspected_values:
119
120 if is_script and filename is not None:
121 _valuedoc_cache[pyid].canonical_name = DottedName(
122 munge_script_name(str(filename)))
123 return _valuedoc_cache[pyid]
124
125
126 val_doc = _get_valuedoc(value)
127
128
129 _introspected_values[pyid] = True
130 introspect_func = _get_introspecter(value)
131 introspect_func(value, val_doc, module_name=module_name)
132
133
134 if val_doc.canonical_name is UNKNOWN and name is not None:
135 val_doc.canonical_name = DottedName(name)
136
137
138 if is_script and filename is not None:
139 val_doc.canonical_name = DottedName(munge_script_name(str(filename)))
140
141 if val_doc.canonical_name is UNKNOWN and filename is not None:
142 shadowed_name = DottedName(value.__name__)
143 log.warning("Module %s is shadowed by a variable with "
144 "the same name." % shadowed_name)
145 val_doc.canonical_name = DottedName(str(shadowed_name)+"'")
146
147 return val_doc
148
150 """
151 If a C{ValueDoc} for the given value exists in the valuedoc
152 cache, then return it; otherwise, create a new C{ValueDoc},
153 add it to the cache, and return it. When possible, the new
154 C{ValueDoc}'s C{pyval}, C{repr}, and C{canonical_name}
155 attributes will be set appropriately.
156 """
157 pyid = id(value)
158 val_doc = _valuedoc_cache.get(pyid)
159 if val_doc is None:
160 try: canonical_name = get_canonical_name(value, strict=True)
161 except DottedName.InvalidDottedName: canonical_name = UNKNOWN
162 val_doc = ValueDoc(pyval=value, canonical_name = canonical_name,
163 docs_extracted_by='introspecter')
164 _valuedoc_cache[pyid] = val_doc
165
166
167
168
169 if inspect.ismodule(value):
170 introspect_module(value, val_doc, preliminary=True)
171 val_doc.defining_module = val_doc
172 else:
173 module_name = str(get_containing_module(value))
174 module = sys.modules.get(module_name)
175 if module is not None and inspect.ismodule(module):
176 val_doc.defining_module = _get_valuedoc(module)
177
178 return val_doc
179
180
181
182
183
184
185
186 UNDOCUMENTED_MODULE_VARS = (
187 '__builtins__', '__doc__', '__all__', '__file__', '__path__',
188 '__name__', '__extra_epydoc_fields__', '__docformat__')
189
191 """
192 Add API documentation information about the module C{module}
193 to C{module_doc}.
194 """
195 module_doc.specialize_to(ModuleDoc)
196
197
198 if hasattr(module, '__docformat__'):
199 module_doc.docformat = unicode(module.__docformat__)
200
201
202 if hasattr(module, '__file__'):
203 try: module_doc.filename = unicode(module.__file__)
204 except KeyboardInterrupt: raise
205 except: pass
206 if module_doc.filename is not UNKNOWN:
207 try: module_doc.filename = py_src_filename(module_doc.filename)
208 except ValueError: pass
209
210
211
212
213
214 module_doc.variables = {}
215 if preliminary: return
216
217
218 if hasattr(module, '__doc__'):
219 module_doc.docstring = get_docstring(module)
220
221
222
223 if hasattr(module, '__path__'):
224 module_doc.is_package = True
225 try: module_doc.path = [unicode(p) for p in module.__path__]
226 except KeyboardInterrupt: raise
227 except: pass
228 else:
229 module_doc.is_package = False
230
231
232 dotted_name = module_doc.canonical_name
233 if dotted_name is UNKNOWN:
234 dotted_name = DottedName(module.__name__)
235 name_without_primes = DottedName(str(dotted_name).replace("'", ""))
236
237
238 if len(dotted_name) > 1:
239 package_name = str(dotted_name.container())
240 package = sys.modules.get(package_name)
241 if package is not None:
242 module_doc.package = introspect_docs(package)
243 else:
244 module_doc.package = None
245
246
247 module_doc.submodules = []
248
249
250 if module_doc.package not in (None, UNKNOWN):
251 module_doc.package.submodules.append(module_doc)
252
253
254 public_names = None
255 if hasattr(module, '__all__'):
256 try:
257 public_names = set([str(name) for name in module.__all__])
258 except KeyboardInterrupt: raise
259 except: pass
260
261
262 module_doc.variables = {}
263 for child_name in dir(module):
264 if child_name in UNDOCUMENTED_MODULE_VARS: continue
265 child = getattr(module, child_name)
266
267
268
269 container = get_containing_module(child)
270 if (((container is not None and
271 container == name_without_primes) or
272 (public_names is not None and
273 child_name in public_names))
274 and not inspect.ismodule(child)):
275
276 child_val_doc = introspect_docs(child, context=module_doc,
277 module_name=dotted_name)
278 child_var_doc = VariableDoc(name=child_name,
279 value=child_val_doc,
280 is_imported=False,
281 container=module_doc,
282 docs_extracted_by='introspecter')
283 elif ((container is None or module_doc.canonical_name is UNKNOWN)
284 and not inspect.ismodule(child)):
285
286
287 if is_future_feature(child): continue
288
289
290 child_val_doc = introspect_docs(child, context=module_doc)
291 child_var_doc = VariableDoc(name=child_name,
292 value=child_val_doc,
293 container=module_doc,
294 docs_extracted_by='introspecter')
295 else:
296
297 child_val_doc = _get_valuedoc(child)
298 child_var_doc = VariableDoc(name=child_name,
299 value=child_val_doc,
300 is_imported=True,
301 container=module_doc,
302 docs_extracted_by='introspecter')
303
304
305
306 if public_names is not None:
307 if child_name in public_names:
308 child_var_doc.is_public = True
309 if not isinstance(child_var_doc, ModuleDoc):
310 child_var_doc.is_imported = False
311 else:
312 child_var_doc.is_public = False
313
314 module_doc.variables[child_name] = child_var_doc
315
316 return module_doc
317
318
319
320
321
322
323
324 UNDOCUMENTED_CLASS_VARS = (
325 '__doc__', '__module__', '__dict__', '__weakref__', '__slots__',
326 '__pyx_vtable__', '__metaclass__')
327
329 """
330 Add API documentation information about the class C{cls}
331 to C{class_doc}.
332 """
333 class_doc.specialize_to(ClassDoc)
334
335
336 class_doc.docstring = get_docstring(cls)
337
338
339 public_names = None
340 if hasattr(cls, '__all__'):
341 try:
342 public_names = set([str(name) for name in cls.__all__])
343 except KeyboardInterrupt: raise
344 except: pass
345
346
347 class_doc.metaclass = introspect_docs(type(cls))
348
349
350 class_doc.subclasses = []
351
352
353
354
355
356
357
358
359
360
361
362
363
364 base_children = {}
365
366
367
368 if hasattr(cls, '__bases__'):
369 try: bases = list(cls.__bases__)
370 except:
371 bases = None
372 log.warning("Class '%s' defines __bases__, but it does not "
373 "contain an iterable; ignoring base list."
374 % getattr(cls, '__name__', '??'))
375 if bases is not None:
376 class_doc.bases = []
377 for base in bases:
378 basedoc = introspect_docs(base)
379 class_doc.bases.append(basedoc)
380 basedoc.subclasses.append(class_doc)
381
382 bases.reverse()
383 for base in bases:
384 if hasattr(base, '__dict__'):
385 base_children.update(base.__dict__)
386
387
388
389 if module_name is None and class_doc.defining_module not in (None, UNKNOWN):
390 module_name = class_doc.defining_module.canonical_name
391
392
393 class_doc.variables = {}
394 if hasattr(cls, '__dict__'):
395 private_prefix = '_%s__' % getattr(cls, '__name__', '<none>')
396 for child_name, child in cls.__dict__.items():
397 if (child_name in base_children
398 and base_children[child_name] == child):
399 continue
400
401 if child_name.startswith(private_prefix):
402 child_name = child_name[len(private_prefix)-2:]
403 if child_name in UNDOCUMENTED_CLASS_VARS: continue
404 val_doc = introspect_docs(child, context=class_doc,
405 module_name=module_name)
406 var_doc = VariableDoc(name=child_name, value=val_doc,
407 container=class_doc,
408