[Epydoc-commits] SF.net SVN: epydoc: [1374] branches/exp-args_in_class/epydoc/src/epydoc
Brought to you by:
edloper
|
From: <dva...@us...> - 2006-09-08 15:40:22
|
Revision: 1374
http://svn.sourceforge.net/epydoc/?rev=1374&view=rev
Author: dvarrazzo
Date: 2006-09-08 08:40:13 -0700 (Fri, 08 Sep 2006)
Log Message:
-----------
- __init__ signature can be described in the class docstring also when there
is no __init__.__doc__ at all.
- parse_function_signature() can receive two arguments: one whose docstring is
to be parsed and one to be populated. So the constructor signature can be
parsed from the class docstring.
- Dropped generation of variables when there is a type w/o matching var.
The issue is still to be defined consistently anyway.
Modified Paths:
--------------
branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py
Added Paths:
-----------
branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest
Modified: branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py
===================================================================
--- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-08 10:38:55 UTC (rev 1373)
+++ branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-08 15:40:13 UTC (rev 1374)
@@ -174,8 +174,12 @@
initialize_api_doc(api_doc)
# If there's no docstring, then there's nothing more to do.
+ # ...except in a case: an __init__ function that is to receive some
+ # documentation from the class docstring
if (api_doc.docstring in (None, UNKNOWN)):
- return
+ if not (isinstance(api_doc, RoutineDoc)
+ and api_doc.canonical_name[-1] == '__init__'):
+ return
# Remove leading indentation from the docstring.
api_doc.docstring = unindent_docstring(api_doc.docstring)
@@ -184,6 +188,10 @@
# overrides any signature we got via introspection/parsing.
if isinstance(api_doc, RoutineDoc):
parse_function_signature(api_doc)
+ elif isinstance(api_doc, ClassDoc):
+ initvar = api_doc.variables.get('__init__')
+ if initvar:
+ parse_function_signature(initvar.value, api_doc)
# Parse the docstring. Any errors encountered are stored as
# `ParseError` objects in the errors list.
@@ -694,9 +702,16 @@
def set_var_type(api_doc, ident, descr):
if ident not in api_doc.variables:
- api_doc.variables[ident] = VariableDoc(
- container=api_doc, name=ident,
- canonical_name=api_doc.canonical_name+ident)
+ # [xx] If there is a type w/o matching var, this would create
+ # a new var. The behavior is to be decied consistently also in other
+ # places in this sources (grep for [xx]).
+ # Currently disable the creation or else each "type" used in the
+ # class docstring to describe an __init__ parameter also generates
+ # an extra class variable.
+ #api_doc.variables[ident] = VariableDoc(
+ #container=api_doc, name=ident,
+ #canonical_name=api_doc.canonical_name+ident)
+ return
var_doc = api_doc.variables[ident]
if var_doc.type_descr not in (None, UNKNOWN):
@@ -740,7 +755,7 @@
# [xx] copied from inspect.getdoc(); we can't use inspect.getdoc()
# itself, since it expects an object, not a string.
- if docstring == '': return ''
+ if not docstring: return ''
lines = docstring.expandtabs().split('\n')
# Find minimum indentation of any non-blank lines after first line.
@@ -823,7 +838,7 @@
"""A regular expression that is used to extract signatures from
docstrings."""
-def parse_function_signature(func_doc):
+def parse_function_signature(func_doc, doc_source=None):
"""
Construct the signature for a builtin function or method from
its docstring. If the docstring uses the standard convention
@@ -833,15 +848,26 @@
Otherwise, the signature will be set to a single varargs
variable named C{"..."}.
+ @param func_doc: The target object where to store parsed signature. Also
+ container of the docstring to parse if doc_source is C{None}
+ @type L{RoutineDoc}
+ @param doc_source: Contains the docstring to parse. If C{None}, parse
+ L{func_doc} docstring instead
+ @type L{APIDoc}
@rtype: C{None}
"""
+ if doc_source is None:
+ doc_source = func_doc
+
# If there's no docstring, then don't do anything.
- if not func_doc.docstring: return False
+ if not doc_source.docstring: return False
- m = _SIGNATURE_RE.match(func_doc.docstring)
+ m = _SIGNATURE_RE.match(doc_source.docstring)
if m is None: return False
# Do I want to be this strict?
+ # Notice that __init__ must match the class name instead, if the signature
+ # comes from the class docstring
# if not (m.group('func') == func_doc.canonical_name[-1] or
# '_'+m.group('func') == func_doc.canonical_name[-1]):
# log.warning("Not extracting function signature from %s's "
@@ -900,7 +926,7 @@
func_doc.posarg_defaults.insert(0, None)
# Remove the signature from the docstring.
- func_doc.docstring = func_doc.docstring[m.end():]
+ doc_source.docstring = doc_source.docstring[m.end():]
# We found a signature.
return True
Added: branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest
===================================================================
--- branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest (rev 0)
+++ branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-08 15:40:13 UTC (rev 1374)
@@ -0,0 +1,171 @@
+Regression Testing for epydoc.docbuilder
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Test Function
+=============
+This test function takes a string containing the contents of a module.
+It writes the string contents to a file, imports the file as a module,
+and uses build_doc to build documentation, and pretty prints the resulting
+ModuleDoc object. The `attribs` argument specifies which attributes
+of the `APIDoc`s should be displayed. The `introspect` argument gives the
+name of a variable in the module whose value should be introspected,
+instead of introspecting the whole module.
+
+ >>> import tempfile, re, os, os.path, textwrap, sys
+ >>> from epydoc.docbuilder import build_doc
+ >>> def runbuilder(s, attribs='', introspect=None, exclude=''):
+ ... # Write it to a temp file.
+ ... tmp_dir = tempfile.mkdtemp()
+ ... out = open(os.path.join(tmp_dir, 'epydoc_test.py'), 'w')
+ ... out.write(textwrap.dedent(s))
+ ... out.close()
+ ... # Import it.
+ ... sys.path.insert(0, tmp_dir)
+ ... if introspect is None:
+ ... import epydoc_test as val
+ ... else:
+ ... exec("from epydoc_test import %s as val" % introspect)
+ ... del sys.path[0]
+ ... # Introspect it.
+ ... val_doc = build_doc(val)
+ ... # Display it.
+ ... s = val_doc.pp(include=attribs.split(),exclude=exclude.split())
+ ... s = re.sub(r"(filename = ).*", r"\1...", s)
+ ... s = re.sub(r"(<module 'epydoc_test' from ).*", r'\1...', s)
+ ... s = re.sub(r"(<function \w+ at )0x\w+>", r"\1...>", s)
+ ... s = re.sub(r"(<\w+ object at )0x\w+>", r"\1...>", s)
+ ... print s
+ ... # Clean up.
+ ... os.unlink(os.path.join(tmp_dir, 'epydoc_test.py'))
+ ... try: os.unlink(os.path.join(tmp_dir, 'epydoc_test.pyc'))
+ ... except OSError: pass
+ ... os.rmdir(tmp_dir)
+ ... del sys.modules['epydoc_test']
+
+
+Specifying constructor signature in class docstring
+===================================================
+
+The class signature can be specified in the class docstring instead of __init__
+
+ >>> runbuilder(s='''
+ ... class Foo:
+ ... """This is the object docstring
+ ...
+ ... @param a: init param.
+ ... @ivar a: instance var.
+ ... @type a: date
+ ... """
+ ... def __init__(self, a):
+ ... """The ctor docstring.
+ ...
+ ... @type a: str
+ ... """
+ ... pass
+ ... ''',
+ ... introspect="Foo",
+ ... attribs="variables name value "
+ ... "posargs vararg kwarg type arg_types arg_descrs")
+ ClassDoc for epydoc_test.Foo [0]
+ +- variables
+ +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1]
+ | +- name = '__init__'
+ | +- value
+ | +- RoutineDoc for epydoc_test.Foo.__init__ [2]
+ | +- arg_descrs = [([u'a'], ...
+ | +- arg_types = {u'a': ...
+ | +- kwarg = None
+ | +- posargs = ['self', 'a']
+ | +- vararg = None
+ +- a => VariableDoc for epydoc_test.Foo.a [3]
+ +- name = u'a'
+ +- value = <UNKNOWN>
+
+Also keywords arguments can be put in the constructor
+
+ >>> runbuilder(s='''
+ ... class Foo:
+ ... """This is the object docstring
+ ...
+ ... @keyword a: a kwarg.
+ ... @type a: str
+ ... """
+ ... def __init__(self, **kwargs):
+ ... """The ctor docstring.
+ ...
+ ... @type a: str
+ ... """
+ ... ''',
+ ... introspect="Foo",
+ ... attribs="variables name value "
+ ... "posargs vararg kwarg type arg_types arg_descrs")
+ ClassDoc for epydoc_test.Foo [0]
+ +- variables
+ +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1]
+ +- name = '__init__'
+ +- value
+ +- RoutineDoc for epydoc_test.Foo.__init__ [2]
+ +- arg_descrs = [([u'a'], ...
+ +- arg_types = {u'a': ...
+ +- kwarg = 'kwargs'
+ +- posargs = ['self']
+ +- vararg = None
+
+A missing docstring on the __init__ is not an issue.
+ >>> runbuilder(s='''
+ ... class Foo:
+ ... """This is the object docstring
+ ...
+ ... @param a: a param.
+ ... @type a: str
+ ... """
+ ... def __init__(self):
+ ... pass
+ ... ''',
+ ... introspect="Foo",
+ ... attribs="variables name value "
+ ... "posargs vararg kwarg type arg_types arg_descrs")
+ ClassDoc for epydoc_test.Foo [0]
+ +- variables
+ +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1]
+ +- name = '__init__'
+ +- value
+ +- RoutineDoc for epydoc_test.Foo.__init__ [2]
+ +- arg_descrs = [([u'a'], ...
+ +- arg_types = {u'a': ...
+ +- kwarg = None
+ +- posargs = ['self']
+ +- vararg = None
+
+Epydoc can also grok the constructor signature from the class docstring
+
+ >>> runbuilder(s='''
+ ... class Foo:
+ ... """Foo(x, y)
+ ...
+ ... A class to ship rockets in outer space.
+ ...
+ ... @param x: first param
+ ... @param y: second param
+ ... """
+ ... def __init__(self, a, b):
+ ... """__init__ doc"""
+ ... pass
+ ... ''',
+ ... introspect="Foo",
+ ... attribs="variables name value "
+ ... "posargs vararg kwarg type arg_types arg_descrs docstring")
+ ClassDoc for epydoc_test.Foo [0]
+ +- docstring = u'A class to ship rockets ...
+ +- variables
+ +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1]
+ +- docstring = <UNKNOWN>
+ +- name = '__init__'
+ +- value
+ +- RoutineDoc for epydoc_test.Foo.__init__ [2]
+ +- arg_descrs = [([u'x'], ...
+ +- arg_types = {}
+ +- docstring = u'__init__ doc'
+ +- kwarg = None
+ +- posargs = [u'x', u'y']
+ +- vararg = None
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|