[Python-Dev] pydoc for named tuples is missing methods (original) (raw)

Tim Lesher tlesher at gmail.com
Tue Mar 15 14:42:38 CET 2011


On Mon, Mar 14, 2011 at 08:28, Tim Lesher <tlesher at gmail.com> wrote:

On Mon, Mar 14, 2011 at 05:45, Nick Coghlan <ncoghlan at gmail.com> wrote:

There are two relatively simple ways forward I can see:

A. Add a public attribute that pydoc (and import *) understand. This would overrride the default "this is private" detection and add affected names to the public list (without needing to respecify all the "default public" names - this is important in order to support subclassing correctly) I believe this was the direction the bug report was implying. I'll be sprinting for a few hours this morning; if there are no objections, I will try to turn this idea into a patch that makes pydoc.visiblename look for a public function attribute as "step 0". Maybe there should also be a @public decorator to apply it, although that name may be an attractive nuisance, tempting C++ or Java programmers new to Python to ask for @protected and @private...

I implemented this on Monday, and it worked great... for instance methods. Unfortunately, it doesn't do a thing for classmethods or data attributes, which are 2/4 of the original namedtuple use cases, so it feels like a bad idea.

In the process of implementing it, though, I realized that the all mechanism for modules could still be reused. Two implementations came to mind:

  1. Allow an all class attribute that affects pydoc for classes the same way it does for modules. Pro: it's familiar, easy to explain, and easy to implement (four lines of code) Con: the original use case (adding a small number of otherwise-excluded attributes to existing documentation) is cumbersome. Because all means "don't document anything but special_names and the contents of all, you'd have to manually add names that pydoc would normally pick up. Also, all itself will show up in the documentation, which seems to me like useless clutter to a reader of help().

  2. Add a new class attribute that uses the same mechanism, with a different name (e.g., api). Pro: fairly easy to explain; because it doesn't share a name with all its semantics can be tweaked without confusing people. Con: slight additional cognitive burden of a new feature

I'm implementing both of these separately this week to see which works better in practice. So far I'm liking api better, with these semantics:

  1. Classes without api are treated just as they are today.
  2. api on classes works just like all on modules (only special names, plus its contents are documented)
  3. Additionally, api can take an Ellipsis. That makes the api list additive--pydoc documents everything it normally would, plus the contents of api
  4. api is added to pydoc's "hidden names" list; since its only purpose is to help generate docs, its value would be of little use in the generated docs themselves.

Point 3 (Ellipsis) is unusual, but to me it makes the declaration read well and solves the namedtuple case succinctly and compatibly, without changing a published API. It also could be used to address the issue of stdlib classes that have non-underscored members that really shouldn't be considered part of the "public" API, but can't be renamed now for fear of breaking code.

Usage example:

class C1: api = ['meth1', '_data2'] # read as "The API consists of meth1 and _data2." def init(self): """documented because it's a special name""" def meth1(self): """documented because it's in api""" def meth2(self): """Shouldn't really have been exposed, but it was released that way, and we don't want to break users' code. NOT documented because it's not in api """ def _meth3(self): """NOT documented because it's not in api""" data1 = None # not documented--not in api _data2 = None # documented--it's in api

class C2: api = ['_data2', ...] # read as "The API includes _data2." def init(self): """This is documented because it's a special name""" def meth1(self): """documented because it follows the normal rules""" def meth2(self): """documented because it follows the normal rules""" def _meth3(self): """NOT documented because it's not in api and starts with underscore""" data1 = # documented because it follows the normal rules _data2 = None # documented--it's in api

Comments and criticisms welcome.

-- Tim Lesher <tlesher at gmail.com>



More information about the Python-Dev mailing list