[Python-3000] Annotation classes (was: Questions on optional type annotations)

Collin Winter collinw at gmail.com
Sun May 14 08:30:23 CEST 2006


On 5/12/06, Nick Coghlan <ncoghlan at gmail.com> wrote:
> Both of these (return type annotation and selecting strict or lenient
> behaviour) can be done inline with the right methods on the annotation object.

[snip]

I've implemented this idea (a Function annotation, using Nick's
suggestion) in typecheck's SVN repository. Documentation [1] and a
tarball of the latest trunk revision [2] are available, and I'd like
feedback on the current design so I can start adding this idea to my
typechecking PEP.

The reception this idea has received (using utility classes to
provided enhanced typechecking) leads me to this question: what other
annotation classes should be provided? Would type unions and
intersections be best handled as utility classes (And, Or, Not, etc)
or as __and__ and __or__ on the type objects? Is it desirable that
users can write their own annotation classes that plug into the
typechecking system? If so, what hooks should be provided into the
system?

My typecheck library ships with a number of annotation classes (13 are
scheduled for inclusion in the upcoming 0.4 release; a sampling
follows) and provides several places where user-defined classes can
hook into the system:

1. Utility classes can hook into the @accepts, @returns and @yields
decorators (which define a callable's type signature) using a
__typesig__ classmethod. The system iterates over each item that makes
up the signature, asking if any annotation class knows how to handle
it (the first class to say "yes" wins). The annotation classes are
free to transform the object however they desire, though this normally
just involves handing the object off to the class's constructor.

2. Annotation classes almost always want to define a __typecheck__
instancemethod. When the typechecked callable is invoked,
__typecheck__ methods are where arguments and return values are
validated against annotation instances.

To signal displeasure with an object, __typecheck__ methods are free
to raise subclasses of the _TC_Exception class. These exceptions
bubble up the call stack, eventually resulting in highly detailed
error messages for the user. 19 such subclasses currently exist, and
users are free to define and raise their own exceptions (assuming they
subclass _TC_Exception and follow the API).

3. Three lesser-used hooks are __startchecking__, __switchchecking__
and __stopchecking__. For example, a function with @accepts applied
result in __startchecking__ and __stopchecking__ signals once the
system had finished checking all the function's arguments. (All
classes that define these hooks are notified at the same time.) A
function with @accepts and @returns would issue __startchecking__
signals when the system started checking the function's arguments and
__stopchecking__ once the function's return values had been validated.
__switchchecking__ exists to handle generators, where a function might
have both @accepts and @yields applied; once the function returns the
generator, the system stops checking the function and starts checking
the generator.

These hooks exist primarily to provide support for the type variables machinery.

To register an annotation class with the system, a
typecheck.register_type() function is provided. This will cause the
class's hook methods to be called at the proper times.

While this may seem like flexibility overkill, this design has made it
very easy to add new annotation classes. I started out with basic And,
Or, Not and Xor type operations and have since used this system to add
support for functions-as-typecheckers [3], ==-equality assertions
(Exact), interface specifiation (HasAttr), type variables [4],
callable()-ness, iterable-ness and typeclasses, among others. In
addition, this same mechanism is used to support Python's built-in
set, dict, list and tuple types. (To read about all of typecheck's
annotation classes, see [5].)

Is there interest in including a hook-based system like this in Python
2.x and 3.x's respective type annotation systems?

Thanks,
Collin Winter

[1] - http://oakwinter.com/code/typecheck/dev/utility/function.html
[2] - http://oakwinter.com/code/typecheck/dist/typecheck-svn-latest.tar.gz
[3] - http://oakwinter.com/code/typecheck/dev/tutorial/functions_as_types.html
[4] - http://oakwinter.com/code/typecheck/dev/tutorial/typevariables.html
[5] - http://oakwinter.com/code/typecheck/dev/utility/index.html


More information about the Python-3000 mailing list