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 docs_extracted_by='introspecter')
409 if public_names is not None:
410 var_doc.is_public = (child_name in public_names)
411 class_doc.variables[child_name] = var_doc
412
413 return class_doc
414
415
416
417
418
420 """Add API documentation information about the function
421 C{routine} to C{routine_doc} (specializing it to C{Routine_doc})."""
422 routine_doc.specialize_to(RoutineDoc)
423
424
425 if isinstance(routine, MethodType):
426 func = routine.im_func
427 elif isinstance(routine, staticmethod):
428 func = routine.__get__(0)
429 elif isinstance(routine, classmethod):
430 func = routine.__get__(0).im_func
431 else:
432 func = routine
433
434
435 routine_doc.docstring = get_docstring(func)
436
437
438 if isinstance(func, FunctionType):
439 (args, vararg, kwarg, defaults) = inspect.getargspec(func)
440
441
442 routine_doc.posargs = args
443 routine_doc.vararg = vararg
444 routine_doc.kwarg = kwarg
445
446
447 routine_doc.posarg_defaults = [None]*len(args)
448 if defaults is not None:
449 offset = len(args)-len(defaults)
450 for i in range(len(defaults)):
451 default_val = introspect_docs(defaults[i])
452 routine_doc.posarg_defaults[i+offset] = default_val
453
454
455 if isinstance(routine, MethodType) and routine.im_self is not None:
456 routine_doc.posargs = routine_doc.posargs[1:]
457 routine_doc.posarg_defaults = routine_doc.posarg_defaults[1:]
458
459
460 if hasattr(func, 'func_code'):
461 routine_doc.lineno = func.func_code.co_firstlineno
462
463 else:
464
465
466
467
468 routine_doc.posargs = ['...']
469 routine_doc.posarg_defaults = [None]
470 routine_doc.kwarg = None
471 routine_doc.vararg = None
472
473
474 if isinstance(routine, staticmethod):
475 routine_doc.specialize_to(StaticMethodDoc)
476 if isinstance(routine, classmethod):
477 routine_doc.specialize_to(ClassMethodDoc)
478
479 return routine_doc
480
481
482
483
484
500
501
502
503
504
509
510
511
512
513
515 """
516 Return true if the given object is a class. In particular, return
517 true if object is an instance of C{types.TypeType} or of
518 C{types.ClassType}. This is used instead of C{inspect.isclass()},
519 because the latter returns true for objects that are not classes
520 (in particular, it returns true for any object that has a
521 C{__bases__} attribute, including objects that define
522 C{__getattr__} to always return a value).
523 """
524 return isinstance(object, tuple(_CLASS_TYPES))
525
526 _CLASS_TYPES = set([TypeType, ClassType])
527 """A list of types that should be treated as classes."""
528
530 """Add a type to the lists of types that should be treated as
531 classes. By default, this list contains C{TypeType} and
532 C{ClassType}."""
533 _CLASS_TYPES.add(typ)
534
535 __future_check_works = None
536
559
561 """
562 Return the docstring for the given value; or C{None} if it
563 does not have a docstring.
564 @rtype: C{unicode}
565 """
566 docstring = getattr(value, '__doc__', None)
567 if docstring is None:
568 return None
569 elif isinstance(docstring, unicode):
570 return docstring
571 elif isinstance(docstring, str):
572 try: return unicode(docstring, 'ascii')
573 except UnicodeDecodeError:
574 if module_name is None:
575 module_name = get_containing_module(value)
576 if module_name is not None:
577 try:
578 module = get_value_from_name(module_name)
579 filename = py_src_filename(module.__file__)
580 encoding = epydoc.docparser.get_module_encoding(filename)
581 return unicode(docstring, encoding)
582 except KeyboardInterrupt: raise
583 except Exception: pass
584 if hasattr(value, '__name__'): name = value.__name__
585 else: name = repr(value)
586 log.warning("%s's docstring is not a unicode string, but it "
587 "contains non-ascii data -- treating it as "
588 "latin-1." % name)
589 return unicode(docstring, 'latin-1')
590 return None
591 elif value is BuiltinMethodType:
592
593 return None
594 else:
595 if hasattr(value, '__name__'): name = value.__name__
596 else: name = repr(value)
597 log.warning("%s's docstring is not a string -- ignoring it." %
598 name)
599 return None
600
602 """
603 @return: the canonical name for C{value}, or C{UNKNOWN} if no
604 canonical name can be found. Currently, C{get_canonical_name}
605 can find canonical names for: modules; functions; non-nested
606 classes; methods of non-nested classes; and some class methods
607 of non-nested classes.
608
609 @rtype: L{DottedName} or C{UNKNOWN}
610 """
611 if not hasattr(value, '__name__'): return UNKNOWN
612
613
614 if isinstance(value, ModuleType):
615 try:
616 dotted_name = DottedName(value.__name__, strict=strict)
617
618
619
620 if verify_name(value, dotted_name) is UNKNOWN:
621 log.warning("Module %s is shadowed by a variable with "
622 "the same name." % dotted_name)
623
624 return DottedName(value.__name__+"'")
625 except DottedName.InvalidDottedName:
626
627 if hasattr(value, '__file__'):
628 filename = '%s' % value.__str__
629 dotted_name = DottedName(munge_script_name(filename))
630
631 elif isclass(value):
632 if value.__module__ == '__builtin__':
633 dotted_name = DottedName(value.__name__, strict=strict)
634 else:
635 dotted_name = DottedName(value.__module__, value.__name__,
636 strict=strict)
637
638 elif (inspect.ismethod(value) and value.im_self is not None and
639 value.im_class is ClassType and
640 not value.__name__.startswith('<')):
641 class_name = get_canonical_name(value.im_self)
642 if class_name is UNKNOWN: return UNKNOWN
643 dotted_name = DottedName(class_name, value.__name__, strict=strict)
644 elif (inspect.ismethod(value) and
645 not value.__name__.startswith('<')):
646 class_name = get_canonical_name(value.im_class)
647 if class_name is UNKNOWN: return UNKNOWN
648 dotted_name = DottedName(class_name, value.__name__, strict=strict)
649 elif (isinstance(value, FunctionType) and
650 not value.__name__.startswith('<')):
651 module_name = _find_function_module(value)
652 if module_name is None: return UNKNOWN
653 dotted_name = DottedName(module_name, value.__name__, strict=strict)
654 else:
655 return UNKNOWN
656
657 return verify_name(value, dotted_name)
658
660 """
661 Verify the name. E.g., if it's a nested class, then we won't be
662 able to find it with the name we constructed.
663 """
664 if dotted_name is UNKNOWN: return UNKNOWN
665 if len(dotted_name) == 1 and hasattr(__builtin__, dotted_name[0]):
666 return dotted_name
667 named_value = sys.modules.get(dotted_name[0])
668 if named_value is None: return UNKNOWN
669 for identifier in dotted_name[1:]:
670 try: named_value = getattr(named_value, identifier)
671 except: return UNKNOWN
672 if value is named_value:
673 return dotted_name
674 else:
675 return UNKNOWN
676
677
686
688 """
689 Return the name of the module containing the given value, or
690 C{None} if the module name can't be determined.
691 @rtype: L{DottedName}
692 """
693 if inspect.ismodule(value):
694 return DottedName(value.__name__)
695 elif isclass(value):
696 return DottedName(value.__module__)
697 elif (inspect.ismethod(value) and value.im_self is not None and
698 value.im_class is ClassType):
699 return DottedName(value.im_self.__module__)
700 elif inspect.ismethod(value):
701 return DottedName(value.im_class.__module__)
702 elif inspect.isroutine(value):
703 module = _find_function_module(value)
704 if module is None: return None
705 return DottedName(module)
706 else:
707 return None
708
710 """
711 @return: The module that defines the given function.
712 @rtype: C{module}
713 @param func: The function whose module should be found.
714 @type func: C{function}
715 """
716 if hasattr(func, '__module__'):
717 return func.__module__
718 try:
719 module = inspect.getmodule(func)
720 if module: return module.__name__
721 except KeyboardInterrupt: raise
722 except: pass
723
724
725
726
727
728 for module in sys.modules.values():
729 if (hasattr(module, '__dict__') and
730 hasattr(func, 'func_globals') and
731 func.func_globals is module.__dict__):
732 return module.__name__
733 return None
734
735
736
737
738
739 _introspecter_registry = []
741 """
742 Register an introspecter function. Introspecter functions take
743 two arguments, a python value and a C{ValueDoc} object, and should
744 add information about the given value to the the C{ValueDoc}.
745 Usually, the first line of an inspecter function will specialize
746 it to a sublass of C{ValueDoc}, using L{ValueDoc.specialize_to()}:
747
748 >>> def typical_introspecter(value, value_doc):
749 ... value_doc.specialize_to(SomeSubclassOfValueDoc)
750 ... <add info to value_doc>
751
752 @param priority: The priority of this introspecter, which determines
753 the order in which introspecters are tried -- introspecters with lower
754 numbers are tried first. The standard introspecters have priorities
755 ranging from 20 to 30. The default priority (10) will place new
756 introspecters before standard introspecters.
757 """
758 _introspecter_registry.append( (priority, applicability_test,
759 introspecter) )
760 _introspecter_registry.sort()
761
768
769
773 register_introspecter(inspect.ismodule, introspect_module, priority=20)
774 register_introspecter(isclass, introspect_class, priority=24)
775 register_introspecter(inspect.isroutine, introspect_routine, priority=28)
776 register_introspecter(is_property, introspect_property, priority=30)
777
778
779 try:
780 import array
781 getset_type = type(array.array.typecode)
782 del array
783 - def is_getset(v): return isinstance(v, getset_type)
784 register_introspecter(is_getset, introspect_property, priority=32)
785 except:
786 pass
787
788
789 try:
790 import datetime
791 member_type = type(datetime.timedelta.days)
792 del datetime
793 - def is_member(v): return isinstance(v, member_type)
794 register_introspecter(is_member, introspect_property, priority=34)
795 except:
796 pass
797
798
799
800
801
853
857
859 """
860 Given a name, return the corresponding value.
861
862 @param globs: A namespace to check for the value, if there is no
863 module containing the named value. Defaults to __builtin__.
864 """
865 name = DottedName(name)
866
867
868
869 try:
870 module = _import(name[0])
871 except ImportError, e:
872 if globs is None: globs = __builtin__.__dict__
873 if name[0] in globs:
874 try: return _lookup(globs[name[0]], name[1:])
875 except: raise e
876 else:
877 raise
878
879
880 for i in range(1, len(name)):
881 try: return _lookup(module, name[i:])
882 except ImportError: pass
883 module = _import('.'.join(name[:i+1]))
884 module = _lookup(module, name[1:i+1])
885 return module
886
888 val = module
889 for i, identifier in enumerate(name):
890 try: val = getattr(val, identifier)
891 except AttributeError:
892 exc_msg = ('no variable named %s in %s' %
893 (identifier, '.'.join(name[:1+i])))
894 raise ImportError(exc_msg)
895 return val
896
898 """
899 Run the given callable in a 'sandboxed' environment.
900 Currently, this includes saving and restoring the contents of
901 sys and __builtins__; and suppressing stdin, stdout, and stderr.
902 """
903
904
905
906 old_sys = sys.__dict__.copy()
907 old_sys_path = sys.path[:]
908 old_builtins = __builtin__.__dict__.copy()
909
910
911
912
913
914 sys.path.append('')
915
916
917
918 sys.stdin = sys.stdout = sys.stderr = _dev_null
919 sys.__stdin__ = sys.__stdout__ = sys.__stderr__ = _dev_null
920
921
922 sys.argv = ['(imported)']
923
924 try:
925 try:
926 if filename is None:
927 return __import__(name)
928 else:
929
930 return imp.load_source(name, filename)
931 except KeyboardInterrupt: raise
932 except:
933 exc_typ, exc_val, exc_tb = sys.exc_info()
934 if exc_val is None:
935 estr = '%s' % (exc_typ,)
936 else:
937 estr = '%s: %s' % (exc_typ.__name__, exc_val)
938 if exc_tb.tb_next is not None:
939 estr += ' (line %d)' % (exc_tb.tb_next.tb_lineno,)
940 raise ImportError(estr)
941 finally:
942
943 __builtin__.__dict__.clear()
944 __builtin__.__dict__.update(old_builtins)
945 sys.__dict__.clear()
946 sys.__dict__.update(old_sys)
947 sys.path = old_sys_path
948
950 """
951 Try to determine the line number on which the given item's
952 docstring begins. Return the line number, or C{None} if the line
953 number can't be determined. The line number of the first line in
954 the file is 1.
955 """
956 if api_doc.docstring_lineno is not UNKNOWN:
957 return api_doc.docstring_lineno
958 if isinstance(api_doc, ValueDoc) and api_doc.pyval is not UNKNOWN:
959 try:
960 lines, lineno = inspect.findsource(api_doc.pyval)
961 if not isinstance(api_doc, ModuleDoc): lineno += 1
962 for lineno in range(lineno, len(lines)):
963 if lines[lineno].split('#', 1)[0].strip():
964 api_doc.docstring_lineno = lineno + 1
965 return lineno + 1
966 except IOError: pass
967 except TypeError: pass
968 except IndexError:
969 log.warning('inspect.findsource(%s) raised IndexError'
970 % api_doc.canonical_name)
971 return None
972
974 """
975 A "file-like" object that discards anything that is written and
976 always reports end-of-file when read. C{_DevNull} is used by
977 L{_import()} to discard output when importing modules; and to
978 ensure that stdin appears closed.
979 """
981 self.closed = 1
982 self.mode = 'r+'
983 self.softspace = 0
984 self.name='</dev/null>'
987 - def read(self, size=0): return ''
990 - def seek(self, offset, whence=0): pass
991 - def tell(self): return 0L
993 - def write(self, str): pass
995 xreadlines = readlines
996 _dev_null = _DevNull()
997
998
999
1000
1001
1002 try:
1003 from zope.interface.interface import InterfaceClass as _ZopeInterfaceClass
1004 register_class_type(_ZopeInterfaceClass)
1005 except:
1006 pass
1007
1008
1009
1010
1011
1012 try:
1013
1014 from ExtensionClass import ExtensionClass as _ExtensionClass
1015 _ZopeType = type(_ExtensionClass)
1018 register_introspecter(_is_zope_type, introspect_class)
1019
1020
1021 from ExtensionClass import PythonMethodType as _ZopeMethodType
1022 from ExtensionClass import ExtensionMethodType as _ZopeCMethodType
1024 return isinstance(val, (_ZopeMethodType, _ZopeCMethodType))
1025 register_introspecter(_is_zope_method, introspect_routine)
1026 except:
1027 pass
1028
1029
1030
1031
1032
1033 0
1034 """
1035 ######################################################################
1036 ## Zope Extension...
1037 ######################################################################
1038 class ZopeIntrospecter(Introspecter):
1039 VALUEDOC_CLASSES = Introspecter.VALUEDOC_CLASSES.copy()
1040 VALUEDOC_CLASSES.update({
1041 'module': ZopeModuleDoc,
1042 'class': ZopeClassDoc,
1043 'interface': ZopeInterfaceDoc,
1044 'attribute': ZopeAttributeDoc,
1045 })
1046
1047 def add_module_child(self, child, child_name, module_doc):
1048 if isinstance(child, zope.interfaces.Interface):
1049 module_doc.add_zope_interface(child_name)
1050 else:
1051 Introspecter.add_module_child(self, child, child_name, module_doc)
1052
1053 def add_class_child(self, child, child_name, class_doc):
1054 if isinstance(child, zope.interfaces.Interface):
1055 class_doc.add_zope_interface(child_name)
1056 else:
1057 Introspecter.add_class_child(self, child, child_name, class_doc)
1058
1059 def introspect_zope_interface(self, interface, interfacename):
1060 pass # etc...
1061 """
1062