epydoc-commits Mailing List for Python API documentation generation tool
Brought to you by:
edloper
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
(77) |
May
|
Jun
(6) |
Jul
(8) |
Aug
(91) |
Sep
(67) |
Oct
(4) |
Nov
|
Dec
(1) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(17) |
Feb
(135) |
Mar
(25) |
Apr
|
May
(1) |
Jun
(1) |
Jul
(7) |
Aug
|
Sep
(62) |
Oct
(1) |
Nov
(3) |
Dec
|
2008 |
Jan
(40) |
Feb
(102) |
Mar
(5) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
|
|
1
|
2
(8) |
3
(4) |
4
(1) |
5
|
6
(13) |
7
(7) |
8
(6) |
9
|
10
(6) |
11
(4) |
12
|
13
(2) |
14
(1) |
15
(3) |
16
(7) |
17
(5) |
18
|
19
|
20
|
21
|
22
|
23
|
24
|
25
|
26
|
27
|
28
|
29
|
30
|
From: <dva...@us...> - 2006-09-17 23:50:41
|
Revision: 1404 http://svn.sourceforge.net/epydoc/?rev=1404&view=rev Author: dvarrazzo Date: 2006-09-17 16:50:35 -0700 (Sun, 17 Sep 2006) Log Message: ----------- - Types in HTML output are treated consistently: not always in monotype font, but respecting user markup. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 20:02:33 UTC (rev 1403) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 23:50:35 UTC (rev 1404) @@ -1939,7 +1939,7 @@ ''' <tr$tr_class$> <td width="15%" align="right" valign="top" class="summary"> - <code class="summary-type">$typ or " "$</code> + <span class="summary-type">$typ or " "$</span> </td><td class="summary"> $description$ </td> @@ -2058,7 +2058,7 @@ if arg_name in func_doc.arg_types: typ = func_doc.arg_types[arg_name] typ_html = self.docstring_to_html(typ, func_doc, 10) - s += " (<code>%s</code>)" % typ_html + s += " (%s)" % typ_html return s write_function_details_entry = compile_template( @@ -2104,13 +2104,13 @@ >>> #endif >>> # === return type === >>> if rdescr and rtype: - <dl><dt>Returns: <code>$rtype$</code></dt> + <dl><dt>Returns: $rtype$</dt> <dd>$rdescr$</dd></dl> >>> elif rdescr: <dl><dt>Returns:</dt> <dd>$rdescr$</dd></dl> >>> elif rtype: - <dl><dt>Returns: <code>$rtype$</code></dt></dl> + <dl><dt>Returns: $rtype$</dt></dl> >>> #endif >>> # === decorators === >>> if func_doc.decorators not in (None, UNKNOWN): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-17 20:02:39
|
Revision: 1403 http://svn.sourceforge.net/epydoc/?rev=1403&view=rev Author: dvarrazzo Date: 2006-09-17 13:02:33 -0700 (Sun, 17 Sep 2006) Log Message: ----------- - Dropped check not required anymore after r1401 Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 18:21:05 UTC (rev 1402) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 20:02:33 UTC (rev 1403) @@ -2128,10 +2128,6 @@ <dl><dt>Decorators:</dt></dl> <ul class="nomargin"> >>> for deco in decos: - >>> if not ((deco=="staticmethod" and - >>> isinstance(func_doc, StaticMethodDoc)) or - >>> (deco=="classmethod" and - >>> isinstance(func_doc, ClassMethodDoc))): <li><code>@$deco$</code></li> >>> #endfor </ul> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-17 18:21:11
|
Revision: 1402 http://svn.sourceforge.net/epydoc/?rev=1402&view=rev Author: dvarrazzo Date: 2006-09-17 11:21:05 -0700 (Sun, 17 Sep 2006) Log Message: ----------- - Property access functions are not shown (as ``None``) when they are None. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 17:54:47 UTC (rev 1401) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 18:21:05 UTC (rev 1402) @@ -2012,7 +2012,9 @@ self.summary(val_doc)) for (name, val_doc) in [('Get', prop_doc.fget), ('Set', prop_doc.fset), ('Delete', prop_doc.fdel)] - if val_doc is not UNKNOWN ] + if val_doc not in (None, UNKNOWN) + and val_doc.pyval is not None ] + self.write_property_details_entry(out, var_doc, descr, accessors, div_class) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-17 17:54:52
|
Revision: 1401 http://svn.sourceforge.net/epydoc/?rev=1401&view=rev Author: dvarrazzo Date: 2006-09-17 10:54:47 -0700 (Sun, 17 Sep 2006) Log Message: ----------- - An empty "Decorators:" fields group is not shown if ``classmethod`` and ``staticmethod`` are the only decorators of a method. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 15:04:40 UTC (rev 1400) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 17:54:47 UTC (rev 1401) @@ -2111,11 +2111,21 @@ <dl><dt>Returns: <code>$rtype$</code></dt></dl> >>> #endif >>> # === decorators === - >>> if func_doc.decorators not in (None, UNKNOWN, (), []): + >>> if func_doc.decorators not in (None, UNKNOWN): + >>> # (staticmethod & classmethod are already shown, above) + >>> decos = filter(lambda deco: + >>> not ((deco=="staticmethod" and + >>> isinstance(func_doc, StaticMethodDoc)) or + >>> (deco=="classmethod" and + >>> isinstance(func_doc, ClassMethodDoc))), + >>> func_doc.decorators) + >>> else: + >>> decos = None + >>> #endif + >>> if decos: <dl><dt>Decorators:</dt></dl> <ul class="nomargin"> - >>> for deco in func_doc.decorators: - >>> # (staticmethod & classmethod are already shown, above) + >>> for deco in decos: >>> if not ((deco=="staticmethod" and >>> isinstance(func_doc, StaticMethodDoc)) or >>> (deco=="classmethod" and This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-17 15:04:47
|
Revision: 1400 http://svn.sourceforge.net/epydoc/?rev=1400&view=rev Author: dvarrazzo Date: 2006-09-17 08:04:40 -0700 (Sun, 17 Sep 2006) Log Message: ----------- - Fixed URLs reported malformed by HTML Tidy Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-16 13:59:05 UTC (rev 1399) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-17 15:04:40 UTC (rev 1400) @@ -1499,7 +1499,7 @@ def callgraph_link(self, callgraph): # Use class=codelink, to match style w/ the source code link. if callgraph is None: return '' - return ('<br /><span class="codelink"><a href="javascript: void(0);" ' + return ('<br /><span class="codelink"><a href="javascript:void(0);" ' 'onclick="toggleCallGraph(\'%s-div\');return false;">' 'call graph</a></span> ' % callgraph.uid) @@ -2882,7 +2882,7 @@ TABLE_FOOTER = '</table>\n' PRIVATE_LINK = ''' - <span class="options">[<a href="javascript: void(0);" class="privatelink" + <span class="options">[<a href="javascript:void(0);" class="privatelink" onclick="toggle_private();">hide private</a>]</span> '''.strip() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-16 13:59:14
|
Revision: 1399 http://svn.sourceforge.net/epydoc/?rev=1399&view=rev Author: dvarrazzo Date: 2006-09-16 06:59:05 -0700 (Sat, 16 Sep 2006) Log Message: ----------- - Dropped unmatched </span> Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-16 13:53:17 UTC (rev 1398) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-16 13:59:05 UTC (rev 1399) @@ -2085,8 +2085,8 @@ >>> #endif </h3> </td><td align="right" valign="top" - >$self.pysrc_link(func_doc)$ </span - >$self.callgraph_link(callgraph)$</td> + >$self.pysrc_link(func_doc)$ + $self.callgraph_link(callgraph)$</td> </table> $self.render_callgraph(callgraph)$ $descr$ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-16 13:53:24
|
Revision: 1398 http://svn.sourceforge.net/epydoc/?rev=1398&view=rev Author: dvarrazzo Date: 2006-09-16 06:53:17 -0700 (Sat, 16 Sep 2006) Log Message: ----------- - Closing (old\!) experimental branch Removed Paths: ------------- branches/exp-all-is-interface/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-16 13:51:01
|
Revision: 1397 http://svn.sourceforge.net/epydoc/?rev=1397&view=rev Author: dvarrazzo Date: 2006-09-16 06:50:56 -0700 (Sat, 16 Sep 2006) Log Message: ----------- - Closing experimental branch Removed Paths: ------------- branches/exp-args_in_class/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-16 13:48:40
|
Revision: 1396 http://svn.sourceforge.net/epydoc/?rev=1396&view=rev Author: dvarrazzo Date: 2006-09-16 06:48:32 -0700 (Sat, 16 Sep 2006) Log Message: ----------- - Class docstrings can describe the constructor signature, parameters and raised exceptions. Merged revisions 1373-1375,1377-1388,1390-1395 via svnmerge from https://svn.sourceforge.net/svnroot/epydoc/branches/exp-args_in_class ........ r1373 | dvarrazzo | 2006-09-08 12:38:55 +0200 (Fri, 08 Sep 2006) | 10 lines - Allow parameter-related fields in a class docstring: use them to extend the matching __init__ docstring. - Enforce docstring parsing in dotted name order to ensure class docstring have already been parsed at __init__ docstring parsing time. - "type" fields are used to specify both class/instance variables types and constructor arguments types. In case a type is expressed in both class and __init__ docstring, the latter wins (e.g. the __init__ may receive an arg, parse it and store it in the instance state with the same name but different type) ........ r1374 | dvarrazzo | 2006-09-08 17:40:13 +0200 (Fri, 08 Sep 2006) | 8 lines - __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. ........ r1390 | dvarrazzo | 2006-09-15 03:47:53 +0200 (Fri, 15 Sep 2006) | 5 lines - Checked in a new algorithm to split fields in the class docstring between class documentation and constructor documentation. The algorithm requires the `type` fields to appear after the related fields. - Added more test. ........ r1391 | dvarrazzo | 2006-09-15 04:24:11 +0200 (Fri, 15 Sep 2006) | 2 lines - Splitting argument refactored into a single distinct function. ........ r1392 | dvarrazzo | 2006-09-16 01:36:23 +0200 (Sat, 16 Sep 2006) | 1 line - Be more lenient about types specified before matching objects. ........ r1393 | dvarrazzo | 2006-09-16 02:02:10 +0200 (Sat, 16 Sep 2006) | 5 lines - Reverted updates to `process_arg_field()` handler: is context is always a function, not the class docstring. - Exceptions are handled in the class docstring as well. - More explicit name of some variables. ........ r1394 | dvarrazzo | 2006-09-16 02:20:06 +0200 (Sat, 16 Sep 2006) | 1 line - Reverting type fields handling to trunk behavior. ........ r1395 | dvarrazzo | 2006-09-16 14:57:14 +0200 (Sat, 16 Sep 2006) | 4 lines - Class docstring fields are passed to __init__ without using an extra ClassDoc attribute. - Some docstring fixed. ........ Modified Paths: -------------- trunk/epydoc/src/epydoc/docstringparser.py trunk/epydoc/src/epydoc/test/docbuilder.doctest Modified: trunk/epydoc/src/epydoc/docstringparser.py =================================================================== --- trunk/epydoc/src/epydoc/docstringparser.py 2006-09-16 12:57:14 UTC (rev 1395) +++ trunk/epydoc/src/epydoc/docstringparser.py 2006-09-16 13:48:32 UTC (rev 1396) @@ -168,7 +168,9 @@ user docfields defined by containing objects. """ if api_doc.metadata is not UNKNOWN: - log.debug("%s's docstring processed twice" % api_doc.canonical_name) + if not (isinstance(api_doc, RoutineDoc) + and api_doc.canonical_name[-1] == '__init__'): + log.debug("%s's docstring processed twice" % api_doc.canonical_name) return initialize_api_doc(api_doc) @@ -197,8 +199,30 @@ descr, fields = parsed_docstring.split_fields(parse_errors) api_doc.descr = descr + field_warnings = [] + + # Handle the constructor fields that have been defined in the class + # docstring. This code assumes that a class docstring is parsed before + # the same class __init__ docstring. + if isinstance(api_doc, ClassDoc): + + # Parse ahead the __init__ docstring for this class + initvar = api_doc.variables.get('__init__') + if initvar and initvar.value not in (None, UNKNOWN): + init_api_doc = initvar.value + parse_docstring(init_api_doc, docindex) + + parse_function_signature(init_api_doc, api_doc) + init_fields = split_init_fields(fields, field_warnings) + + # Process fields + for field in init_fields: + try: + process_field(init_api_doc, docindex, field.tag(), + field.arg(), field.body()) + except ValueError, e: field_warnings.append(str(e)) + # Process fields - field_warnings = [] for field in fields: try: process_field(api_doc, docindex, field.tag(), @@ -254,6 +278,91 @@ if api_doc.sort_spec is UNKNOWN: api_doc.sort_spec = [] +def split_init_fields(fields, warnings): + """ + Remove the fields related to the constructor from a class docstring + fields list. + + @param fields: The fields to process. The list will be modified in place + @type fields: C{list} of L{markup.Field} + @param warnings: A list to emit processing warnings + @type warnings: C{list} + @return: The C{fields} items to be applied to the C{__init__} method + @rtype: C{list} of L{markup.Field} + """ + init_fields = [] + + # Split fields in lists according to their argument, keeping order. + arg_fields = {} + args_order = [] + i = 0 + while i < len(fields): + field = fields[i] + + # gather together all the fields with the same arg + if field.arg() is not None: + arg_fields.setdefault(field.arg(), []).append(fields.pop(i)) + args_order.append(field.arg()) + else: + i += 1 + + # Now check that for each argument there is at most a single variable + # and a single parameter, and at most a single type for each of them. + for arg in args_order: + ff = arg_fields.pop(arg, None) + if ff is None: + continue + + var = tvar = par = tpar = None + for field in ff: + if field.tag() in VARIABLE_TAGS: + if var is None: + var = field + fields.append(field) + else: + warnings.append( + "There is more than one variable named '%s'" + % arg) + elif field.tag() in PARAMETER_TAGS: + if par is None: + par = field + init_fields.append(field) + else: + warnings.append( + "There is more than one parameter named '%s'" + % arg) + + elif field.tag() == 'type': + if var is None and par is None: + # type before obj + tvar = tpar = field + else: + if var is not None and tvar is None: + tvar = field + if par is not None and tpar is None: + tpar = field + + elif field.tag() in EXCEPTION_TAGS: + init_fields.append(field) + + else: # Unespected field + fields.append(field) + + # Put selected types into the proper output lists + if tvar is not None: + if var is not None: + fields.append(tvar) + else: + pass # [xx] warn about type w/o object? + + if tpar is not None: + if par is not None: + init_fields.append(tpar) + else: + pass # [xx] warn about type w/o object? + + return init_fields + def report_errors(api_doc, docindex, parse_errors, field_warnings): """A helper function for L{parse_docstring()} that reports any markup warnings and field warnings that we encountered while @@ -620,6 +729,16 @@ register_field_handler(process_raise_field, 'raise', 'raises', 'except', 'exception') +# Tags related to function parameters +PARAMETER_TAGS = ('arg', 'argument', 'parameter', 'param', + 'kwarg', 'keyword', 'kwparam') + +# Tags related to variables in a class +VARIABLE_TAGS = ('cvar', 'cvariable', 'ivar', 'ivariable') + +# Tags related to exceptions +EXCEPTION_TAGS = ('raise', 'raises', 'except', 'exception') + ###################################################################### #{ Helper Functions ###################################################################### @@ -697,7 +816,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. @@ -780,7 +899,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 @@ -790,15 +909,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 func_doc: L{RoutineDoc} + @param doc_source: Contains the docstring to parse. If C{None}, parse + L{func_doc} docstring instead + @type doc_source: 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 " @@ -857,7 +987,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 Modified: trunk/epydoc/src/epydoc/test/docbuilder.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-16 12:57:14 UTC (rev 1395) +++ trunk/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-16 13:48:32 UTC (rev 1396) @@ -1,5 +1,5 @@ Regression Testing for epydoc.docbuilder -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Test Function ============= @@ -14,6 +14,22 @@ >>> import tempfile, re, os, os.path, textwrap, sys >>> from epydoc.docbuilder import build_doc + >>> from epydoc.apidoc import ClassDoc, RoutineDoc + >>> from epydoc.markup import ParsedDocstring + + >>> def to_plain(docstring): + ... """Conver a parsed docstring into plain text""" + ... if isinstance(docstring, ParsedDocstring): + ... docstring = docstring.to_plaintext(None) + ... return docstring.rsplit() + + >>> def fun_to_plain(val_doc): + ... """Convert parsed docstrings in text from a RoutineDoc""" + ... for k, v in val_doc.arg_types.items(): + ... val_doc.arg_types[k] = to_plain(v) + ... for i, (k, v) in enumerate(val_doc.arg_descrs): + ... val_doc.arg_descrs[i] = (k, to_plain(v)) + >>> def runbuilder(s, attribs='', build=None, exclude=''): ... # Write it to a temp file. ... tmp_dir = tempfile.mkdtemp() @@ -24,6 +40,10 @@ ... val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py')) ... if build: val_doc = val_doc.variables[build].value ... # Display it. + ... if isinstance(val_doc, ClassDoc): + ... for val in val_doc.variables.values(): + ... if isinstance(val.value, RoutineDoc): + ... fun_to_plain(val.value) ... 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) @@ -115,3 +135,291 @@ +- PropertyDoc for epydoc_test.Foo.y [9] +- descr = u'A property has no defining module' +- type_descr = u'int' + +Stuff from future doesn't appear as variable. + + >>> runbuilder(s=""" + ... from __future__ import division + ... from re import match + ... """, + ... attribs='variables value') + ModuleDoc for epydoc_test [0] + +- variables + +- match => VariableDoc for epydoc_test.match [1] + +- value + +- ValueDoc for sre.match [2] + + +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 + ... ''', + ... build="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 + ... """ + ... ''', + ... build="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 + ... ''', + ... build="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 + +Exceptions can be put in the docstring class, and they are assigned to the +constructor too. + >>> runbuilder(s=''' + ... class Foo: + ... """Foo(x, y) + ... + ... A class to ship rockets in outer space. + ... + ... @param x: first param + ... @param y: second param + ... @except ValueError: frobnication error + ... """ + ... def __init__(self, a, b): + ... """__init__ doc""" + ... pass + ... ''', + ... build="Foo", + ... attribs="variables name value exception_descrs " + ... "posargs vararg kwarg type arg_types arg_descrs docstring") + ClassDoc for epydoc_test.Foo [0] + +- docstring = u'A class to ship rockets in outer sp... + +- 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'], [u'first', u'param']), ... + +- arg_types = {} + +- docstring = u'__init__ doc' + +- exception_descrs = [(DottedName(u'ValueError'), ... + +- kwarg = None + +- posargs = [u'x', u'y'] + +- 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 + ... ''', + ... build="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 + +A type can apply to both a param and a variable + + >>> runbuilder(s=''' + ... class Foo: + ... """This is the object docstring + ... + ... @param a: init param. + ... @ivar a: instance var. + ... @type a: date + ... """ + ... def __init__(self, a): + ... pass + ... ''', + ... build="Foo", + ... attribs="variables name value " + ... "posargs vararg kwarg type_descr arg_types arg_descrs") + ClassDoc for epydoc_test.Foo [0] + +- variables + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1] + | +- name = '__init__' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.__init__ [2] + | +- arg_descrs = [([u'a'], [u'init', u'param.'])] + | +- arg_types = {u'a': [u'date']} + | +- kwarg = None + | +- posargs = ['self', 'a'] + | +- vararg = None + +- a => VariableDoc for epydoc_test.Foo.a [3] + +- name = u'a' + +- type_descr = u'date\n\n' + +- value = <UNKNOWN> + +But there can also be two different types + + >>> runbuilder(s=''' + ... class Foo: + ... """This is the object docstring + ... + ... @param a: init param. + ... @type a: string + ... @ivar a: instance var. + ... @type a: date + ... """ + ... def __init__(self, a): + ... pass + ... ''', + ... build="Foo", + ... attribs="variables name value " + ... "posargs vararg kwarg type_descr arg_types arg_descrs") + ClassDoc for epydoc_test.Foo [0] + +- variables + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1] + | +- name = '__init__' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.__init__ [2] + | +- arg_descrs = [([u'a'], [u'init', u'param.'])] + | +- arg_types = {u'a': [u'string']} + | +- kwarg = None + | +- posargs = ['self', 'a'] + | +- vararg = None + +- a => VariableDoc for epydoc_test.Foo.a [3] + +- name = u'a' + +- type_descr = u'date\n\n' + +- value = <UNKNOWN> + +Also reST consolidated fields are not a problem. + + >>> runbuilder(s=''' + ... __docformat__ = 'restructuredtext' + ... class Foo: + ... """This is the object docstring + ... + ... :Parameters: + ... `a` : string + ... init param. + ... + ... :Exceptions: + ... * `ValueError`: frobnication error + ... init param. + ... + ... :IVariables: + ... `a` : date + ... instance var. + ... """ + ... def __init__(self, a): + ... pass + ... ''', + ... build="Foo", + ... attribs="variables name value exception_descrs " + ... "posargs vararg kwarg type_descr arg_types arg_descrs") + ClassDoc for epydoc_test.Foo [0] + +- variables + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1] + | +- name = '__init__' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.__init__ [2] + | +- arg_descrs = [([u'a'], [u'init', u'param.'])] + | +- arg_types = {u'a': [u'string']} + | +- exception_descrs = [(DottedName(u'ValueError'), ... + | +- kwarg = None + | +- posargs = ['self', 'a'] + | +- vararg = None + +- a => VariableDoc for epydoc_test.Foo.a [3] + +- name = u'a' + +- type_descr = u'date' + +- value = <UNKNOWN> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-16 12:57:21
|
Revision: 1395 http://svn.sourceforge.net/epydoc/?rev=1395&view=rev Author: dvarrazzo Date: 2006-09-16 05:57:14 -0700 (Sat, 16 Sep 2006) Log Message: ----------- - Class docstring fields are passed to __init__ without using an extra ClassDoc attribute. - Some docstring fixed. Modified Paths: -------------- branches/exp-args_in_class/epydoc/src/epydoc/apidoc.py branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py Modified: branches/exp-args_in_class/epydoc/src/epydoc/apidoc.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/apidoc.py 2006-09-16 00:20:06 UTC (rev 1394) +++ branches/exp-args_in_class/epydoc/src/epydoc/apidoc.py 2006-09-16 12:57:14 UTC (rev 1395) @@ -1118,10 +1118,6 @@ """@ivar: API documentation for the class's known subclasses. @type: C{list} of L{ClassDoc}""" #} - init_args = UNKNOWN - """@ivar: Tags to be used as constructor documentation. - @type: C{list} of C{(tag, arg, descr)} tuples""" - #} def apidoc_links(self, **filters): val_docs = NamespaceDoc.apidoc_links(self, **filters) Modified: branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-16 00:20:06 UTC (rev 1394) +++ branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-16 12:57:14 UTC (rev 1395) @@ -168,18 +168,16 @@ user docfields defined by containing objects. """ if api_doc.metadata is not UNKNOWN: - log.debug("%s's docstring processed twice" % api_doc.canonical_name) + if not (isinstance(api_doc, RoutineDoc) + and api_doc.canonical_name[-1] == '__init__'): + log.debug("%s's docstring processed twice" % api_doc.canonical_name) return 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)): - if not (isinstance(api_doc, RoutineDoc) - and api_doc.canonical_name[-1] == '__init__'): - return + return # Remove leading indentation from the docstring. api_doc.docstring = unindent_docstring(api_doc.docstring) @@ -188,10 +186,6 @@ # 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. @@ -211,14 +205,23 @@ # docstring. This code assumes that a class docstring is parsed before # the same class __init__ docstring. if isinstance(api_doc, ClassDoc): - split_init_fields(fields, api_doc.init_args, field_warnings) - elif (isinstance(api_doc, RoutineDoc) - and api_doc.canonical_name[-1] == '__init__'): - class_doc = docindex.get_valdoc(api_doc.canonical_name[:-1]) - if class_doc is not None and class_doc.init_args is not UNKNOWN: - fields.extend(class_doc.init_args) + # Parse ahead the __init__ docstring for this class + initvar = api_doc.variables.get('__init__') + if initvar and initvar.value not in (None, UNKNOWN): + init_api_doc = initvar.value + parse_docstring(init_api_doc, docindex) + parse_function_signature(init_api_doc, api_doc) + init_fields = split_init_fields(fields, field_warnings) + + # Process fields + for field in init_fields: + try: + process_field(init_api_doc, docindex, field.tag(), + field.arg(), field.body()) + except ValueError, e: field_warnings.append(str(e)) + # Process fields for field in fields: try: @@ -255,9 +258,6 @@ api_doc.summary = None if api_doc.metadata is UNKNOWN: api_doc.metadata = [] - if isinstance(api_doc, ClassDoc): - if api_doc.init_args is UNKNOWN: - api_doc.init_args = [] if isinstance(api_doc, RoutineDoc): if api_doc.arg_descrs is UNKNOWN: api_doc.arg_descrs = [] @@ -278,13 +278,20 @@ if api_doc.sort_spec is UNKNOWN: api_doc.sort_spec = [] -def split_init_fields(fields, init_fields, warnings): +def split_init_fields(fields, warnings): """ - Move the fields related to init into a different list. - C{fields} is supposed obtained from a class docstring. Remove - fields not related to the class from it and add them to C{init_fields}, - which is a list of constructor fields. + Remove the fields related to the constructor from a class docstring + fields list. + + @param fields: The fields to process. The list will be modified in place + @type fields: C{list} of L{markup.Field} + @param warnings: A list to emit processing warnings + @type warnings: C{list} + @return: The C{fields} items to be applied to the C{__init__} method + @rtype: C{list} of L{markup.Field} """ + init_fields = [] + # Split fields in lists according to their argument, keeping order. arg_fields = {} args_order = [] @@ -354,6 +361,8 @@ else: pass # [xx] warn about type w/o object? + return init_fields + def report_errors(api_doc, docindex, parse_errors, field_warnings): """A helper function for L{parse_docstring()} that reports any markup warnings and field warnings that we encountered while @@ -902,10 +911,10 @@ @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} + @type func_doc: L{RoutineDoc} @param doc_source: Contains the docstring to parse. If C{None}, parse L{func_doc} docstring instead - @type L{APIDoc} + @type doc_source: L{APIDoc} @rtype: C{None} """ if doc_source is None: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-16 00:20:11
|
Revision: 1394 http://svn.sourceforge.net/epydoc/?rev=1394&view=rev Author: dvarrazzo Date: 2006-09-15 17:20:06 -0700 (Fri, 15 Sep 2006) Log Message: ----------- - Reverting type fields handling to trunk behavior. Modified Paths: -------------- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py Modified: branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-16 00:02:10 UTC (rev 1393) +++ branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-16 00:20:06 UTC (rev 1394) @@ -764,7 +764,6 @@ 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): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-16 00:02:18
|
Revision: 1393 http://svn.sourceforge.net/epydoc/?rev=1393&view=rev Author: dvarrazzo Date: 2006-09-15 17:02:10 -0700 (Fri, 15 Sep 2006) Log Message: ----------- - Reverted updates to `process_arg_field()` handler: is context is always a function, not the class docstring. - Exceptions are handled in the class docstring as well. - More explicit name of some variables. Modified Paths: -------------- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 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-15 23:36:23 UTC (rev 1392) +++ branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-16 00:02:10 UTC (rev 1393) @@ -308,7 +308,7 @@ var = tvar = par = tpar = None for field in ff: - if field.tag() in VAR_TAGS: + if field.tag() in VARIABLE_TAGS: if var is None: var = field fields.append(field) @@ -316,7 +316,7 @@ warnings.append( "There is more than one variable named '%s'" % arg) - elif field.tag() in PARAM_TAGS: + elif field.tag() in PARAMETER_TAGS: if par is None: par = field init_fields.append(field) @@ -335,6 +335,9 @@ if par is not None and tpar is None: tpar = field + elif field.tag() in EXCEPTION_TAGS: + init_fields.append(field) + else: # Unespected field fields.append(field) @@ -683,24 +686,15 @@ api_doc.return_type = descr def process_arg_field(api_doc, docindex, tag, arg, descr): - _check(api_doc, tag, arg, context=(ClassDoc, RoutineDoc), expect_arg=True) + _check(api_doc, tag, arg, context=RoutineDoc, expect_arg=True) idents = re.split('[:;, ] *', arg) + api_doc.arg_descrs.append( (idents, descr) ) + # Check to make sure that the documented parameter(s) are + # actually part of the function signature. + bad_params = ['"%s"' % i for i in idents if i not in api_doc.all_args()] + if bad_params: + raise ValueError(BAD_PARAM % (tag, ', '.join(bad_params))) - if isinstance(api_doc, RoutineDoc): - api_doc.arg_descrs.append( (idents, descr) ) - - # Check to make sure that the documented parameter(s) are - # actually part of the function signature. - bad_params = ['"%s"' % i for i in idents if i not in api_doc.all_args()] - if bad_params: - raise ValueError(BAD_PARAM % (tag, ', '.join(bad_params))) - - elif isinstance(api_doc, ClassDoc): - api_doc.init_args.append( (tag, arg, descr) ) - - else: - assert False, "unexpected context" - def process_kwarg_field(api_doc, docindex, tag, arg, descr): # [xx] these should -not- be checked if they exist.. # and listed separately or not?? @@ -727,13 +721,15 @@ 'except', 'exception') # Tags related to function parameters -PARAM_TAGS = ('arg', 'argument', 'parameter', 'param', - 'kwarg', 'keyword', 'kwparam') +PARAMETER_TAGS = ('arg', 'argument', 'parameter', 'param', + 'kwarg', 'keyword', 'kwparam') # Tags related to variables in a class -VAR_TAGS = ('cvar', 'cvariable', - 'ivar', 'ivariable') +VARIABLE_TAGS = ('cvar', 'cvariable', 'ivar', 'ivariable') +# Tags related to exceptions +EXCEPTION_TAGS = ('raise', 'raises', 'except', 'exception') + ###################################################################### #{ Helper Functions ###################################################################### Modified: branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-15 23:36:23 UTC (rev 1392) +++ branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-16 00:02:10 UTC (rev 1393) @@ -245,6 +245,42 @@ +- posargs = ['self'] +- vararg = None +Exceptions can be put in the docstring class, and they are assigned to the +constructor too. + >>> runbuilder(s=''' + ... class Foo: + ... """Foo(x, y) + ... + ... A class to ship rockets in outer space. + ... + ... @param x: first param + ... @param y: second param + ... @except ValueError: frobnication error + ... """ + ... def __init__(self, a, b): + ... """__init__ doc""" + ... pass + ... ''', + ... build="Foo", + ... attribs="variables name value exception_descrs " + ... "posargs vararg kwarg type arg_types arg_descrs docstring") + ClassDoc for epydoc_test.Foo [0] + +- docstring = u'A class to ship rockets in outer sp... + +- 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'], [u'first', u'param']), ... + +- arg_types = {} + +- docstring = u'__init__ doc' + +- exception_descrs = [(DottedName(u'ValueError'), ... + +- kwarg = None + +- posargs = [u'x', u'y'] + +- vararg = None + + Epydoc can also grok the constructor signature from the class docstring >>> runbuilder(s=''' @@ -356,6 +392,10 @@ ... `a` : string ... init param. ... + ... :Exceptions: + ... * `ValueError`: frobnication error + ... init param. + ... ... :IVariables: ... `a` : date ... instance var. @@ -364,7 +404,7 @@ ... pass ... ''', ... build="Foo", - ... attribs="variables name value " + ... attribs="variables name value exception_descrs " ... "posargs vararg kwarg type_descr arg_types arg_descrs") ClassDoc for epydoc_test.Foo [0] +- variables @@ -375,6 +415,7 @@ | +- RoutineDoc for epydoc_test.Foo.__init__ [2] | +- arg_descrs = [([u'a'], [u'init', u'param.'])] | +- arg_types = {u'a': [u'string']} + | +- exception_descrs = [(DottedName(u'ValueError'), ... | +- kwarg = None | +- posargs = ['self', 'a'] | +- vararg = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-15 23:36:31
|
Revision: 1392 http://svn.sourceforge.net/epydoc/?rev=1392&view=rev Author: dvarrazzo Date: 2006-09-15 16:36:23 -0700 (Fri, 15 Sep 2006) Log Message: ----------- - Be more lenient about types specified before matching objects. Modified Paths: -------------- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py Modified: branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-15 02:24:11 UTC (rev 1391) +++ branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-15 23:36:23 UTC (rev 1392) @@ -313,33 +313,44 @@ var = field fields.append(field) else: - warnings.append("there are more variables " - "named '%s'" % arg) + warnings.append( + "There is more than one variable named '%s'" + % arg) elif field.tag() in PARAM_TAGS: if par is None: par = field init_fields.append(field) else: - warnings.append("there are more parameters " - "named '%s'" % arg) + warnings.append( + "There is more than one parameter named '%s'" + % arg) elif field.tag() == 'type': - gone = False - if var is not None and tvar is None: - tvar = field - fields.append(field) - gone = True - if par is not None and tpar is None: - tpar = field - init_fields.append(field) - gone = True - if not gone: - warnings.append("type for '%s' doesn't apply " - "to any variable or argument" % arg) + if var is None and par is None: + # type before obj + tvar = tpar = field + else: + if var is not None and tvar is None: + tvar = field + if par is not None and tpar is None: + tpar = field else: # Unespected field fields.append(field) + # Put selected types into the proper output lists + if tvar is not None: + if var is not None: + fields.append(tvar) + else: + pass # [xx] warn about type w/o object? + + if tpar is not None: + if par is not None: + init_fields.append(tpar) + else: + pass # [xx] warn about type w/o object? + def report_errors(api_doc, docindex, parse_errors, field_warnings): """A helper function for L{parse_docstring()} that reports any markup warnings and field warnings that we encountered while @@ -754,15 +765,9 @@ def set_var_type(api_doc, ident, descr): if ident not in api_doc.variables: - # [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) + api_doc.variables[ident] = VariableDoc( + container=api_doc, name=ident, + canonical_name=api_doc.canonical_name+ident) return var_doc = api_doc.variables[ident] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-15 02:24:16
|
Revision: 1391 http://svn.sourceforge.net/epydoc/?rev=1391&view=rev Author: dvarrazzo Date: 2006-09-14 19:24:11 -0700 (Thu, 14 Sep 2006) Log Message: ----------- - Splitting argument refactored into a single distinct function. Modified Paths: -------------- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py Modified: branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-15 01:47:53 UTC (rev 1390) +++ branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-15 02:24:11 UTC (rev 1391) @@ -211,62 +211,8 @@ # docstring. This code assumes that a class docstring is parsed before # the same class __init__ docstring. if isinstance(api_doc, ClassDoc): + split_init_fields(fields, api_doc.init_args, field_warnings) - # Split fields in lists according to their argument - arg_fields = {} - args_order = [] - i = 0 - while i < len(fields): - field = fields[i] - - # gather together all the fields with the same arg - if field.arg() is not None: - arg_fields.setdefault(field.arg(), []).append(fields.pop(i)) - args_order.append(field.arg()) - else: - i += 1 - - # Now check that for each argument there is at most a single variable - # and a single argument, and a single type for them. - for arg in args_order: - ff = arg_fields.pop(arg, None) - if ff is None: - continue - - var = tvar = par = tpar = None - for field in ff: - if field.tag() in VAR_TAGS: - if var is None: - var = field - fields.append(field) - else: - field_warnings.append("there are more variables " - "named '%s'" % arg) - elif field.tag() in PARAM_TAGS: - if par is None: - par = field - api_doc.init_args.append(field) - else: - field_warnings.append("there are more parameters " - "named '%s'" % arg) - - elif field.tag() == 'type': - gone = False - if var is not None and tvar is None: - tvar = field - fields.append(field) - gone = True - if par is not None and tpar is None: - tpar = field - api_doc.init_args.append(field) - gone = True - if not gone: - field_warnings.append("type for '%s' doesn't apply " - "to any variable or argument" % arg) - - else: # Unespected field - fields.append(field) - elif (isinstance(api_doc, RoutineDoc) and api_doc.canonical_name[-1] == '__init__'): class_doc = docindex.get_valdoc(api_doc.canonical_name[:-1]) @@ -332,6 +278,68 @@ if api_doc.sort_spec is UNKNOWN: api_doc.sort_spec = [] +def split_init_fields(fields, init_fields, warnings): + """ + Move the fields related to init into a different list. + C{fields} is supposed obtained from a class docstring. Remove + fields not related to the class from it and add them to C{init_fields}, + which is a list of constructor fields. + """ + # Split fields in lists according to their argument, keeping order. + arg_fields = {} + args_order = [] + i = 0 + while i < len(fields): + field = fields[i] + + # gather together all the fields with the same arg + if field.arg() is not None: + arg_fields.setdefault(field.arg(), []).append(fields.pop(i)) + args_order.append(field.arg()) + else: + i += 1 + + # Now check that for each argument there is at most a single variable + # and a single parameter, and at most a single type for each of them. + for arg in args_order: + ff = arg_fields.pop(arg, None) + if ff is None: + continue + + var = tvar = par = tpar = None + for field in ff: + if field.tag() in VAR_TAGS: + if var is None: + var = field + fields.append(field) + else: + warnings.append("there are more variables " + "named '%s'" % arg) + elif field.tag() in PARAM_TAGS: + if par is None: + par = field + init_fields.append(field) + else: + warnings.append("there are more parameters " + "named '%s'" % arg) + + elif field.tag() == 'type': + gone = False + if var is not None and tvar is None: + tvar = field + fields.append(field) + gone = True + if par is not None and tpar is None: + tpar = field + init_fields.append(field) + gone = True + if not gone: + warnings.append("type for '%s' doesn't apply " + "to any variable or argument" % arg) + + else: # Unespected field + fields.append(field) + def report_errors(api_doc, docindex, parse_errors, field_warnings): """A helper function for L{parse_docstring()} that reports any markup warnings and field warnings that we encountered while This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-15 01:48:02
|
Revision: 1390 http://svn.sourceforge.net/epydoc/?rev=1390&view=rev Author: dvarrazzo Date: 2006-09-14 18:47:53 -0700 (Thu, 14 Sep 2006) Log Message: ----------- - Checked in a new algorithm to split fields in the class docstring between class documentation and constructor documentation. The algorithm requires the `type` fields to appear after the related fields. - Added more test. Modified Paths: -------------- branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 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-14 21:37:38 UTC (rev 1389) +++ branches/exp-args_in_class/epydoc/src/epydoc/docstringparser.py 2006-09-15 01:47:53 UTC (rev 1390) @@ -205,39 +205,75 @@ descr, fields = parsed_docstring.split_fields(parse_errors) api_doc.descr = descr + field_warnings = [] + # Handle the constructor fields that have been defined in the class # docstring. This code assumes that a class docstring is parsed before # the same class __init__ docstring. if isinstance(api_doc, ClassDoc): - # Put aside param-related fields, which are to be considered as - # __init__ fields. "type" fields are to be used in both contexts. - param_tags = ('arg', 'argument', 'parameter', 'param', - 'kwarg', 'keyword', 'kwparam') + + # Split fields in lists according to their argument + arg_fields = {} + args_order = [] i = 0 while i < len(fields): field = fields[i] - if field.tag() in param_tags: - api_doc.init_args.append(fields.pop(i)) + + # gather together all the fields with the same arg + if field.arg() is not None: + arg_fields.setdefault(field.arg(), []).append(fields.pop(i)) + args_order.append(field.arg()) + else: + i += 1 + + # Now check that for each argument there is at most a single variable + # and a single argument, and a single type for them. + for arg in args_order: + ff = arg_fields.pop(arg, None) + if ff is None: continue - elif field.tag() == 'type': - api_doc.init_args.append(field) - i += 1 + var = tvar = par = tpar = None + for field in ff: + if field.tag() in VAR_TAGS: + if var is None: + var = field + fields.append(field) + else: + field_warnings.append("there are more variables " + "named '%s'" % arg) + elif field.tag() in PARAM_TAGS: + if par is None: + par = field + api_doc.init_args.append(field) + else: + field_warnings.append("there are more parameters " + "named '%s'" % arg) + + elif field.tag() == 'type': + gone = False + if var is not None and tvar is None: + tvar = field + fields.append(field) + gone = True + if par is not None and tpar is None: + tpar = field + api_doc.init_args.append(field) + gone = True + if not gone: + field_warnings.append("type for '%s' doesn't apply " + "to any variable or argument" % arg) + + else: # Unespected field + fields.append(field) + elif (isinstance(api_doc, RoutineDoc) - and api_doc.canonical_name[-1] == '__init__'): - # __init__ can receive arguments descriptions from the class docstring - # if a type is specified in both docstring, __init__ wins. + and api_doc.canonical_name[-1] == '__init__'): class_doc = docindex.get_valdoc(api_doc.canonical_name[:-1]) if class_doc is not None and class_doc.init_args is not UNKNOWN: - init_types = [ field.arg() for field in fields - if field.tag() == 'type' ] - for field in class_doc.init_args: - if field.tag() == 'type' and field.arg() in init_types: - continue - fields.append(field) + fields.extend(class_doc.init_args) # Process fields - field_warnings = [] for field in fields: try: process_field(api_doc, docindex, field.tag(), @@ -671,6 +707,14 @@ register_field_handler(process_raise_field, 'raise', 'raises', 'except', 'exception') +# Tags related to function parameters +PARAM_TAGS = ('arg', 'argument', 'parameter', 'param', + 'kwarg', 'keyword', 'kwparam') + +# Tags related to variables in a class +VAR_TAGS = ('cvar', 'cvariable', + 'ivar', 'ivariable') + ###################################################################### #{ Helper Functions ###################################################################### Modified: branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-14 21:37:38 UTC (rev 1389) +++ branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-15 01:47:53 UTC (rev 1390) @@ -14,6 +14,22 @@ >>> import tempfile, re, os, os.path, textwrap, sys >>> from epydoc.docbuilder import build_doc + >>> from epydoc.apidoc import ClassDoc, RoutineDoc + >>> from epydoc.markup import ParsedDocstring + + >>> def to_plain(docstring): + ... """Conver a parsed docstring into plain text""" + ... if isinstance(docstring, ParsedDocstring): + ... docstring = docstring.to_plaintext(None) + ... return docstring.rsplit() + + >>> def fun_to_plain(val_doc): + ... """Convert parsed docstrings in text from a RoutineDoc""" + ... for k, v in val_doc.arg_types.items(): + ... val_doc.arg_types[k] = to_plain(v) + ... for i, (k, v) in enumerate(val_doc.arg_descrs): + ... val_doc.arg_descrs[i] = (k, to_plain(v)) + >>> def runbuilder(s, attribs='', build=None, exclude=''): ... # Write it to a temp file. ... tmp_dir = tempfile.mkdtemp() @@ -24,6 +40,10 @@ ... val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py')) ... if build: val_doc = val_doc.variables[build].value ... # Display it. + ... if isinstance(val_doc, ClassDoc): + ... for val in val_doc.variables.values(): + ... if isinstance(val.value, RoutineDoc): + ... fun_to_plain(val.value) ... 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) @@ -116,11 +136,18 @@ +- descr = u'A property has no defining module' +- type_descr = u'int' +Stuff from future doesn't appear as variable. + >>> runbuilder(s=""" ... from __future__ import division ... from re import match ... """, ... attribs='variables value') + ModuleDoc for epydoc_test [0] + +- variables + +- match => VariableDoc for epydoc_test.match [1] + +- value + +- ValueDoc for sre.match [2] Specifying constructor signature in class docstring @@ -143,7 +170,7 @@ ... """ ... pass ... ''', - ... introspect="Foo", + ... build="Foo", ... attribs="variables name value " ... "posargs vararg kwarg type arg_types arg_descrs") ClassDoc for epydoc_test.Foo [0] @@ -176,7 +203,7 @@ ... @type a: str ... """ ... ''', - ... introspect="Foo", + ... build="Foo", ... attribs="variables name value " ... "posargs vararg kwarg type arg_types arg_descrs") ClassDoc for epydoc_test.Foo [0] @@ -192,6 +219,7 @@ +- vararg = None A missing docstring on the __init__ is not an issue. + >>> runbuilder(s=''' ... class Foo: ... """This is the object docstring @@ -202,7 +230,7 @@ ... def __init__(self): ... pass ... ''', - ... introspect="Foo", + ... build="Foo", ... attribs="variables name value " ... "posargs vararg kwarg type arg_types arg_descrs") ClassDoc for epydoc_test.Foo [0] @@ -232,7 +260,7 @@ ... """__init__ doc""" ... pass ... ''', - ... introspect="Foo", + ... build="Foo", ... attribs="variables name value " ... "posargs vararg kwarg type arg_types arg_descrs docstring") ClassDoc for epydoc_test.Foo [0] @@ -249,3 +277,108 @@ +- kwarg = None +- posargs = [u'x', u'y'] +- vararg = None + +A type can apply to both a param and a variable + + >>> runbuilder(s=''' + ... class Foo: + ... """This is the object docstring + ... + ... @param a: init param. + ... @ivar a: instance var. + ... @type a: date + ... """ + ... def __init__(self, a): + ... pass + ... ''', + ... build="Foo", + ... attribs="variables name value " + ... "posargs vararg kwarg type_descr arg_types arg_descrs") + ClassDoc for epydoc_test.Foo [0] + +- variables + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1] + | +- name = '__init__' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.__init__ [2] + | +- arg_descrs = [([u'a'], [u'init', u'param.'])] + | +- arg_types = {u'a': [u'date']} + | +- kwarg = None + | +- posargs = ['self', 'a'] + | +- vararg = None + +- a => VariableDoc for epydoc_test.Foo.a [3] + +- name = u'a' + +- type_descr = u'date\n\n' + +- value = <UNKNOWN> + +But there can also be two different types + + >>> runbuilder(s=''' + ... class Foo: + ... """This is the object docstring + ... + ... @param a: init param. + ... @type a: string + ... @ivar a: instance var. + ... @type a: date + ... """ + ... def __init__(self, a): + ... pass + ... ''', + ... build="Foo", + ... attribs="variables name value " + ... "posargs vararg kwarg type_descr arg_types arg_descrs") + ClassDoc for epydoc_test.Foo [0] + +- variables + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1] + | +- name = '__init__' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.__init__ [2] + | +- arg_descrs = [([u'a'], [u'init', u'param.'])] + | +- arg_types = {u'a': [u'string']} + | +- kwarg = None + | +- posargs = ['self', 'a'] + | +- vararg = None + +- a => VariableDoc for epydoc_test.Foo.a [3] + +- name = u'a' + +- type_descr = u'date\n\n' + +- value = <UNKNOWN> + +Also reST consolidated fields are not a problem. + + >>> runbuilder(s=''' + ... __docformat__ = 'restructuredtext' + ... class Foo: + ... """This is the object docstring + ... + ... :Parameters: + ... `a` : string + ... init param. + ... + ... :IVariables: + ... `a` : date + ... instance var. + ... """ + ... def __init__(self, a): + ... pass + ... ''', + ... build="Foo", + ... attribs="variables name value " + ... "posargs vararg kwarg type_descr arg_types arg_descrs") + ClassDoc for epydoc_test.Foo [0] + +- variables + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1] + | +- name = '__init__' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.__init__ [2] + | +- arg_descrs = [([u'a'], [u'init', u'param.'])] + | +- arg_types = {u'a': [u'string']} + | +- kwarg = None + | +- posargs = ['self', 'a'] + | +- vararg = None + +- a => VariableDoc for epydoc_test.Foo.a [3] + +- name = u'a' + +- type_descr = u'date' + +- value = <UNKNOWN> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-14 21:37:55
|
Revision: 1389 http://svn.sourceforge.net/epydoc/?rev=1389&view=rev Author: dvarrazzo Date: 2006-09-14 14:37:38 -0700 (Thu, 14 Sep 2006) Log Message: ----------- Merged revisions 1376-1388 via svnmerge from https://svn.sourceforge.net/svnroot/epydoc/trunk ........ r1377 | edloper | 2006-09-10 16:29:31 +0200 (Sun, 10 Sep 2006) | 4 lines - Fixed bug where base tree generation would fail if the context was UNKNOWN (e.g., if we can't determine what the containing module is.) ........ r1378 | dvarrazzo | 2006-09-10 17:16:41 +0200 (Sun, 10 Sep 2006) | 2 lines Fixed typo. ........ r1379 | dvarrazzo | 2006-09-10 18:23:49 +0200 (Sun, 10 Sep 2006) | 15 lines - Don't strip empty lines from documentation comment blocks. Without the patch, a block such:: #: frobnication factor #: #: :type: ``int`` is transformed in the string:: frobnication factor :type: ``int`` that is a docstring error (the field is not recognized). ........ r1380 | dvarrazzo | 2006-09-10 18:31:38 +0200 (Sun, 10 Sep 2006) | 6 lines - defining_module is propagated to object which don't have other means to detect it, such as properties. So docformat can be correctly detected for such objects too. - Added a test suite to verify docbuilder behavior. ........ r1381 | edloper | 2006-09-11 00:43:02 +0200 (Mon, 11 Sep 2006) | 4 lines - When checking keyword args to APIDoc constructor, don't complain about args that begin with '_'. - Minor docstring changes ........ r1382 | edloper | 2006-09-11 00:43:51 +0200 (Mon, 11 Sep 2006) | 3 lines - When building stdlib docs, don't include any graphs or source code -- the quota on sourceforge won't allow enough space for them. :( ........ r1383 | dvarrazzo | 2006-09-11 14:34:31 +0200 (Mon, 11 Sep 2006) | 6 lines - Fixed docutils version check. E.g. when docutils.__version__ == '0.4' => [ 0, 4 ] < [ 0, 4, 0 ] == True => Deprecation warnings are raised. ........ r1384 | dvarrazzo | 2006-09-11 15:42:10 +0200 (Mon, 11 Sep 2006) | 9 lines - Introspecter doesn't document the object resulting from a "from __future__" statement. Because the check deals with the implementation of a quasi-magic module, guard from unexpected implementation changes. In such case, issue a single warning and don't barf. The current implementation is tested with Python 2.4.3. ........ r1385 | dvarrazzo | 2006-09-11 15:45:12 +0200 (Mon, 11 Sep 2006) | 2 lines - Replaced a "!= None" test with an "is not None" ........ r1386 | dvarrazzo | 2006-09-11 18:12:51 +0200 (Mon, 11 Sep 2006) | 4 lines - Fixed parsing of import statements in the form:: from mod import a as b ........ r1387 | dvarrazzo | 2006-09-13 05:04:00 +0200 (Wed, 13 Sep 2006) | 3 lines - Added a filter to remove the class vtable generated by Pyrex for extension modules. ........ r1388 | dvarrazzo | 2006-09-13 05:24:38 +0200 (Wed, 13 Sep 2006) | 2 lines - member_descriptor attributes are recognized as property. ........ Modified Paths: -------------- branches/exp-args_in_class/epydoc/Makefile branches/exp-args_in_class/epydoc/doc/doctest/index.html branches/exp-args_in_class/epydoc/doc/fields.html branches/exp-args_in_class/epydoc/src/epydoc/apidoc.py branches/exp-args_in_class/epydoc/src/epydoc/docbuilder.py branches/exp-args_in_class/epydoc/src/epydoc/docintrospecter.py branches/exp-args_in_class/epydoc/src/epydoc/docparser.py branches/exp-args_in_class/epydoc/src/epydoc/docwriter/html.py branches/exp-args_in_class/epydoc/src/epydoc/markup/restructuredtext.py branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest branches/exp-args_in_class/epydoc/src/epydoc/test/docintrospecter.doctest branches/exp-args_in_class/epydoc/src/epydoc/test/docparser.doctest Property Changed: ---------------- branches/exp-args_in_class/ Property changes on: branches/exp-args_in_class ___________________________________________________________________ Name: svnmerge-integrated - /trunk:1-1375 + /trunk:1-1388 Modified: branches/exp-args_in_class/epydoc/Makefile =================================================================== --- branches/exp-args_in_class/epydoc/Makefile 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/Makefile 2006-09-14 21:37:38 UTC (rev 1389) @@ -235,7 +235,7 @@ mkdir -p $(HTML_STDLIB) @echo "Building stdlib html docs..." @$(EPYDOC) -o $(HTML_STDLIB) --css white --name $(SLNAME) \ - --url $(SLURL) --debug --graph classtree --debug \ + --url $(SLURL) --debug --no-sourcecode --debug \ --show-imports $(SLBUILTINS) $(SLFILES) touch .stdlib-html.up2date Modified: branches/exp-args_in_class/epydoc/doc/doctest/index.html =================================================================== --- branches/exp-args_in_class/epydoc/doc/doctest/index.html 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/doc/doctest/index.html 2006-09-14 21:37:38 UTC (rev 1389) @@ -27,6 +27,9 @@ <li> <a href="docparser.html">Source Code Parsing</a> -- Extracting API information about Python objects by parsing their source code.</li> + <li> <a href="docbuilder.html">Documentation building</a> -- + Merging different information sources into a single API + hypertext. <li> <a href="encoding.html">Unicode & Encodings</a> -- Tests for the processing of Python files that use non-ascii encodings. </li> Modified: branches/exp-args_in_class/epydoc/doc/fields.html =================================================================== --- branches/exp-args_in_class/epydoc/doc/fields.html 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/doc/fields.html 2006-09-14 21:37:38 UTC (rev 1389) @@ -262,7 +262,7 @@ fields may be used if an object has multiple authors.</td></tr> <tr><td width="10%" align="left" valign="top"> - <code>@<b>organiation</b>:</code> ... </td><td> The + <code>@<b>organization</b>:</code> ... </td><td> The organization that created or maintains an object. </td></tr> Modified: branches/exp-args_in_class/epydoc/src/epydoc/apidoc.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/apidoc.py 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/apidoc.py 2006-09-14 21:37:38 UTC (rev 1389) @@ -374,7 +374,7 @@ """ if epydoc.DEBUG: for key in kwargs: - if not hasattr(self.__class__, key): + if key[0] != '_' and not hasattr(self.__class__, key): raise TypeError('%s got unexpected arg %r' % (self.__class__.__name__, key)) self.__dict__.update(kwargs) @@ -850,7 +850,7 @@ names, and the values are lists of C{VariableDoc}s. The order that groups should be listed in should be taken from L{group_specs}. - @type: C{dict} from C{str} to C{list} of L{APIDoc}""" + @type: C{dict} from C{str} to C{list} of L{VariableDoc}""" #} end of group "information about variables" def __init__(self, **kwargs): @@ -996,7 +996,7 @@ names, and the values are lists of C{ModuleDoc}s. The order that groups should be listed in should be taken from L{group_specs}. - @type: C{dict} from C{str} to C{list} of L{APIDoc}""" + @type: C{dict} from C{str} to C{list} of L{ModuleDoc}""" #{ Information about Packages package = UNKNOWN """@ivar: API documentation for the module's containing package. Modified: branches/exp-args_in_class/epydoc/src/epydoc/docbuilder.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/docbuilder.py 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/docbuilder.py 2006-09-14 21:37:38 UTC (rev 1389) @@ -191,6 +191,12 @@ if (isinstance(val_doc, NamespaceDoc) and val_doc.variables not in (None, UNKNOWN)): for var_doc in val_doc.variables.values(): + # Now we have a chance to propagate the defining module + # to objects for which introspection is not possible, + # such as properties. + if (isinstance(var_doc.value, ValueDoc) + and var_doc.value.defining_module is UNKNOWN): + var_doc.value.defining_module = val_doc.defining_module parse_docstring(var_doc, docindex) log.end_progress() Modified: branches/exp-args_in_class/epydoc/src/epydoc/docintrospecter.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/docintrospecter.py 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/docintrospecter.py 2006-09-14 21:37:38 UTC (rev 1389) @@ -246,7 +246,7 @@ # Create a VariableDoc for the child, and introspect its # value if it's defined in this module. container = get_containing_module(child) - if container != None and container == module_doc.canonical_name: + if container is not None and container == module_doc.canonical_name: # Local variable. child_val_doc = introspect_docs(child, context=module_doc) child_var_doc = VariableDoc(name=child_name, @@ -255,6 +255,10 @@ container=module_doc, docs_extracted_by='introspecter') elif container is None or module_doc.canonical_name is UNKNOWN: + + # Don't introspect stuff "from __future__" + if is_future_feature(child): continue + # Possibly imported variable. child_val_doc = introspect_docs(child, context=module_doc) child_var_doc = VariableDoc(name=child_name, @@ -295,7 +299,8 @@ #: A list of class variables that should not be included in a #: class's API documentation. UNDOCUMENTED_CLASS_VARS = ( - '__doc__', '__module__', '__dict__', '__weakref__', '__slots__') + '__doc__', '__module__', '__dict__', '__weakref__', '__slots__', + '__pyx_vtable__') def introspect_class(cls, class_doc): """ @@ -483,6 +488,31 @@ """ return isinstance(object, (TypeType, ClassType)) +__future_check_works = None + +def is_future_feature(object): + """ + Return True if C{object} results from a C{from __future__ import feature"} + statement. + """ + # Guard from unexpected implementation changes of the __future__ module. + global __future_check_works + if __future_check_works is not None: + if __future_check_works: + import __future__ + return isinstance(object, __future__._Feature) + else: + return False + else: + __future_check_works = True + try: + return is_future_feature(object) + except: + __future_check_works = False + log.warning("Troubles inspecting __future__. Python implementation" + " may have been changed.") + return False + def get_docstring(value): """ Return the docstring for the given value; or C{None} if it @@ -685,15 +715,26 @@ register_introspecter(inspect.isroutine, introspect_routine, priority=28) register_introspecter(is_property, introspect_property, priority=30) +# Register getset_descriptor as a property try: import array - attribute = type(array.array.typecode) + getset_type = type(array.array.typecode) del array - def is_attribute(v): return isinstance(v, attribute) - register_introspecter(is_attribute, introspect_property, priority=32) + def is_getset(v): return isinstance(v, getset_type) + register_introspecter(is_getset, introspect_property, priority=32) except: pass +# Register member_descriptor as a property +try: + import datetime + member_type = type(datetime.timedelta.days) + del datetime + def is_member(v): return isinstance(v, member_type) + register_introspecter(is_member, introspect_property, priority=34) +except: + pass + #//////////////////////////////////////////////////////////// # Import support #//////////////////////////////////////////////////////////// Modified: branches/exp-args_in_class/epydoc/src/epydoc/docparser.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/docparser.py 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/docparser.py 2006-09-14 21:37:38 UTC (rev 1389) @@ -157,7 +157,7 @@ """ #{ Configuration Constants: Comment docstrings -COMMENT_DOCSTRING_MARKER = '#: ' +COMMENT_DOCSTRING_MARKER = '#:' """The prefix used to mark comments that contain attribute docstrings for variables.""" @@ -577,6 +577,8 @@ elif toktype == tokenize.COMMENT: if toktext.startswith(COMMENT_DOCSTRING_MARKER): comment_line = toktext[len(COMMENT_DOCSTRING_MARKER):].rstrip() + if comment_line.startswith(" "): + comment_line = comment_line[1:] comments.append( [comment_line, srow]) elif toktext.startswith(START_GROUP_MARKER): start_group = toktext[len(START_GROUP_MARKER):].strip() @@ -844,12 +846,24 @@ # >>> from os.path import join, split else: src_name = parse_dotted_name(lhs) - for elt in rhs: - if elt != (token.OP, ','): - var_name = parse_name(elt) + parts = split_on(rhs, (token.OP, ',')) + for part in parts: + # from m import x + if len(part) == 1: + var_name = parse_name(part[0]) _import_var_as(DottedName(src_name, var_name), var_name, parent_docs) - + + # from m import x as y + elif len(part) == 3 and part[1] == (token.NAME, 'as'): + orig_name = parse_name(part[0]) + var_name = parse_name(part[2]) + _import_var_as(DottedName(src_name, orig_name), + var_name, parent_docs) + + else: + ParseError("Bad from-import") + def _process_fromstar_import(src, parent_docs): """ Handle a statement of the form: Modified: branches/exp-args_in_class/epydoc/src/epydoc/docwriter/html.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/docwriter/html.py 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/docwriter/html.py 2006-09-14 21:37:38 UTC (rev 1389) @@ -2498,8 +2498,11 @@ else: return '??' else: - context_name = context.canonical_name - return str(doc.canonical_name.contextualize(context_name)) + if context is UNKNOWN: + return str(doc.canonical_name) + else: + context_name = context.canonical_name + return str(doc.canonical_name.contextualize(context_name)) #//////////////////////////////////////////////////////////// #{ Function Signatures Modified: branches/exp-args_in_class/epydoc/src/epydoc/markup/restructuredtext.py =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/markup/restructuredtext.py 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/markup/restructuredtext.py 2006-09-14 21:37:38 UTC (rev 1389) @@ -215,7 +215,9 @@ # depending on the version of docutils that's being used, because # the default_transforms attribute was deprecated & replaced by # get_transforms(). - if [int(v) for v in docutils.__version__.split('.')] < [0,4,0]: + version = [int(v) for v in docutils.__version__.split('.')] + version += [ 0 ] * (3 - len(version)) + if version < [0,4,0]: default_transforms = list(StandaloneReader.default_transforms) try: default_transforms.remove(docutils.transforms.frontmatter.DocInfo) except ValueError: pass @@ -223,6 +225,7 @@ def get_transforms(self): return [t for t in StandaloneReader.get_transforms(self) if t != docutils.transforms.frontmatter.DocInfo] + del version def __init__(self, errors): self._errors = errors Modified: branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-14 21:37:38 UTC (rev 1389) @@ -3,31 +3,26 @@ 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. +of the `APIDoc`s should be displayed. The `build` argument gives the +name of a variable in the module whose documentation should be built, +instead of bilding docs for the whole module. >>> import tempfile, re, os, os.path, textwrap, sys >>> from epydoc.docbuilder import build_doc - >>> def runbuilder(s, attribs='', introspect=None, exclude=''): + >>> def runbuilder(s, attribs='', build=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) + ... # Build it. + ... val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py')) + ... if build: val_doc = val_doc.variables[build].value ... # Display it. ... s = val_doc.pp(include=attribs.split(),exclude=exclude.split()) ... s = re.sub(r"(filename = ).*", r"\1...", s) @@ -42,7 +37,92 @@ ... os.rmdir(tmp_dir) ... del sys.modules['epydoc_test'] +Docformat selection +=================== +The docstrings format can be selected using the ``__docformat__`` module +variable. + + >>> runbuilder(s=''' + ... __docformat__ = 'restructuredtext' + ... + ... class Foo: + ... """Testing defining_module + ... + ... :cvar `c`: class var in class docstring + ... :type `c`: str + ... """ + ... c = 'abc' + ... + ... def __init__(self): + ... #: A funny number + ... #: + ... #: :type: float + ... self.x = 108.0 + ... + ... y = property( + ... fget=lambda self: 42, + ... doc="""A property has no defining module + ... + ... :type: int + ... """) + ... + ... def f(self): + ... """A function has a defining module + ... + ... :rtype: int + ... """ + ... return 42 + ... ''', + ... build='Foo', + ... attribs="variables name value type_descr return_type descr") + ClassDoc for epydoc_test.Foo [0] + +- descr = u'Testing defining_module' + +- variables + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1] + | +- descr = None + | +- name = '__init__' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.__init__ [2] + | +- descr = None + | +- return_type = None + +- c => VariableDoc for epydoc_test.Foo.c [3] + | +- descr = u'class var in class docstring' + | +- name = 'c' + | +- type_descr = u'str' + | +- value + | +- GenericValueDoc [4] + | +- descr = None + +- f => VariableDoc for epydoc_test.Foo.f [5] + | +- descr = None + | +- name = 'f' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.f [6] + | +- descr = u'A function has a defining module' + | +- return_type = u'int' + +- x => VariableDoc for epydoc_test.Foo.x [7] + | +- descr = u'A funny number' + | +- name = u'x' + | +- type_descr = u'float' + | +- value = <UNKNOWN> + +- y => VariableDoc for epydoc_test.Foo.y [8] + +- descr = None + +- name = 'y' + +- type_descr = None + +- value + +- PropertyDoc for epydoc_test.Foo.y [9] + +- descr = u'A property has no defining module' + +- type_descr = u'int' + + >>> runbuilder(s=""" + ... from __future__ import division + ... from re import match + ... """, + ... attribs='variables value') + + Specifying constructor signature in class docstring =================================================== Modified: branches/exp-args_in_class/epydoc/src/epydoc/test/docintrospecter.doctest =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/test/docintrospecter.doctest 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/test/docintrospecter.doctest 2006-09-14 21:37:38 UTC (rev 1389) @@ -520,6 +520,16 @@ +- ModuleDoc for re [4] +- variables = {} + >>> runintrospecter(s=""" + ... from __future__ import division + ... from re import match + ... """, + ... attribs='variables value') + ModuleDoc for epydoc_test [0] + +- variables + +- match => VariableDoc for epydoc_test.match [1] + +- value + +- ValueDoc for sre.match [2] Unicode ======= Modified: branches/exp-args_in_class/epydoc/src/epydoc/test/docparser.doctest =================================================================== --- branches/exp-args_in_class/epydoc/src/epydoc/test/docparser.doctest 2006-09-13 03:24:38 UTC (rev 1388) +++ branches/exp-args_in_class/epydoc/src/epydoc/test/docparser.doctest 2006-09-14 21:37:38 UTC (rev 1389) @@ -710,6 +710,21 @@ +- is_imported = True +- value = <UNKNOWN> + >>> runparser(s=""" + ... from re import match as much, split, sub as scuba + ... """, + ... attribs='variables name imported_from') + ModuleDoc for test [0] + +- variables + +- much => VariableDoc for test.much [1] + | +- imported_from = DottedName(u're', u'match') + | +- name = u'much' + +- scuba => VariableDoc for test.scuba [2] + | +- imported_from = DottedName(u're', u'sub') + | +- name = u'scuba' + +- split => VariableDoc for test.split [3] + +- imported_from = DottedName(u're', u'split') + +- name = u'split' Unicode ======= This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-13 03:24:43
|
Revision: 1388 http://svn.sourceforge.net/epydoc/?rev=1388&view=rev Author: dvarrazzo Date: 2006-09-12 20:24:38 -0700 (Tue, 12 Sep 2006) Log Message: ----------- - member_descriptor attributes are recognized as property. Modified Paths: -------------- trunk/epydoc/src/epydoc/docintrospecter.py Modified: trunk/epydoc/src/epydoc/docintrospecter.py =================================================================== --- trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-13 03:04:00 UTC (rev 1387) +++ trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-13 03:24:38 UTC (rev 1388) @@ -715,15 +715,26 @@ register_introspecter(inspect.isroutine, introspect_routine, priority=28) register_introspecter(is_property, introspect_property, priority=30) +# Register getset_descriptor as a property try: import array - attribute = type(array.array.typecode) + getset_type = type(array.array.typecode) del array - def is_attribute(v): return isinstance(v, attribute) - register_introspecter(is_attribute, introspect_property, priority=32) + def is_getset(v): return isinstance(v, getset_type) + register_introspecter(is_getset, introspect_property, priority=32) except: pass +# Register member_descriptor as a property +try: + import datetime + member_type = type(datetime.timedelta.days) + del datetime + def is_member(v): return isinstance(v, member_type) + register_introspecter(is_member, introspect_property, priority=34) +except: + pass + #//////////////////////////////////////////////////////////// # Import support #//////////////////////////////////////////////////////////// This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-13 03:04:05
|
Revision: 1387 http://svn.sourceforge.net/epydoc/?rev=1387&view=rev Author: dvarrazzo Date: 2006-09-12 20:04:00 -0700 (Tue, 12 Sep 2006) Log Message: ----------- - Added a filter to remove the class vtable generated by Pyrex for extension modules. Modified Paths: -------------- trunk/epydoc/src/epydoc/docintrospecter.py Modified: trunk/epydoc/src/epydoc/docintrospecter.py =================================================================== --- trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-11 16:12:51 UTC (rev 1386) +++ trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-13 03:04:00 UTC (rev 1387) @@ -299,7 +299,8 @@ #: A list of class variables that should not be included in a #: class's API documentation. UNDOCUMENTED_CLASS_VARS = ( - '__doc__', '__module__', '__dict__', '__weakref__', '__slots__') + '__doc__', '__module__', '__dict__', '__weakref__', '__slots__', + '__pyx_vtable__') def introspect_class(cls, class_doc): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-11 16:13:01
|
Revision: 1386 http://svn.sourceforge.net/epydoc/?rev=1386&view=rev Author: dvarrazzo Date: 2006-09-11 09:12:51 -0700 (Mon, 11 Sep 2006) Log Message: ----------- - Fixed parsing of import statements in the form:: from mod import a as b Modified Paths: -------------- trunk/epydoc/src/epydoc/docparser.py trunk/epydoc/src/epydoc/test/docparser.doctest Modified: trunk/epydoc/src/epydoc/docparser.py =================================================================== --- trunk/epydoc/src/epydoc/docparser.py 2006-09-11 13:45:12 UTC (rev 1385) +++ trunk/epydoc/src/epydoc/docparser.py 2006-09-11 16:12:51 UTC (rev 1386) @@ -846,12 +846,24 @@ # >>> from os.path import join, split else: src_name = parse_dotted_name(lhs) - for elt in rhs: - if elt != (token.OP, ','): - var_name = parse_name(elt) + parts = split_on(rhs, (token.OP, ',')) + for part in parts: + # from m import x + if len(part) == 1: + var_name = parse_name(part[0]) _import_var_as(DottedName(src_name, var_name), var_name, parent_docs) - + + # from m import x as y + elif len(part) == 3 and part[1] == (token.NAME, 'as'): + orig_name = parse_name(part[0]) + var_name = parse_name(part[2]) + _import_var_as(DottedName(src_name, orig_name), + var_name, parent_docs) + + else: + ParseError("Bad from-import") + def _process_fromstar_import(src, parent_docs): """ Handle a statement of the form: Modified: trunk/epydoc/src/epydoc/test/docparser.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docparser.doctest 2006-09-11 13:45:12 UTC (rev 1385) +++ trunk/epydoc/src/epydoc/test/docparser.doctest 2006-09-11 16:12:51 UTC (rev 1386) @@ -710,6 +710,21 @@ +- is_imported = True +- value = <UNKNOWN> + >>> runparser(s=""" + ... from re import match as much, split, sub as scuba + ... """, + ... attribs='variables name imported_from') + ModuleDoc for test [0] + +- variables + +- much => VariableDoc for test.much [1] + | +- imported_from = DottedName(u're', u'match') + | +- name = u'much' + +- scuba => VariableDoc for test.scuba [2] + | +- imported_from = DottedName(u're', u'sub') + | +- name = u'scuba' + +- split => VariableDoc for test.split [3] + +- imported_from = DottedName(u're', u'split') + +- name = u'split' Unicode ======= This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-11 13:45:24
|
Revision: 1385 http://svn.sourceforge.net/epydoc/?rev=1385&view=rev Author: dvarrazzo Date: 2006-09-11 06:45:12 -0700 (Mon, 11 Sep 2006) Log Message: ----------- - Replaced a "!= None" test with an "is not None" Modified Paths: -------------- trunk/epydoc/src/epydoc/docintrospecter.py Modified: trunk/epydoc/src/epydoc/docintrospecter.py =================================================================== --- trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-11 13:42:10 UTC (rev 1384) +++ trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-11 13:45:12 UTC (rev 1385) @@ -246,7 +246,7 @@ # Create a VariableDoc for the child, and introspect its # value if it's defined in this module. container = get_containing_module(child) - if container != None and container == module_doc.canonical_name: + if container is not None and container == module_doc.canonical_name: # Local variable. child_val_doc = introspect_docs(child, context=module_doc) child_var_doc = VariableDoc(name=child_name, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-11 13:42:21
|
Revision: 1384 http://svn.sourceforge.net/epydoc/?rev=1384&view=rev Author: dvarrazzo Date: 2006-09-11 06:42:10 -0700 (Mon, 11 Sep 2006) Log Message: ----------- - Introspecter doesn't document the object resulting from a "from __future__" statement. Because the check deals with the implementation of a quasi-magic module, guard from unexpected implementation changes. In such case, issue a single warning and don't barf. The current implementation is tested with Python 2.4.3. Modified Paths: -------------- trunk/epydoc/src/epydoc/docintrospecter.py trunk/epydoc/src/epydoc/test/docintrospecter.doctest Modified: trunk/epydoc/src/epydoc/docintrospecter.py =================================================================== --- trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-11 12:34:31 UTC (rev 1383) +++ trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-11 13:42:10 UTC (rev 1384) @@ -255,6 +255,10 @@ container=module_doc, docs_extracted_by='introspecter') elif container is None or module_doc.canonical_name is UNKNOWN: + + # Don't introspect stuff "from __future__" + if is_future_feature(child): continue + # Possibly imported variable. child_val_doc = introspect_docs(child, context=module_doc) child_var_doc = VariableDoc(name=child_name, @@ -483,6 +487,31 @@ """ return isinstance(object, (TypeType, ClassType)) +__future_check_works = None + +def is_future_feature(object): + """ + Return True if C{object} results from a C{from __future__ import feature"} + statement. + """ + # Guard from unexpected implementation changes of the __future__ module. + global __future_check_works + if __future_check_works is not None: + if __future_check_works: + import __future__ + return isinstance(object, __future__._Feature) + else: + return False + else: + __future_check_works = True + try: + return is_future_feature(object) + except: + __future_check_works = False + log.warning("Troubles inspecting __future__. Python implementation" + " may have been changed.") + return False + def get_docstring(value): """ Return the docstring for the given value; or C{None} if it Modified: trunk/epydoc/src/epydoc/test/docintrospecter.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docintrospecter.doctest 2006-09-11 12:34:31 UTC (rev 1383) +++ trunk/epydoc/src/epydoc/test/docintrospecter.doctest 2006-09-11 13:42:10 UTC (rev 1384) @@ -520,6 +520,16 @@ +- ModuleDoc for re [4] +- variables = {} + >>> runintrospecter(s=""" + ... from __future__ import division + ... from re import match + ... """, + ... attribs='variables value') + ModuleDoc for epydoc_test [0] + +- variables + +- match => VariableDoc for epydoc_test.match [1] + +- value + +- ValueDoc for sre.match [2] Unicode ======= This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-11 12:34:44
|
Revision: 1383 http://svn.sourceforge.net/epydoc/?rev=1383&view=rev Author: dvarrazzo Date: 2006-09-11 05:34:31 -0700 (Mon, 11 Sep 2006) Log Message: ----------- - Fixed docutils version check. E.g. when docutils.__version__ == '0.4' => [ 0, 4 ] < [ 0, 4, 0 ] == True => Deprecation warnings are raised. Modified Paths: -------------- trunk/epydoc/src/epydoc/markup/restructuredtext.py Modified: trunk/epydoc/src/epydoc/markup/restructuredtext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-09-10 22:43:51 UTC (rev 1382) +++ trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-09-11 12:34:31 UTC (rev 1383) @@ -215,7 +215,9 @@ # depending on the version of docutils that's being used, because # the default_transforms attribute was deprecated & replaced by # get_transforms(). - if [int(v) for v in docutils.__version__.split('.')] < [0,4,0]: + version = [int(v) for v in docutils.__version__.split('.')] + version += [ 0 ] * (3 - len(version)) + if version < [0,4,0]: default_transforms = list(StandaloneReader.default_transforms) try: default_transforms.remove(docutils.transforms.frontmatter.DocInfo) except ValueError: pass @@ -223,6 +225,7 @@ def get_transforms(self): return [t for t in StandaloneReader.get_transforms(self) if t != docutils.transforms.frontmatter.DocInfo] + del version def __init__(self, errors): self._errors = errors This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-10 22:43:55
|
Revision: 1382 http://svn.sourceforge.net/epydoc/?rev=1382&view=rev Author: edloper Date: 2006-09-10 15:43:51 -0700 (Sun, 10 Sep 2006) Log Message: ----------- - When building stdlib docs, don't include any graphs or source code -- the quota on sourceforge won't allow enough space for them. :( Modified Paths: -------------- trunk/epydoc/Makefile Modified: trunk/epydoc/Makefile =================================================================== --- trunk/epydoc/Makefile 2006-09-10 22:43:02 UTC (rev 1381) +++ trunk/epydoc/Makefile 2006-09-10 22:43:51 UTC (rev 1382) @@ -235,7 +235,7 @@ mkdir -p $(HTML_STDLIB) @echo "Building stdlib html docs..." @$(EPYDOC) -o $(HTML_STDLIB) --css white --name $(SLNAME) \ - --url $(SLURL) --debug --graph classtree --debug \ + --url $(SLURL) --debug --no-sourcecode --debug \ --show-imports $(SLBUILTINS) $(SLFILES) touch .stdlib-html.up2date This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-10 22:43:05
|
Revision: 1381 http://svn.sourceforge.net/epydoc/?rev=1381&view=rev Author: edloper Date: 2006-09-10 15:43:02 -0700 (Sun, 10 Sep 2006) Log Message: ----------- - When checking keyword args to APIDoc constructor, don't complain about args that begin with '_'. - Minor docstring changes Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-10 16:31:38 UTC (rev 1380) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-10 22:43:02 UTC (rev 1381) @@ -374,7 +374,7 @@ """ if epydoc.DEBUG: for key in kwargs: - if not hasattr(self.__class__, key): + if key[0] != '_' and not hasattr(self.__class__, key): raise TypeError('%s got unexpected arg %r' % (self.__class__.__name__, key)) self.__dict__.update(kwargs) @@ -850,7 +850,7 @@ names, and the values are lists of C{VariableDoc}s. The order that groups should be listed in should be taken from L{group_specs}. - @type: C{dict} from C{str} to C{list} of L{APIDoc}""" + @type: C{dict} from C{str} to C{list} of L{VariableDoc}""" #} end of group "information about variables" def __init__(self, **kwargs): @@ -996,7 +996,7 @@ names, and the values are lists of C{ModuleDoc}s. The order that groups should be listed in should be taken from L{group_specs}. - @type: C{dict} from C{str} to C{list} of L{APIDoc}""" + @type: C{dict} from C{str} to C{list} of L{ModuleDoc}""" #{ Information about Packages package = UNKNOWN """@ivar: API documentation for the module's containing package. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2006-09-10 16:31:52
|
Revision: 1380 http://svn.sourceforge.net/epydoc/?rev=1380&view=rev Author: dvarrazzo Date: 2006-09-10 09:31:38 -0700 (Sun, 10 Sep 2006) Log Message: ----------- - defining_module is propagated to object which don't have other means to detect it, such as properties. So docformat can be correctly detected for such objects too. - Added a test suite to verify docbuilder behavior. Modified Paths: -------------- trunk/epydoc/doc/doctest/index.html trunk/epydoc/src/epydoc/docbuilder.py Added Paths: ----------- trunk/epydoc/src/epydoc/test/docbuilder.doctest Modified: trunk/epydoc/doc/doctest/index.html =================================================================== --- trunk/epydoc/doc/doctest/index.html 2006-09-10 16:23:49 UTC (rev 1379) +++ trunk/epydoc/doc/doctest/index.html 2006-09-10 16:31:38 UTC (rev 1380) @@ -27,6 +27,9 @@ <li> <a href="docparser.html">Source Code Parsing</a> -- Extracting API information about Python objects by parsing their source code.</li> + <li> <a href="docbuilder.html">Documentation building</a> -- + Merging different information sources into a single API + hypertext. <li> <a href="encoding.html">Unicode & Encodings</a> -- Tests for the processing of Python files that use non-ascii encodings. </li> Modified: trunk/epydoc/src/epydoc/docbuilder.py =================================================================== --- trunk/epydoc/src/epydoc/docbuilder.py 2006-09-10 16:23:49 UTC (rev 1379) +++ trunk/epydoc/src/epydoc/docbuilder.py 2006-09-10 16:31:38 UTC (rev 1380) @@ -188,6 +188,12 @@ if (isinstance(val_doc, NamespaceDoc) and val_doc.variables not in (None, UNKNOWN)): for var_doc in val_doc.variables.values(): + # Now we have a chance to propagate the defining module + # to objects for which introspection is not possible, + # such as properties. + if (isinstance(var_doc.value, ValueDoc) + and var_doc.value.defining_module is UNKNOWN): + var_doc.value.defining_module = val_doc.defining_module parse_docstring(var_doc, docindex) log.end_progress() Added: trunk/epydoc/src/epydoc/test/docbuilder.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docbuilder.doctest (rev 0) +++ trunk/epydoc/src/epydoc/test/docbuilder.doctest 2006-09-10 16:31:38 UTC (rev 1380) @@ -0,0 +1,117 @@ +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 `build` argument gives the +name of a variable in the module whose documentation should be built, +instead of bilding docs for the whole module. + + >>> import tempfile, re, os, os.path, textwrap, sys + >>> from epydoc.docbuilder import build_doc + >>> def runbuilder(s, attribs='', build=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() + ... # Build it. + ... val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py')) + ... if build: val_doc = val_doc.variables[build].value + ... # 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'] + +Docformat selection +=================== + +The docstrings format can be selected using the ``__docformat__`` module +variable. + + >>> runbuilder(s=''' + ... __docformat__ = 'restructuredtext' + ... + ... class Foo: + ... """Testing defining_module + ... + ... :cvar `c`: class var in class docstring + ... :type `c`: str + ... """ + ... c = 'abc' + ... + ... def __init__(self): + ... #: A funny number + ... #: + ... #: :type: float + ... self.x = 108.0 + ... + ... y = property( + ... fget=lambda self: 42, + ... doc="""A property has no defining module + ... + ... :type: int + ... """) + ... + ... def f(self): + ... """A function has a defining module + ... + ... :rtype: int + ... """ + ... return 42 + ... ''', + ... build='Foo', + ... attribs="variables name value type_descr return_type descr") + ClassDoc for epydoc_test.Foo [0] + +- descr = u'Testing defining_module' + +- variables + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [1] + | +- descr = None + | +- name = '__init__' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.__init__ [2] + | +- descr = None + | +- return_type = None + +- c => VariableDoc for epydoc_test.Foo.c [3] + | +- descr = u'class var in class docstring' + | +- name = 'c' + | +- type_descr = u'str' + | +- value + | +- GenericValueDoc [4] + | +- descr = None + +- f => VariableDoc for epydoc_test.Foo.f [5] + | +- descr = None + | +- name = 'f' + | +- type_descr = None + | +- value + | +- RoutineDoc for epydoc_test.Foo.f [6] + | +- descr = u'A function has a defining module' + | +- return_type = u'int' + +- x => VariableDoc for epydoc_test.Foo.x [7] + | +- descr = u'A funny number' + | +- name = u'x' + | +- type_descr = u'float' + | +- value = <UNKNOWN> + +- y => VariableDoc for epydoc_test.Foo.y [8] + +- descr = None + +- name = 'y' + +- type_descr = None + +- value + +- PropertyDoc for epydoc_test.Foo.y [9] + +- descr = u'A property has no defining module' + +- type_descr = u'int' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |