tox-dev / sphinx-autodoc-typehints

Type hints support for the Sphinx autodoc extension
MIT License
548 stars 104 forks source link

Tuple[] internals changes in Python 3.6 #11

Closed miohtama closed 7 years ago

miohtama commented 7 years ago

Python 3.6 TupleMeta no longer has __tuple_args__. Hitting a Tuple annotation when running sphinx-build causes exception.

Instead one can extra arguments from Tuple like:

def format_annotation(annotation):
    if inspect.isclass(annotation):
        if annotation.__module__ == 'builtins':
            if annotation.__qualname__ == 'NoneType':
                return '``None``'
            else:
                return ':class:`{}`'.format(annotation.__qualname__)

        extra = ''
        if annotation.__module__ in ('typing', 'backports.typing'):
            if annotation.__qualname__ == 'Union':
                params = annotation.__union_params__
                if len(params) == 2 and params[1].__qualname__ == 'NoneType':
                    annotation = Optional
                    params = (params[0],)
            elif annotation.__qualname__ == 'Tuple':

                if hasattr(annotation, "__tuple_params__"):
                    # Python 3.5
                    params = annotation.__tuple_params__
                    if annotation.__tuple_use_ellipsis__:
                        params += ('...',)
                else:
                    # Python 3.6
                    params = getattr(annotation, "__args__", None)
                    # TODO: Handle ellipsis

            else:
                params = getattr(annotation, '__parameters__', None)

            if params:
                extra = '\\[' + ', '.join(format_annotation(param) for param in params) + ']'

        return ':class:`~{}.{}`{}'.format(annotation.__module__, annotation.__qualname__, extra)

    return str(annotation)

However, I did not yet figure out how to handle the ellipsis case, as internals of typing.py are pretty mindblowing.

wheerd commented 7 years ago

The same goes for Union: It now basically inherits from Generic and has an __args__ attribute.

gaborbernat commented 7 years ago

The whole function needs some rework for Python 3.6. Union is also no longer a class (see https://github.com/python/typing/issues/380). I've started creating unit test for the project on my fork. So that we can know what works and what not beyond trial and error.

agronholm commented 7 years ago

I know all this, and I've fixed the same problem in my other project, typeguard. I am in the process of fixing the code, assisted by the test suite written by @wheerd. But it will take some time because I've been swamped with my commercial work for a while. I'm hoping things will calm down in the coming couple weeks.

miohtama commented 7 years ago

Does anyone know if there are better reflection APIs coming to typing in the future versions of Python? @jukkal?

JukkaL commented 7 years ago

@miohtama It seems likely that reflection is going to improve. For example, have a look at https://github.com/python/typing/pull/377.

agronholm commented 7 years ago

Should be fixed by 712d432ecd74ec2fa15faa52f0b435ca8f8061db.