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
:rtype:. Well, it's not so much that it's redundant rather than
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
:rtype: directives and let
sphinx interpret your annotations.
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
So instead, inspired by Grzegorz's comments below, I'm going with inline typedefs. The problem is
that the usual
~ 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.