[Doc-SIG] PEP: DPS Generic Implementation Details
David Goodger
dgoodger@bigfoot.com
Sun, 03 Jun 2001 10:32:21 -0400
PEP: ???
Title: DPS Generic Implementation Details
Version: $Revision$
Author: dgoodger@bigfoot.com (David Goodger)
Discussions-To: doc-sig@python.org
Status: Draft
Type: Standards Track
Created: 31-May-2001
Post-History:
Abstract
This PEP documents generic implementation details for a Python
Docstring Processing System (DPS).
Copyright
This document has been placed in the public domain.
Acknowledgements
This document borrows ideas from the archives of the Python Doc-SIG
[1]. Thanks to all members past & present.
Project Website
A SourceForge project has been set up for this work at
http://docstring.sf.net.
Specification
Docstring Extraction Rules
==========================
1. If the '__all__' variable is present in the module being documented,
only identifiers listed in '__all__' are examined for docstrings. In
the absense of '__all__', all identifiers are examined, except those
whose names are private (names begin with '_' but don't begin and
end with '__').
2. Docstrings are string literal expressions, and are recognized in the
following places within Python modules:
a) At the beginning of a module, class definition, or function
definition, after any comments. This is the standard for Python
__doc__ attributes.
b) Immediately following a simple assignment at the top level of a
module, class definition, or __init__ method definition, after
any comments. See "Attribute Docstrings" below.
c) Additional string literals found immediately after the docstrings
in (a) and (b) will be recognized, extracted, and concatenated.
See "Additional Docstrings" below.
3. Python modules must be parsed by the docstring processing system,
not imported. There are security reasons for not importing untrusted
code. Also, docstrings are to be recognized in places where the
bytecode compiler ignores string literal expressions (2b and 2c
above), meaning importing the module will lose these docstrings. Of
course, standard Python parsing tools such as the 'parser' library
module should be used.
Since attribute docstrings and additional docstrings are not recognized
by the Python bytecode compiler, no namespace pollution or performance
degradation will result from their use. (The initial parsing of a
module may take a slight performance hit.)
Attribute Docstrings
--------------------
XXX A description of attribute docstrings would be appropriate in the
Docstring Conventions PEP.
(This is a simplified version of PEP 224 [2] by Marc-Andre Lemberg.)
A string literal immediately following an assignment statement is
interpreted by the docstring extration machinery as the docstring of
the target of the assignment statement, under the following conditions:
1. The assignment must be in one of the following contexts:
a) At the top level of a module (i.e., not inside a loop or
conditional): a module attribute.
b) At the top level of a class definition: a class attribute.
c) At the top level of a class' '__init__' method definition: an
instance attribute.
Since each of the above contexts are at the top level (i.e., just
inside the outermost suite of a definition), it may be necessary to
place dummy assignments for attributes assigned conditionally or in
a loop. Blank lines may be used after attribute docstrings to
emphasize the connection between the assignment and the docstring.
2. The assignment must be to a single target, not to a list or a tuple
of targets.
3. The form of the target:
a) For contexts 1a and 1b above, the target must be a simple
identifier (not a dotted identifier, a subscripted expression, or
a sliced expression).
b) For context 1c above, the target must be of the form
'self.attrib', where 'self' matches the '__init__' method's first
parameter (the instance parameter) and 'attrib' is a simple
indentifier as in 3a.
Examples::
g = 'module attribute (global variable)'
"""This is g's docstring."""
class AClass:
c = 'class attribute'
"""This is AClass.c's docstring."""
def __init__(self):
self.i = 'instance attribute'
"""This is self.i's docstring."""
Additional Docstrings
---------------------
XXX A description of additional docstrings would be appropriate in the
Docstring Conventions PEP.
Many programmers would like to make extensive use of docstrings for API
documentation. However, docstrings do take up space in the running
program, so some of these programmers are reluctant to 'bloat up' their
code. Also, not all API documentation is applicable to interactive
environments, where __doc__ would be displayed.
The docstring processing system's extraction tools will concatenate all
string literal expressions which appear at the beginning of a
definition or after a simple assignment. Only the first strings in
definitions will be available as __doc__, and can be used for brief
usage text suitable for interactive sessions; subsequent string
literals and all attribute docstrings are ignored by the Python
bytecode compiler and may contain more extensive API information.
Example::
def function(arg):
"""This is __doc__, function's docstring."""
"""
This is an additional docstring, ignored by the bytecode
compiler, but extracted by the docstring processing system.
"""
pass
Issue: This breaks 'from __future__ import' statements in Python 2.1 for
multiple module docstrings. Resolution?
1. Should we search for docstrings after a __future__ statement? Very
ugly.
2. Redefine __future__ statements to allow multiple preceeding string
literals?
3. Or should we not even worry about this? There shouldn't be
__future__ statements in production code, after all. Modules with
__future__ statements will have to put up with the single-docstring
limitation.
Choice of Docstring Format
==========================
Rather than force everyone to use a single docstring format, multiple
input formats are allowed by the processing system. A special variable,
__docformat__, may appear at the top level of a module before any
function or class definitions. Over time or through decree, a standard
format or set of formats should emerge.
The __docformat__ variable is a string containing the name of the
format being used, a case-insensitive string matching the input
parser's module or package name (i.e., the same name as required to
'import' the module or package), or a registered alias. If no
__docformat__ is specified, the default format is 'plaintext' for now;
this may be changed to the standard format once determined.
The __docformat__ string may contain an optional second field,
separated from the format name (first field) by a single space: a
case-insensitive language identifier as defined in RFC 1766 [3]. A
typical language identifier consists of a 2-letter language code from
ISO 639 [4] (3-letter codes used only if no 2-letter code exists; RFC
1766 is currently being revised to allow 3-letter codes). If no
language identifier is specified, the default is 'en' for English. The
language identifier is passed to the parser and can be used for
language-dependent markup features.
DPS Structure
=============
- package 'dps'
- function 'dps.main()' (in 'dps/__init__.py')
- package 'dps.parsers'
- module 'dps.parsers.model'; see 'Input Parser API' below.
- package 'dps.formatters'
- module 'dps.formatters.model'; see 'Output Formatter API' below.
- package 'dps.languages'
- module 'dps.languages.en' (English)
- others to be added
- utility modules: 'dps.statemachine'
Command-Line Interface
======================
XXX To be determined.
System Python API
=================
XXX To be determined.
Input Parser API
================
Each input parser is a module or package exporting a 'Parser' class,
with the following interface:
class Parser:
def __init__(self, inputstring, errors='warn', language='en'):
"""Initialize the Parser instance."""
def parse(self):
"""Return a DOM tree, the parsed input string."""
XXX This needs a lot of work. What is required for this API?
A model 'Parser' class implementing the full interface along with
utility functions can be found in the 'dps.parsers.model' module.
Output Formatter API
====================
Each output formatter is a module or package exporting a 'Formatter'
class, with the following interface:
class Formatter:
def __init__(self, domtree, language='en', showwarnings=0):
"""Initialize the Formatter instance."""
def format(self):
"""
Return a formatted string representation of the DOM tree.
"""
XXX This also needs a lot of work. What is required for this API?
A model 'Formatter' class implementing the full interface along with
utility functions can be found in the 'dps.formatters.model' module.
Language Module API
===================
Language modules will contain language-dependent strings and mappings.
They will be named for their language identifier (as defined in 'Choice
of Docstring Format' above), converting dashes to underscores.
XXX Specifics to be determined.
Intermediate Data Structure
===========================
A single intermediate data structure is used internally by the
docstring processing system. This data structure is a DOM tree whose
schema is documented in an XML DTD (eXtensible Markup Language Document
Type Definition), which comes in three parts:
- the Python Plaintext Document Interface DTD, ppdi.dtd [5],
- the Generic Plaintext Document Interface DTD, gpdi.dtd [6],
- and the OASIS Exchange Table Model, soextbl.dtd [7].
The DTD defines a rich set of elements, suitable for any input syntax
or output format. The input parser and the output formatter share the
same intermediate data structure. The processing system may do
transformations on the data from the input parser before passing it on
to the output formatter. The DTD retains all information necessary to
reconstruct the original input text, or a reasonable facsimile thereof.
XXX Specifics (about the DOM tree) to be determined.
Output Management
=================
XXX To be determined.
Type of output: filesystem only, or in-memory data structure too?
File/directory naming & structure conventions. In-memory data structure
should follow filesystem naming; file/directory == leaf/node. Use a
directory hierarchy rather than long file names (long file names were
one of the reasons pythondoc couldn't run on MacOS).
References and Footnotes
[1] http://www.python.org/sigs/doc-sig/
[2] http://python.sf.net/peps/pep-0224.html
[3] http://www.rfc-editor.org/rfc/rfc1766.txt
[4] http://lcweb.loc.gov/standards/iso639-2/englangn.html
[5] http://docstring.sf.net/spec/ppdi.dtd
[6] http://docstring.sf.net/spec/ppdi.dtd
[7] http://docstring.sf.net/spec/soextblx.dtd
Local Variables:
mode: indented-text
indent-tabs-mode: nil
End: