Index: src/epydoc/objdoc.py =================================================================== RCS file: /cvsroot/epydoc/epydoc/src/epydoc/objdoc.py,v retrieving revision 1.87 diff -u -4 -r1.87 objdoc.py --- src/epydoc/objdoc.py 24 Apr 2004 15:57:30 -0000 1.87 +++ src/epydoc/objdoc.py 26 Apr 2004 21:25:17 -0000 @@ -1156,8 +1156,20 @@ # If mod is a package, then it will contain a __path__ if mod.__dict__.has_key('__path__'): self._modules = [] else: self._modules = None + # check for a __docfilter__ + if mod.__dict__.has_key('__docfilter__'): + self._docfilter = mod.__docfilter__ + else: + self._docfilter = None + + # and __all__ + if mod.__dict__.has_key('__all__'): + self._all = mod.__all__ + else: + self._all = [] + # Handle functions, classes, and variables. self._classes = [] self._functions = [] self._variables = [] @@ -1165,18 +1177,32 @@ self._imported_functions = [] self._imported_variables = [] self._imported_modules = [] for (field, val) in mod.__dict__.items(): - vuid = make_uid(val, self._uid, field) - # Don't do anything for these special variables: if field in ('__builtins__', '__doc__', '__all__', '__file__', '__path__', '__name__', - '__extra_epydoc_fields__', '__docformat__'): + '__extra_epydoc_fields__', '__docformat__', + '__docfilter__'): continue + + # Don't do anything if the filter rejects field + if self._docfilter is not None and not self._docfilter(field): + continue + + # make a uid for the object + vuid = make_uid(val, self._uid, field) + # Don't do anything if we can't get a UID. if vuid is None: continue - + + # if the name appears in __all__ then make it look like it + # belongs to this module even if it doesn't + if field in self._all and not vuid.is_module() and vuid.module() != self._uid: + vuid._name = self._uid.name() + '.' + vuid.shortname() + vuid._module = self._uid + vuid._public = True + # Record imported modules. if vuid.is_module(): self._imported_modules.append(Link(field, vuid)) @@ -1347,9 +1373,9 @@ # Any explicit (non-autogenerated) variables are also # considierd to be "defined." for var in self._variables: - if not var.autogenerated(): + if var.name() in self._all or not var.autogenerated(): defined_variables[var.name()] = 1 # Go through our list of variables. Move any variables that # were *not* defined by a top-level statement to the @@ -2196,22 +2222,12 @@ self._raises = [] self._overrides = None self._matches_override = 0 - docstring = _getdoc(func) # Initialize the signature if uid.is_method(): func = func.im_func - if type(func) is types.FunctionType: - self._init_signature(func) - elif uid.is_routine(): - # If there's a builtin signature, then just parse it; - # don't include it in the description. - if self._init_builtin_signature(func): - if '\n' in docstring: - docstring = docstring.split('\n', 1)[1] - else: - raise TypeError("Can't document %s" % func) + docstring = self._init_signature(func) # These are used to keep track of params & keyword arguments # while processing fields; we can delete them when we're done. self._tmp_param = {} @@ -2247,53 +2263,60 @@ # The function name (must match exactly) r'(?P\w+)' + - # The parameters - r'\((?P(\s*\[?\s*[\w\-\.]+(=.+?)?'+ - r'(\s*\[?\s*,\s*\]?\s*[\w\-\.]+(=.+?)?)*\]*)?)\s*\)' + + # The parameters, with optional types + r'\((?P(\s*\[?\s*\w*\s*[\w\-\.]+(=.+?)?'+ + r'(\s*\[?\s*,\s*\]?\s*\w*\s*[\w\-\.]+(=.+?)?)*\]*)?)\s*\)' + # The return value (optional) r'(\s*(->|<=+>)\s*(?P\S.*?))?'+ # The end marker r'\s*(\n|\s+--\s+|$|\.\s|\.\n)') - def _init_builtin_signature(self, func): + def _init_signature(self, func): """ - Construct the signature for a builtin function or method from - its docstring. If the docstring uses the standard convention - of including a signature in the first line of the docstring - (and formats that signature according to standard - conventions), then it will be used to extract a signature. - Otherwise, the signature will be set to a single varargs - variable named C{"..."}. + Construct the signature for a function or method from its + docstring. If the docstring uses the standard convention of + including a signature in the first line of the docstring (and + formats that signature according to standard conventions), + then it will be used to extract a signature. Otherwise, + introspection will be used to get the details of the + parameters and etc. If that is not possible then the + signature will be set to a single varargs variable named C{"..."}. @rtype: C{None} """ + docstring = _getdoc(func) self._params = [] self._kwarg_param = None self._vararg_param = None self._return = Param('return') - m = FuncDoc._SIGNATURE_RE.match(_getdoc(func) or '') + # first check if there is a matching signature at the begining + # of the docstring + m = FuncDoc._SIGNATURE_RE.match(docstring or '') if m and m.group('func') == func.__name__: + params = m.group('params') rtype = m.group('return') selfparam = m.group('self') - - if selfparam and not rtype: - self._vararg_param = Param('...') - return 0 + + # i don't think this is an error??? + #if selfparam and not rtype and not self._introspect_signature(func): + # self._vararg_param = Param('...') + # return docstring # Extract the parameters from the signature. if params: # Figure out which parameters are optional. while '[' in params or ']' in params: m2 = re.match(r'(.*)\[([^\[\]]+)\](.*)', params) if not m2: - self._vararg_param = Param('...') - return 0 + if not self._introspect_signature(func): + self._vararg_param = Param('...') + return docstring (start, mid, end) = m2.groups() mid = re.sub(r'((,|^)\s*[\w\-\.]+)', r'\1=...', mid) params = start+mid+end @@ -2301,16 +2324,19 @@ for name in params.split(','): if '=' in name: (name, default) = name.split('=',1) else: default = None name = name.strip() + if ' ' in name: (ptype, name) = name.split(' ',1) + else: ptype = None + if ptype: ptype = markup.parse(ptype, verbatim=0) if name == '...': - self._vararg_param = Param('...', default=default) + self._vararg_param = Param('...', default=default, type=ptype) elif name.startswith('**'): - self._kwarg_param = Param(name[1:], default=default) + self._kwarg_param = Param(name[1:], default=default, type=ptype) elif name.startswith('*'): - self._vararg_param = Param(name[1:], default=default) + self._vararg_param = Param(name[1:], default=default, type=ptype) else: - self._params.append(Param(name, default=default)) + self._params.append(Param(name, default=default, type=ptype)) # Extract the return type/value from the signature if rtype: if selfparam: self._return.set_descr(markup.parse(rtype)) @@ -2319,27 +2345,36 @@ # Add the self parameter, if it was specified. if selfparam: self._params.insert(0, Param(selfparam)) - # We found a signature. - return 1 - - else: - # We couldn't parse the signature. + # trim the signature out of the docstring + docstring = docstring[m.end():] + + # if no match then use introspection if possible + elif not self._introspect_signature(func): + # otherwise just set a generic value self._vararg_param = Param('...') - return 0 + #raise TypeError("Can't document %s" % func) - def _init_signature(self, func): - # Get the function's signature - (args, vararg, kwarg, defaults) = inspect.getargspec(func) + return docstring - # Construct argument/return Variables. - self._params = self._params_to_vars(args, defaults) - if vararg: self._vararg_param = Param(vararg) - else: self._vararg_param = None - if kwarg: self._kwarg_param = Param(kwarg) - else: self._kwarg_param = None - self._return = Param('return') + + def _introspect_signature(self, func): + if type(func) is types.FunctionType: + # Get the function's signature + (args, vararg, kwarg, defaults) = inspect.getargspec(func) + + # Construct argument/return Variables. + self._params = self._params_to_vars(args, defaults) + if vararg: self._vararg_param = Param(vararg) + else: self._vararg_param = None + if kwarg: self._kwarg_param = Param(kwarg) + else: self._kwarg_param = None + self._return = Param('return') + return True + else: + return False + def _params_to_vars(self, params, defaults): vars = [] if defaults == None: defaults = [] Index: src/epydoc/uid.py =================================================================== RCS file: /cvsroot/epydoc/epydoc/src/epydoc/uid.py,v retrieving revision 1.52 diff -u -4 -r1.52 uid.py --- src/epydoc/uid.py 18 Apr 2004 04:17:24 -0000 1.52 +++ src/epydoc/uid.py 26 Apr 2004 21:25:18 -0000 @@ -524,19 +524,19 @@ def cls(self): if not hasattr(self, '_cls'): obj = self._obj if type(obj) in (_MethodType, _ZopeMethodType, _ZopeCMethodType): - self._cls = ObjectUID(obj.im_class) + self._cls = make_uid(obj.im_class) elif (type(obj) is _BuiltinMethodType and obj.__self__ is not None): if obj.__name__ == '__new__': # __new__ is a class method of sorts - self._cls = ObjectUID(obj.__self__) + self._cls = make_uid(obj.__self__) else: - self._cls = ObjectUID(type(obj.__self__)) + self._cls = make_uid(type(obj.__self__)) elif type(obj) in (_WrapperDescriptorType, _MethodDescriptorType): - self._cls = ObjectUID(obj.__objclass__) + self._cls = make_uid(obj.__objclass__) else: self._cls = None return self._cls @@ -548,54 +548,54 @@ try: if typ is _ModuleType: return None if typ is _ClassType: - self._module = ObjectUID(import_module(obj.__module__)) + self._module = make_uid(import_module(obj.__module__)) elif typ is _ZopeType: if hasattr(obj, '__module__'): - self._module = ObjectUID(import_module(obj.__module__)) + self._module = make_uid(import_module(obj.__module__)) else: # We have a non-wrapped base C Class. if (hasattr(obj, '__doc__') and hasattr(obj, '__name__') and obj.__name__ == obj.__doc__): - return ObjectUID(import_module('ExtensionClass')) + return make_uid(import_module('ExtensionClass')) else: raise ValueError, 'Malformed Zope base class!' elif typ is _FunctionType: - self._module = ObjectUID(_find_function_module(obj)) + self._module = make_uid(_find_function_module(obj)) elif typ in (_MethodType, _ZopeMethodType, _ZopeCMethodType): - self._module = ObjectUID(obj.im_class).module() + self._module = make_uid(obj.im_class).module() elif typ is _BuiltinFunctionType and obj.__self__ is None: module = _find_builtin_obj_module(obj) if module is None: self._module = None - else: self._module = ObjectUID(module) + else: self._module = make_uid(module) elif typ is _BuiltinMethodType and obj.__self__ is not None: cls = type(obj.__self__) module = _find_builtin_obj_module(cls) if module is None: self._module = None - else: self._module = ObjectUID(module) + else: self._module = make_uid(module) elif typ in (_WrapperDescriptorType, _MethodDescriptorType): cls = obj.__objclass__ module = _find_builtin_obj_module(cls) if module is None: self._module = None - else: self._module = ObjectUID(module) + else: self._module = make_uid(module) elif (isinstance(obj, _TypeType) and hasattr(obj, '__module__')): - self._module = ObjectUID(import_module(obj.__module__)) + self._module = make_uid(import_module(obj.__module__)) if self._module is not None: for val in self._module.value().__dict__.values(): if val is obj: break else: # The __module__ attribute lied; try # finding it ourselves. module = _find_builtin_obj_module(obj) if module is not None: - self._module = ObjectUID(module) + self._module = make_uid(module) elif isinstance(obj, _TypeType): module = _find_builtin_obj_module(obj) if module is None: self._module = None - else: self._module = ObjectUID(module) + else: self._module = make_uid(module) else: raise ValueError("Can't find module for %r" % self._obj) except ImportError, e: # Error importing the module @@ -623,9 +623,9 @@ dot = mname.rfind('.') if dot < 0: self._pkg = None else: try: - self._pkg = ObjectUID(import_module(mname[:dot])) + self._pkg = make_uid(import_module(mname[:dot])) except ImportError, e: if sys.stderr.softspace: print >>sys.stderr print >>sys.stderr, '\n Warning: %s' % e self._pkg = None