[Python-3000] Conventions for annotation consumers (was: Re: Draft pre-PEP: function annotations)

Collin Winter collinw at gmail.com
Tue Aug 15 16:06:28 CEST 2006

On 8/14/06, Collin Winter <collinw at gmail.com> wrote:
> On 8/14/06, Jim Jewett <jimjjewett at gmail.com> wrote:
> > On 8/14/06, Collin Winter <collinw at gmail.com> wrote:
> > > The problem with using lists is that its impossible for non-decorator
> > > annotation consumers to know which element "belongs" to them.
> >
> > The ones whose type they own -- which is why I see at least some
> > parallel to exceptions, and its inheritance based semantics.
> >
> >     def f(a:[mytype("asdfljasdf"),
> >              zope.mypackage.something(b,d,e),
> >              "a string",
> >              mytype([47]),
> >              15):
> >
> > Whoever defined mytype controls the meaning of the mytype annotations;
> > anyone not familiar with that package should ignore them (and hope
> > there were no side effects in the expressions that generated them).
> >
> > zope.mypackage controls that annotation; anyone not familiar with that
> > product should ignore it (and hope there were no side effects ...)
> As hideous as I think this is from an aesthetics/visual noise
> standpoint, it's probably the only reliable way to let both decorator-
> and non-decorator-based consumers work.

I've changed my mind. This idea isn't going to work at all.

The sticking point is that while this might allow decorator and
non-decorator-based consumers to operate side-by-side *within a single
program*, it makes it impossible for things like pychecker or an
optimising compiler to take advantage of the annotations.

Here's another stab at my earlier idea:

Here's the modified example

def foo(a: {'doc': "Frobnication count",
           'type': Number,
           'constrain_values': range(3, 9)},
       b: {'type': Number,
            # This can be only 4, 8 or 12
           'constrain_values': [4, 8, 12]}) -> {'type': Number}

We're still using dicts to hold the annotations, but instead of having
the dict keyed on the name (function.__name__) of the annotation
consumer, the keys are arbitrary (for certain values of "arbitrary").
To enable both in-program and static analysis, the most prominent keys
will be specified by the PEP. In this example, "type" and "doc" are
reserved keys; anything that needs the intended type of an annotation
will look at the "type" key, anything that's looking for special doc
strings will look at the "doc" key. Any other consumers are free to
define whatever keys they want (e.g., "constrain_values", above), so
long as they stay away from the reserved strings.

The dict form will be required, even if there's only one type of
annotation. To modify the example above to only use typechecker(),

def foo(a: {'type': Number},
       b: {'type': Number}) -> {'type': Number}

I'm going to raise the bar for future ideas on this subject: any
proposals must be able to address the following use cases:

1) Static analysis tools (pychecker, optimising compilers, etc) must
be able to use the annotations
2) Decorator-based annotation consumers must be able to use the annotations
3) Non-decorator-based annotation consumers (pydoc, etc) must be able
to use the annotations

Proposals that do not address all of these will not be considered.

Collin Winter

More information about the Python-3000 mailing list