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
275 child_val_doc = introspect_docs(child, context=module_doc,
276 module_name=dotted_name)
277 child_var_doc = VariableDoc(name=child_name,
278 value=child_val_doc,
279 is_imported=False,
280 container=module_doc,
281 docs_extracted_by='introspecter')
282 elif container is None or module_doc.canonical_name is UNKNOWN:
283
284
285 if is_future_feature(child): continue
286
287
288 child_val_doc = introspect_docs(child, context=module_doc)
289 child_var_doc = VariableDoc(name=child_name,
290 value=child_val_doc,
291 container=module_doc,
292 docs_extracted_by='introspecter')
293 else:
294
295 child_val_doc = _get_valuedoc(child)
296 child_var_doc = VariableDoc(name=child_name,
297 value=child_val_doc,
298 is_imported=True,
299 container=module_doc,
300 docs_extracted_by='introspecter')
301
302
303
304 if public_names is not None:
305 if child_name in public_names:
306 child_var_doc.is_public = True
307 if not isinstance(child_var_doc, ModuleDoc):
308 child_var_doc.is_imported = False
309 else:
310 child_var_doc.is_public = False
311
312 module_doc.variables[child_name] = child_var_doc
313
314 return module_doc
315
316
317
318
319
320
321
322 UNDOCUMENTED_CLASS_VARS = (
323 '__doc__', '__module__', '__dict__', '__weakref__', '__slots__',
324 '__pyx_vtable__')
325
327 """
328 Add API documentation information about the class C{cls}
329 to C{class_doc}.
330 """
331 class_doc.specialize_to(ClassDoc)
332
333
334 class_doc.docstring = get_docstring(cls)
335
336
337 public_names = None
338 if hasattr(cls, '__all__'):
339 try:
340 public_names = set([str(name) for name in cls.__all__])
341 except KeyboardInterrupt: raise
342 except: pass
343
344
345 class_doc.subclasses = []
346
347
348
349
350
351
352
353
354
355
356
357
358
359 base_children = {}
360
361
362
363 if hasattr(cls, '__bases__'):
364 try: bases = list(cls.__bases__)
365 except:
366 bases = None
367 log.warning("Class '%s' defines __bases__, but it does not "
368 "contain an iterable; ignoring base list."
369 % getattr(cls, '__name__', '??'))
370 if bases is not None:
371 class_doc.bases = []
372 for base in bases:
373 basedoc = introspect_docs(base)
374 class_doc.bases.append(basedoc)
375 basedoc.subclasses.append(class_doc)
376
377 bases.reverse()
378 for base in bases:
379 if hasattr(base, '__dict__'):
380 base_children.update(base.__dict__)
381
382
383
384 if module_name is None and class_doc.defining_module not in (None, UNKNOWN):
385 module_name = class_doc.defining_module.canonical_name
386
387
388 class_doc.variables = {}
389 if hasattr(cls, '__dict__'):
390 private_prefix = '_%s__' % getattr(cls, '__name__', '<none>')
391 for child_name, child in cls.__dict__.items():
392 if (child_name in base_children
393 and base_children[child_name] == child):
394 continue
395
396 if child_name.startswith(private_prefix):
397 child_name = child_name[len(private_prefix)-2:]
398 if child_name in UNDOCUMENTED_CLASS_VARS: continue
399 val_doc = introspect_docs(child, context=class_doc,
400 module_name=module_name)
401 var_doc = VariableDoc(name=child_name, value=val_doc,
402 container=class_doc,
403 docs_extracted_by='introspecter')
404 if public_names is not None:
405 var_doc.is_public = (child_name in public_names)
406 class_doc.variables[child_name] = var_doc
407
408 return class_doc
409
410
411
412
413
415 """Add API documentation information about the function
416 C{routine} to C{routine_doc} (specializing it to C{Routine_doc})."""
417 routine_doc.specialize_to(RoutineDoc)
418
419
420 if isinstance(routine, MethodType):
421 func = routine.im_func
422 elif isinstance(routine, staticmethod):
423 func = routine.__get__(0)
424 elif isinstance(routine, classmethod):
425 func = routine.__get__(0).im_func
426 else:
427 func = routine
428
429
430 routine_doc.docstring = get_docstring(func)
431
432
433 if isinstance(func, FunctionType):
434 (args, vararg, kwarg, defaults) = inspect.getargspec(func)
435
436
437 routine_doc.posargs = args
438 routine_doc.vararg = vararg
439 routine_doc.kwarg = kwarg
440
441
442 routine_doc.posarg_defaults = [None]*len(args)
443 if defaults is not None:
444 offset = len(args)-len(defaults)
445 for i in range(len(defaults)):
446 default_val = introspect_docs(defaults[i])
447 routine_doc.posarg_defaults[i+offset] = default_val
448
449
450 if isinstance(routine, MethodType) and routine.im_self is not None:
451 routine_doc.posargs = routine_doc.posargs[1:]
452 routine_doc.posarg_defaults = routine_doc.posarg_defaults[1:]
453
454
455 if hasattr(func, 'func_code'):
456 routine_doc.lineno = func.func_code.co_firstlineno
457
458 else:
459
460
461
462
463 routine_doc.posargs = ['...']
464 routine_doc.posarg_defaults = [None]
465 routine_doc.kwarg = None
466 routine_doc.vararg = None
467
468
469 if isinstance(routine, staticmethod):
470 routine_doc.specialize_to(StaticMethodDoc)
471 if isinstance(routine, classmethod):
472 routine_doc.specialize_to(ClassMethodDoc)
473
474 return routine_doc
475
476
477
478
479
495
496
497
498
499
504
505
506
507
508
510 """
511 Return true if the given object is a class. In particular, return
512 true if object is an instance of C{types.TypeType} or of
513 C{types.ClassType}. This is used instead of C{inspect.isclass()},
514 because the latter returns true for objects that are not classes
515 (in particular, it returns true for any object that has a
516 C{__bases__} attribute, including objects that define
517 C{__getattr__} to always return a value).
518 """
519 return isinstance(object, tuple(_CLASS_TYPES))
520
521 _CLASS_TYPES = set([TypeType, ClassType])
522 """A list of types that should be treated as classes."""
523
525 """Add a type to the lists of types that should be treated as
526 classes. By default, this list contains C{TypeType} and
527 C{ClassType}."""
528 _CLASS_TYPES.add(typ)
529
530 __future_check_works = None
531
554
556 """
557 Return the docstring for the given value; or C{None} if it
558 does not have a docstring.
559 @rtype: C{unicode}
560 """
561 docstring = getattr(value, '__doc__', None)
562 if docstring is None:
563 return None
564 elif isinstance(docstring, unicode):
565 return docstring
566 elif isinstance(docstring, str):
567 try: return unicode(docstring, 'ascii')
568 except UnicodeDecodeError:
569 if module_name is None:
570 module_name = get_containing_module(value)
571 if module_name is not None:
572 try:
573 module = get_value_from_name(module_name)
574 filename = py_src_filename(module.__file__)
575 encoding = epydoc.docparser.get_module_encoding(filename)
576 return unicode(docstring, encoding)
577 except KeyboardInterrupt: raise
578 except Exception: pass
579 if hasattr(value, '__name__'): name = value.__name__
580 else: name = repr(value)
581 log.warning("%s's docstring is not a unicode string, but it "
582 "contains non-ascii data -- treating it as "
583 "latin-1." % name)
584 return unicode(docstring, 'latin-1')
585 return None
586 elif value is BuiltinMethodType:
587
588 return None
589 else:
590 if hasattr(value, '__name__'): name = value.__name__
591 else: name = repr(value)
592 log.warning("%s's docstring is not a string -- ignoring it." %
593 name)
594 return None
595
597 """
598 @return: the canonical name for C{value}, or C{UNKNOWN} if no
599 canonical name can be found. Currently, C{get_canonical_name}
600 can find canonical names for: modules; functions; non-nested
601 classes; methods of non-nested classes; and some class methods
602 of non-nested classes.
603
604 @rtype: L{DottedName} or C{UNKNOWN}
605 """
606 if not hasattr(value, '__name__'): return UNKNOWN
607
608
609 if isinstance(value, ModuleType):
610 try:
611 dotted_name = DottedName(value.__name__, strict=strict)
612
613
614
615 if verify_name(value, dotted_name) is UNKNOWN:
616 log.warning("Module %s is shadowed by a variable with "
617 "the same name." % dotted_name)
618
619 return DottedName(value.__name__+"'")
620 except DottedName.InvalidDottedName:
621
622 if hasattr(value, '__file__'):
623 filename = '%s' % value.__str__
624 dotted_name = DottedName(munge_script_name(filename))
625
626 elif isclass(value):
627 if value.__module__ == '__builtin__':
628 dotted_name = DottedName(value.__name__, strict=strict)
629 else:
630 dotted_name = DottedName(value.__module__, value.__name__,
631 strict=strict)
632
633 elif (inspect.ismethod(value) and value.im_self is not None and
634 value.im_class is ClassType and
635 not value.__name__.startswith('<')):
636 class_name = get_canonical_name(value.im_self)
637 if class_name is UNKNOWN: return UNKNOWN
638 dotted_name = DottedName(class_name, value.__name__, strict=strict)
639 elif (inspect.ismethod(value) and
640 not value.__name__.startswith('<')):
641 class_name = get_canonical_name(value.im_class)
642 if class_name is UNKNOWN: return UNKNOWN
643 dotted_name = DottedName(class_name, value.__name__, strict=strict)
644 elif (isinstance(value, FunctionType) and
645 not value.__name__.startswith('<')):
646 module_name = _find_function_module(value)
647 if module_name is None: return UNKNOWN
648 dotted_name = DottedName(module_name, value.__name__, strict=strict)
649 else:
650 return UNKNOWN
651
652 return verify_name(value, dotted_name)
653
655 """
656 Verify the name. E.g., if it's a nested class, then we won't be
657 able to find it with the name we constructed.
658 """
659 if dotted_name is UNKNOWN: return UNKNOWN
660 if len(dotted_name) == 1 and hasattr(__builtin__, dotted_name[0]):
661 return dotted_name
662 named_value = sys.modules.get(dotted_name[0])
663 if named_value is None: return UNKNOWN
664 for identifier in dotted_name[1:]:
665 try: named_value = getattr(named_value, identifier)
666 except: return UNKNOWN
667 if value is named_value:
668 return dotted_name
669 else:
670 return UNKNOWN
671
672
681
683 """
684 Return the name of the module containing the given value, or
685 C{None} if the module name can't be determined.
686 @rtype: L{DottedName}
687 """
688 if inspect.ismodule(value):
689 return DottedName(value.__name__)
690 elif isclass(value):
691 return DottedName(value.__module__)
692 elif (inspect.ismethod(value) and value.im_self is not None and
693 value.im_class is ClassType):
694 return DottedName(value.im_self.__module__)
695 elif inspect.ismethod(value):
696 return DottedName(value.im_class.__module__)
697 elif inspect.isroutine(value):
698 module = _find_function_module(value)
699 if module is None: return None
700 return DottedName(module)
701 else:
702 return None
703
705 """
706 @return: The module that defines the given function.
707 @rtype: C{module}
708 @param func: The function whose module should be found.
709 @type func: C{function}
710 """
711 if hasattr(func, '__module__'):
712 return func.__module__
713 try:
714 module = inspect.getmodule(func)
715 if module: return module.__name__
716 except KeyboardInterrupt: raise
717 except: pass
718
719
720
721
722
723 for module in sys.modules.values():
724 if (hasattr(module, '__dict__') and
725 hasattr(func, 'func_globals') and
726 func.func_globals is module.__dict__):
727 return module.__name__
728 return None
729
730
731
732
733
734 _introspecter_registry = []
736 """
737 Register an introspecter function. Introspecter functions take
738 two arguments, a python value and a C{ValueDoc} object, and should
739 add information about the given value to the the C{ValueDoc}.
740 Usually, the first line of an inspecter function will specialize
741 it to a sublass of C{ValueDoc}, using L{ValueDoc.specialize_to()}:
742
743 >>> def typical_introspecter(value, value_doc):
744 ... value_doc.specialize_to(SomeSubclassOfValueDoc)
745 ... <add info to value_doc>
746
747 @param priority: The priority of this introspecter, which determines
748 the order in which introspecters are tried -- introspecters with lower
749 numbers are tried first. The standard introspecters have priorities
750 ranging from 20 to 30. The default priority (10) will place new
751 introspecters before standard introspecters.
752 """
753 _introspecter_registry.append( (priority, applicability_test,
754 introspecter) )
755 _introspecter_registry.sort()
756
763
764
768 register_introspecter(inspect.ismodule, introspect_module, priority=20)
769 register_introspecter(isclass, introspect_class, priority=24)
770 register_introspecter(inspect.isroutine, introspect_routine, priority=28)
771 register_introspecter(is_property, introspect_property, priority=30)
772
773
774 try:
775 import array
776 getset_type = type(array.array.typecode)
777 del array
778 - def is_getset(v): return isinstance(v, getset_type)
779 register_introspecter(is_getset, introspect_property, priority=32)
780 except:
781 pass
782
783
784 try:
785 import datetime
786 member_type = type(datetime.timedelta.days)
787 del datetime
788 - def is_member(v): return isinstance(v, member_type)
789 register_introspecter(is_member, introspect_property, priority=34)
790 except:
791 pass
792
793
794
795
796
848
852
854 """
855 Given a name, return the corresponding value.
856
857 @param globs: A namespace to check for the value, if there is no
858 module containing the named value. Defaults to __builtin__.
859 """
860 name = DottedName(name)
861
862
863
864 try:
865 module = _import(name[0])
866 except ImportError, e:
867 if globs is None: globs = __builtin__.__dict__
868 if name[0] in globs:
869 try: return _lookup(globs[name[0]], name[1:])
870 except: raise e
871 else:
872 raise
873
874
875 for i in range(1, len(name)):
876 try: return _lookup(module, name[i:])
877 except ImportError: pass
878 module = _import('.'.join(name[:i+1]))
879 module = _lookup(module, name[1:i+1])
880 return module
881
883 val = module
884 for i, identifier in enumerate(name):
885 try: val = getattr(val, identifier)
886 except AttributeError:
887 exc_msg = ('no variable named %s in %s' %
888 (identifier, '.'.join(name[:1+i])))
889 raise ImportError(exc_msg)
890 return val
891
893 """
894 Run the given callable in a 'sandboxed' environment.
895 Currently, this includes saving and restoring the contents of
896 sys and __builtins__; and suppressing stdin, stdout, and stderr.
897 """
898
899
900
901 old_sys = sys.__dict__.copy()
902 old_sys_path = sys.path[:]
903 old_builtins = __builtin__.__dict__.copy()
904
905
906
907
908
909 sys.path.append('')
910
911
912
913 sys.stdin = sys.stdout = sys.stderr = _dev_null
914 sys.__stdin__ = sys.__stdout__ = sys.__stderr__ = _dev_null
915
916
917 sys.argv = ['(imported)']
918
919 try:
920 try:
921 if filename is None:
922 return __import__(name)
923 else:
924
925 return imp.load_source(name, filename)
926 except KeyboardInterrupt: raise
927 except:
928 exc_typ, exc_val, exc_tb = sys.exc_info()
929 if exc_val is None:
930 estr = '%s' % (exc_typ,)
931 else:
932 estr = '%s: %s' % (exc_typ.__name__, exc_val)
933 if exc_tb.tb_next is not None:
934 estr += ' (line %d)' % (exc_tb.tb_next.tb_lineno,)
935 raise ImportError(estr)
936 finally:
937
938 __builtin__.__dict__.clear()
939 __builtin__.__dict__.update(old_builtins)
940 sys.__dict__.clear()
941 sys.__dict__.update(old_sys)
942 sys.path = old_sys_path
943
945 """
946 Try to determine the line number on which the given item's
947 docstring begins. Return the line number, or C{None} if the line
948 number can't be determined. The line number of the first line in
949 the file is 1.
950 """
951 if api_doc.docstring_lineno is not UNKNOWN:
952 return api_doc.docstring_lineno
953 if isinstance(api_doc, ValueDoc) and api_doc.pyval is not UNKNOWN:
954 try:
955 lines, lineno = inspect.findsource(api_doc.pyval)
956 if not isinstance(api_doc, ModuleDoc): lineno += 1
957 for lineno in range(lineno, len(lines)):
958 if lines[lineno].split('#', 1)[0].strip():
959 api_doc.docstring_lineno = lineno + 1
960 return lineno + 1
961 except IOError: pass
962 except TypeError: pass
963 except IndexError:
964 log.warning('inspect.findsource(%s) raised IndexError'
965 % api_doc.canonical_name)
966 return None
967
969 """
970 A "file-like" object that discards anything that is written and
971 always reports end-of-file when read. C{_DevNull} is used by
972 L{_import()} to discard output when importing modules; and to
973 ensure that stdin appears closed.
974 """
976 self.closed = 1
977 self.mode = 'r+'
978 self.softspace = 0
979 self.name='</dev/null>'
982 - def read(self, size=0): return ''
985 - def seek(self, offset, whence=0): pass
986 - def tell(self): return 0L
988 - def write(self, str): pass
990 xreadlines = readlines
991 _dev_null = _DevNull()
992
993
994
995
996
997 try:
998 from zope.interface.interface import InterfaceClass as _ZopeInterfaceClass
999 register_class_type(_ZopeInterfaceClass)
1000 except:
1001 pass
1002
1003
1004
1005
1006
1007 try:
1008
1009 from ExtensionClass import ExtensionClass as _ExtensionClass
1010 _ZopeType = type(_ExtensionClass)
1013 register_introspecter(_is_zope_type, introspect_class)
1014
1015
1016 from ExtensionClass import PythonMethodType as _ZopeMethodType
1017 from ExtensionClass import ExtensionMethodType as _ZopeCMethodType
1019 return isinstance(val, (_ZopeMethodType, _ZopeCMethodType))
1020 register_introspecter(_is_zope_method, introspect_routine)
1021 except:
1022 pass
1023
1024
1025
1026
1027
1028 0
1029 """
1030 ######################################################################
1031 ## Zope Extension...
1032 ######################################################################
1033 class ZopeIntrospecter(Introspecter):
1034 VALUEDOC_CLASSES = Introspecter.VALUEDOC_CLASSES.copy()
1035 VALUEDOC_CLASSES.update({
1036 'module': ZopeModuleDoc,
1037 'class': ZopeClassDoc,
1038 'interface': ZopeInterfaceDoc,
1039 'attribute': ZopeAttributeDoc,
1040 })
1041
1042 def add_module_child(self, child, child_name, module_doc):
1043 if isinstance(child, zope.interfaces.Interface):
1044 module_doc.add_zope_interface(child_name)
1045 else:
1046 Introspecter.add_module_child(self, child, child_name, module_doc)
1047
1048 def add_class_child(self, child, child_name, class_doc):
1049 if isinstance(child, zope.interfaces.Interface):
1050 class_doc.add_zope_interface(child_name)
1051 else:
1052 Introspecter.add_class_child(self, child, child_name, class_doc)
1053
1054 def introspect_zope_interface(self, interface, interfacename):
1055 pass # etc...
1056 """
1057