Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception in util/typing.py for empty tuple type: Tuple[()] #9362

Closed
triebelf opened this issue Jun 18, 2021 · 4 comments
Closed

Exception in util/typing.py for empty tuple type: Tuple[()] #9362

triebelf opened this issue Jun 18, 2021 · 4 comments

Comments

@triebelf
Copy link

triebelf commented Jun 18, 2021

Describe the bug
Exception occurs in util/typing.py, when I generate documentation with Sphinx autodoc extension. This seems to be caused by Python type hint Tuple[()], that is the type of empty tuple ():

Exception occurred:
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/util/typing.py", line 116, in restify
    elif cls.__module__ in ('__builtin__', 'builtins'):
AttributeError: 'tuple' object has no attribute '__module__'

This behaviour started with Sphinx 3.4, whereas it worked as expected in Sphinx 3.3.

To Reproduce

  • create some source file to be documented with autodoc extension
  • add Python type hint
  • run sphinx-build
  • observe full trace
# Sphinx version: 3.5.4
# Python version: 3.6.9 (CPython)
# Docutils version: 0.16 release
# Jinja2 version: 2.11.3
# Last messages:
#   building [html]: targets for 5 source files that are out of date
#   
#   updating environment:
#   
#   [new config]
#   
#   5 added, 0 changed, 0 removed
#   
#   reading sources... [ 20%] dol_launcher
#   
# Loaded extensions:
#   sphinx.ext.mathjax (3.5.4) from /home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/mathjax.py
#   sphinxcontrib.applehelp (1.0.2) from /home/ftr8fe/.local/lib/python3.6/site-packages/sphinxcontrib/applehelp/__init__.py
#   sphinxcontrib.devhelp (1.0.2) from /home/ftr8fe/.local/lib/python3.6/site-packages/sphinxcontrib/devhelp/__init__.py
#   sphinxcontrib.htmlhelp (2.0.0) from /home/ftr8fe/.local/lib/python3.6/site-packages/sphinxcontrib/htmlhelp/__init__.py
#   sphinxcontrib.serializinghtml (1.1.5) from /home/ftr8fe/.local/lib/python3.6/site-packages/sphinxcontrib/serializinghtml/__init__.py
#   sphinxcontrib.qthelp (1.0.3) from /home/ftr8fe/.local/lib/python3.6/site-packages/sphinxcontrib/qthelp/__init__.py
#   alabaster (0.7.12) from /home/ftr8fe/.local/lib/python3.6/site-packages/alabaster/__init__.py
#   sphinx.ext.autodoc.type_comment (3.5.4) from /home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/type_comment.py
#   sphinx.ext.autodoc (3.5.4) from /home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py
Traceback (most recent call last):
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/cmd/build.py", line 280, in build_main
    app.build(args.force_all, filenames)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/application.py", line 352, in build
    self.builder.build_update()
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 298, in build_update
    len(to_build))
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 310, in build
    updated_docnames = set(self.read())
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 417, in read
    self._read_serial(docnames)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 438, in _read_serial
    self.read_doc(docname)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 478, in read_doc
    doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/io.py", line 221, in read_doc
    pub.publish()
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/core.py", line 218, in publish
    self.settings)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/io.py", line 126, in read
    self.parse()
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/readers/__init__.py", line 77, in parse
    self.parser.parse(self.input, document)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/parsers.py", line 104, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 171, in run
    input_source=document['source'])
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/statemachine.py", line 242, in run
    context, state, transitions)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/statemachine.py", line 459, in check_line
    return method(match, context, next_state)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/statemachine.py", line 242, in run
    context, state, transitions)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/statemachine.py", line 459, in check_line
    return method(match, context, next_state)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/statemachine.py", line 242, in run
    context, state, transitions)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/statemachine.py", line 459, in check_line
    return method(match, context, next_state)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2097, in directive
    directive_class, match, type_name, option_presets)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/directive.py", line 167, in run
    documenter.generate(more_content=self.content)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 970, in generate
    self.document_members(all_members)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 853, in document_members
    check_module=members_check_module and not isattr)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 1728, in generate
    all_members=all_members)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 960, in generate
    self.add_directive_header(sig)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 1626, in add_directive_header
    bases = [restify(cls) for cls in self.object.__orig_bases__]
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/ext/autodoc/__init__.py", line 1626, in <listcomp>
    bases = [restify(cls) for cls in self.object.__orig_bases__]
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/util/typing.py", line 122, in restify
    return _restify_py36(cls)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/util/typing.py", line 215, in _restify_py36
    args = ', '.join(restify(arg) for arg in cls.__args__[:-1])  # type: ignore
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/util/typing.py", line 215, in <genexpr>
    args = ', '.join(restify(arg) for arg in cls.__args__[:-1])  # type: ignore
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/util/typing.py", line 122, in restify
    return _restify_py36(cls)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/util/typing.py", line 202, in _restify_py36
    param_str = ', '.join(restify(p) for p in params)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/util/typing.py", line 202, in <genexpr>
    param_str = ', '.join(restify(p) for p in params)
  File "/home/ftr8fe/.local/lib/python3.6/site-packages/sphinx/util/typing.py", line 116, in restify
    elif cls.__module__ in ('__builtin__', 'builtins'):
AttributeError: 'tuple' object has no attribute '__module__'

Expected behavior

  • sphinx-build completes without error

Your project

  • I cannot share anything because of company policy

Environment info

  • OS: Linux
  • Python version: 3.6, 3.8
  • Sphinx version: 3.5
  • Sphinx extensions: sphinx.ext.autodoc
@tk0miya
Copy link
Member

tk0miya commented Jun 20, 2021

I failed to reproduce the error. Could you make a minimal reproducible example, please?

@tk0miya
Copy link
Member

tk0miya commented Jun 20, 2021

Additionally, I'd like to know the meaning of Tuple[()]. This is the first time I've seen it.

@triebelf
Copy link
Author

triebelf commented Jun 21, 2021

Additionally, I'd like to know the meaning of Tuple[()]. This is the first time I've seen it.

Tuple[()] is the empty tuple type, that is the type of a tuple with no values: ()

I learned it from here

@triebelf
Copy link
Author

triebelf commented Jun 21, 2021

update 2021-06-21: I corrected a typo in the code.

I failed to reproduce the error. Could you make a minimal reproducible example, please?

I extracted this minimal example, that follows my use case:

#!/usr/bin/env python3

from abc import ABC, abstractmethod
from typing import Generic, Tuple, TypeVar

T = TypeVar("T", bound=Tuple[str, ...], contravariant=True)


class Base(ABC, Generic[T]):
    @abstractmethod
    def some_method(self, t: T) -> None:
        pass


class Inherited(Base[Tuple[()]]):
    def some_method(self, _: Tuple[()]) -> None:
        # empty parameter is not used
        pass


class Inherited2(Base[Tuple[str]]):
    def some_method(self, t: Tuple[str]) -> None:
        print(t)

@tk0miya tk0miya added this to the 4.1.0 milestone Jul 7, 2021
@tk0miya tk0miya closed this as completed in 007dee7 Jul 8, 2021
tk0miya added a commit that referenced this issue Jul 8, 2021
…s_of_empty_tuple

Fix #9362: autodoc: AttributeError is raised for a subclass of Tuple[()]
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants