Here's something you can't do with Python 2



I recently found myself a passion for code documentation through Sphinx-style docstrings and I've just published a small library to help with redundant typing that I find annoying: argument types specification through :type: and :rtype:. Well, it's not so much that it's redundant rather than inelegant:

def myfunc(foo, bar):
    """Do some awesome stuff.

    :param foo: Bring in some foo.
    :type foo: :class:`FooClass`.
    :param bar: Do the bar dance.
    :type bar: :class:`BarClass`.
    :rtype: ``str``
    """

Being a Python 3 early adopter, I've been having access to the new annotation feature for a while now, so why not use it and do something like this:

def myfunc(foo: FooClass, bar: BarClass) -> str:
    """Do some awesome stuff.

    :param foo: Bring in some foo.
    :param bar: Do the bar dance.
    """

That would be great, wouldn't it? It's now possible with sphinx-autodoc-annotation! After having installed and enabled the library, you can skip the :type: and :rtype: directives and let sphinx interpret your annotations.

Update 05-01-2014

After having tried to use my new extension on my own projects, I don't think I'll use it after all.

First, the annotation syntax in some situations (when default values are involved), is quite inelegant. Let's use this example:

def format_amount(amount, currency=None, someflag=False):

If we add annotations, we almost automatically have to turn into one argument per line, or else we end up with:

def format_amount(amount: Amount, currency: Currency = None, someflag=False):

We don't see who's an argument and who's an annotation anymore. Note also that we've introduced an ambiguity with the old idiomatic "no space in between '=' char in default values defs". We can go like this:

def format_amount(
    amount: Amount,
    currency: Currency = None,
    someflag = False):

This isn't as bad as the previous one, but we still have lost some elegance in the process.

Second, there's the circular reference problem. For type annotations to work, we need a reference to our type when the Python code is evaluated. My experimentations showed that in many, many cases, we end up with circular reference problems, preventing us from importing our needed types forcing us to fallback to the old :type:.

So instead, inspired by Grzegorz's comments below, I'm going with inline typedefs. The problem is that the usual . and ~ prefix tricks that you can use with :class: aren't available in inline typedefs. So yesterday, I've worked on a patch to fix that and submitted a pull request.


This site is best viewed with Firefox while listening to The White Stripes