[Doc-SIG] A documentation idea.

Edward Welbourne Edward Welbourne <eddy@chaos.org.uk>
Tue, 31 Mar 1998 02:56:22 +0100 (BST)


Following earlier discussions about cross-reference [ notably
 <A href="http://www.python.org/pipermail/1998q1.doc-sig/b73971c17835.html">Status
of the documentation effort</A>
 <A href="http://www.python.org/pipermail/1998q1.doc-sig/faad164f31af.html">Information
content and readability</A>
and subsequent, in our lovely new archive pages ;^]

I've been thinking about what's possible and what seems like a good
idea.  The best way I can find to express this is as `what did I want'
followed by a sketch of how.  I hope they're useful ;^)

	Eddy

--
Here's the `what I want' part:

ways of indicating in the __doc__ which parts of a module (or class) I
want documented, in which order: gendoc can throw in other parts of the
module after the bits indicated by the __doc__, but IWBNI it could be
told not to

the means to let the __doc__ string refer to a variable in my namespace
as a component of what is to be generated as the doc - so that part of
the documentation of the module can appear further down the file than
the start, just before the portion of the module to which it relates (I
find docs get maintained better if they're next to the code they discuss ;^)

[modulo choice of punctuation] to write (see [pack.mod.what]) in a doc
string, at the end of which I indicate what [pack.mod.what] refers to:
and I want to give a text (word or phrase) with that which will be used
as the link-text off which the reference hangs: so the original becomes
(see <A href="somewhere/pack/mod/what.html#Begin">my choice of
words</A>) and, as is only proper for citations, the same choice of
words is used in each place I've referred to [pack.mod.what].

The reason why I want that last is so that my doc string, prosaically,
tells its reader (the code maintainer) what entity's documentation it is
referring to, while the pretty form of it gives it a helpful name and
makes it a hyperlink.  Don't force the code-author to make the doc
string's form of the x-ref be the actual name of a value in your
namespace, just make it a recommended practice - possibly supported by
some shorthands, such as allowing the bit where I say what pack.mod.what
x-refs are to just say `look it up in my namespace and work out where
you're documenting that'.

--
Here's a sketch of the best bits I can pilfer from the discussion as to
what the Xref form needs to be: illustrated by a putative file from
which nearly all the code is omitted.

"""A 'stat()'-wrapper Module.

Defines a private class used to wrap up the output of 'os.stat()' in a
convenient form, and a cacheing lookup function to obtain such data.
The objects returned support an 'uncache()' method which will tell this
module's export, [stat], to look the relevant file up afresh next time
it's asked for that file.

.. +[stat] local: the 'stat()' function
.. +[copyright] href \
	"http://tools.py.org/contrib/toolsets/oswrap/tools/copyright.html": \
	Copyleft, 1998, 2001, the python contibution project.
"""

import os, lazy
class _Stat(lazy.Lazy):
    """A wrapper class for 'stat' data.

    Emulates a sequence, just like the data returned by 'os.stat()' (see
    [os.stat]), but also allows you to read data such as 'self.ownerid',
    rather than needing to import the 'stat' class (see [stat]) and use
    its data as subscripts.

    Uses [Lazy] so that its namespace is only as populated as you've
    asked for: the value of 'self.ownerid' is computed the first time
    you access that attribute of an object 'self' and cached in the
    namespace of 'self'.

    .. + local name_space_doc: Available Namespace
    .. [Lazy] global lazy.Lazy: lazy evaluation
    .. [os.stat] global:
    """

    name_space_doc = """
    ownerid -- the user ID of the owner of this file
    owner -- an [User] describing this user
    groupid -- the ID of the group
    group -- an [Group] describing this group
    mode -- an [Mode] describing accessibility of the file

    .. [User] external tools.wrap.User: object
    .. [Group] external tools.wrap.Group: object
    .. [Mode] external tools.wrap.Mode: object
    """

    # definitions, including magic methods used by Lazy, some of which
    # (if and when it's needed) import tools.wrap and add it somewhere
    # out-of-the way in _Stat's namespace, for subsequent access to the
    # classes it exports.

def stat(file):
    """Namespace-decoded 'os.stat()'.

    Argument, 'file', is a filename, with the usual interpretation.
    Raises 'os.error' (see [Exception]) if there is no such file.
    Otherwise, returns an object which provides status information on
    the file: see [return], below.

    See also the related [tools.wrap].

    .. +[return] global _Stat: Return Type
    .. [tools.wrap] external: system wrapper toolset
    .. [Exception] builtin:
    """
--
So what have I used ?

Putting + just after the .. says: add the indicated thing to my doc.
This can have a [name] if the earlier parts of my doc want to refer to
it, but it needn't: if such a name is given, it'll be used as the name
of an anchor.

After the [] comes a word saying how to look up the reference: it's
followed by an expression that this lookup can decode, then a : and the
text to use for the anchor.

If the anchor text or the lookup-expression is omitted, it's the
contents of the [].  Styles of lookup are:

global, local, builtin -- indicates which of my namespaces I'd be using
to look up the reference: if no lookup-style is given, it'll be done
using the usual lookup order for python evaluation (possibly bending
slightly, as <A
 href="http://www.python.org/pipermail/1998q1.doc-sig/0b675dc5399b.html">suggested</A>
by David Ascher).

external -- you're going to have to import tools.wrap to find its docs:
though you'll probably have some idiom for telling gendoc to turn that
into some-root/tools/wrap.html#Begin, or similar.  This fills the need
to refer to something not actually accessible to my namespace: notably,
in a `see also' section, one may wish to refer to things based on the
present module, which won't usually be in its namespace !

href -- well, of course, we also need these.  Given that they can be
rather long, it's worth letting a .. entry be spread over many lines -
though this probably doesn't want to be done with \, rather by noticing
that the next line is more indented.

--
I'm presuming a reading of a string as its own `doc string'.
Just to be sure what I'm intending here, I'd want the resulting
doc to begin with the file's __doc__, under the heading "A
'stat()'-wrapper module".

That's followed by a subsection on the module's stat() function, under
the heading "Namespace-decoded 'os.stat()'.", with cross-references to
documentation of python's built-in exceptions and of a module called
tools.wrap.

This, in turn, has a subsubsection describing the type of stat()'s
return (without the user documentation ever using the name _Stat), under
the heading "Return Type".  That has a sub^3^section telling us how to
read the namespace of the object - and the string which does this might
be borrowed by other things needing to refer to the same - furthermore,
name_space_doc will show up in the namespace of each object returned by
stat(), so it's a self-documenting object ;^)

[A rather different use for a string like this is where it *isn't* a
variable of the class, it's a short essay in the namespace of the
module, to which the class doc refers rather than clutter up its body
unduly.]

Note that the module's documentation (when rendered to HTML) ends with

<A name="copyright"
 href="http://tools.py.org/contrib/toolsets/oswrap/tools/copyright.html">Copyleft, 
1998, 2001, the python contibution project.</A>

--
Details:

Because tools.wrap doesn't get imported until it's needed, if at all, it
isn't accessible to _Stat during a gendoc run (which won't be
instanciating the class, let alone prompting it to read its data): so it
has to talk about tools.wrap as external.

Note that I said

 group -- an [Group] ...

despite usual rules for a and an, because what it really says is `an
object ...', with a hyperlink to Group off `object'.