[Tutor] Central Python Library / Viewing __doc__ strings

Patrick K. O'Brien pobrien@orbtech.com
Sun, 10 Jun 2001 12:41:01 -0500


First, the short answer. It's all in the inspect module:

>>> import inspect
>>> inspect.getargspec(t)
(['x', 'y', 's', 'll', 'm', 'f', 'n'], None, None, (None, 2))

That gets you part of the way. Then you need to do some formatting:

>>> inspect.formatargspec(inspect.getargspec(t))
'((x, y, s, ll, m, f, n), None, None, (None, 2))'

Then you'll need to spend a few hours dissecting the inspect module to
figure out everything that goes on to get the arguments and produce the
final formatting that help(t) shows. (Because I'm too tired to do it myself
and I'm already in trouble with the wife for spending all morning on this.
<grin>)

Now for the long(er) answer. Here is the relevant method from pydoc.py. It
is part of the Helper class defined in pydoc:

    def help(self, request):
        if type(request) is type(''):
            if request == 'help': self.intro()
            elif request == 'keywords': self.listkeywords()
            elif request == 'topics': self.listtopics()
            elif request == 'modules': self.listmodules()
            elif request[:8] == 'modules ':
                self.listmodules(split(request)[1])
            elif self.keywords.has_key(request): self.showtopic(request)
            elif self.topics.has_key(request): self.showtopic(request)
            elif request: doc(request, 'Help on %s:')
        elif isinstance(request, Helper): self()
        else: doc(request, 'Help on %s:')
        self.output.write('\n')


So calling help on an object results in a call to doc(object, 'Help on
%s:'). Doc() is a function that looks like:

def doc(thing, title='Python Library Documentation: %s', forceload=0):
    """Display text documentation, given an object or a path to an
object."""
    suffix, name = '', None
    if type(thing) is type(''):
        try:
            object = locate(thing, forceload)
        except ErrorDuringImport, value:
            print value
            return
        if not object:
            print 'no Python documentation found for %s' % repr(thing)
            return
        parts = split(thing, '.')
        if len(parts) > 1: suffix = ' in ' + join(parts[:-1], '.')
        name = parts[-1]
        thing = object

    desc = describe(thing)
    module = inspect.getmodule(thing)
    if not suffix and module and module is not thing:
        suffix = ' in module ' + module.__name__
    pager(title % (desc + suffix) + '\n\n' + text.document(thing, name))


The last bit of code - text.document(thing, name) - is what we need to
explore. Doc() gets documentation on the thing with the document() method of
the TextDoc class (which is a child of the Doc class and the document method
is actually defined in the Doc class, not in TextDoc):

class Doc:
    def document(self, object, name=None, *args):
        """Generate documentation for an object."""
        args = (object, name) + args
        if inspect.ismodule(object): return apply(self.docmodule, args)
        if inspect.isclass(object): return apply(self.docclass, args)
        if inspect.isroutine(object): return apply(self.docroutine, args)
        return apply(self.docother, args)


Since in your example t is a function (inspect.isroutine(t) will return 1,
or true), we need to look at self.docroutine:

class TextDoc(Doc):
... <snipped>
    def docroutine(self, object, name=None, mod=None, cl=None):
        """Produce text documentation for a function or method object."""
        realname = object.__name__
        name = name or realname
        note = ''
        skipdocs = 0
        if inspect.ismethod(object):
            imclass = object.im_class
            if cl:
                if imclass is not cl:
                    note = ' from ' + classname(imclass, mod)
                    skipdocs = 1
            else:
                if object.im_self:
                    note = ' method of %s instance' % classname(
                        object.im_self.__class__, mod)
                else:
                    note = ' unbound %s method' % classname(imclass,mod)
            object = object.im_func

        if name == realname:
            title = self.bold(realname)
        else:
            if (cl and cl.__dict__.has_key(realname) and
                cl.__dict__[realname] is object):
                skipdocs = 1
            title = self.bold(name) + ' = ' + realname
        if inspect.isbuiltin(object):
            argspec = '(...)'
        else:
            args, varargs, varkw, defaults = inspect.getargspec(object)
            argspec = inspect.formatargspec(
                args, varargs, varkw, defaults,
formatvalue=self.formatvalue)
            if realname == '<lambda>':
                title = 'lambda'
                argspec = argspec[1:-1] # remove parentheses
        decl = title + argspec + note

        if skipdocs:
            return decl + '\n'
        else:
            doc = getdoc(object) or ''
            return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')

Now, this is a lot of code to look at, but the answer to your question lies
with inspect.getargspec(object). If we run that bit of code on t we get the
following:

>>> inspect.getargspec(t)
(['x', 'y', 's', 'll', 'm', 'f', 'n'], None, None, (None, 2))
>>>

The rest of the code makes things a prettier.  Again, that analysis will be
left as an exercise for the reader. <wink>

Hope that answered your question.

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

-----Original Message-----
From: tutor-admin@python.org [mailto:tutor-admin@python.org]On Behalf Of
Allan Crooks
Sent: Sunday, June 10, 2001 9:29 AM
To: tutor@python.org
Subject: [Tutor] Central Python Library / Viewing __doc__ strings

<snip>

BTW, does anyone know how Pydoc retrieves the arg list for functions when
you use help?

e.g.

>>> def t(x,y,s,ll,m,f=None,n=2):
..   print x,y,s,ll,m,f,n

>>> pydoc.help(t)

Help on function t in module __main__:

t(x, y, s, ll, m, f=None, n=2)

<snip>

Thanks again,
Allan.


_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor