# Buggy code
def _stringify_py37(annotation: Any) -> str:
    """stringify() for py37+."""
    module = getattr(annotation, "__module__", None)
    if module == "typing":
        if getattr(annotation, "_name", None):
            qualname = annotation._name
        elif getattr(annotation, "__qualname__", None):
            qualname = annotation.__qualname__
        elif getattr(annotation, "__forward_arg__", None):
            qualname = annotation.__forward_arg__
        else:
            qualname = stringify(annotation.__origin__)  # ex. Union
    elif hasattr(annotation, "__qualname__"):
        qualname = "%s.%s" % (module, annotation.__qualname__)
    elif hasattr(annotation, "__origin__"):
        # instantiated generic provided by a user
        qualname = stringify(annotation.__origin__)
    else:
        # we weren't able to extract the base type, appending arguments would
        # only make them appear twice
        return repr(annotation)

    if getattr(annotation, "__args__", None):
        if qualname == "Union":
            if len(annotation.__args__) > 1 and annotation.__args__[-1] is NoneType:
                if len(annotation.__args__) > 2:
                    args = ", ".join(stringify(a) for a in annotation.__args__[:-1])
                    return "Optional[Union[%s]]" % args
                else:
                    return "Optional[%s]" % stringify(annotation.__args__[0])
            else:
                args = ", ".join(stringify(a) for a in annotation.__args__)
                return "Union[%s]" % args
        elif qualname == "Callable":
            args = ", ".join(stringify(a) for a in annotation.__args__[:-1])
            returns = stringify(annotation.__args__[-1])
            return "%s[[%s], %s]" % (qualname, args, returns)
        elif str(annotation).startswith("typing.Annotated"):  # for py39+
            return stringify(annotation.__args__[0])
        elif all(is_system_TypeVar(a) for a in annotation.__args__):
            # Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT])
            return qualname
        else:
            args = ", ".join(stringify(a) for a in annotation.__args__)
            return "%s[%s]" % (qualname, args)

    return qualname


# Traceback (TypeError)
Sphinx version: 3.2.1
Python version: 3.8.5 (CPython)
Docutils version: 0.16 release
Jinja2 version: 2.11.2
Last messages:
Running Sphinx v3.2.1
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 22 source files that are out of date
updating environment:
[new config]
22 added, 0 changed, 0 removed
reading sources... [  4%] eopack
Loaded extensions:
sphinx.ext.mathjax (3.2.1) from PATH\venv\lib\site-packages\sphinx\ext\mathjax.py
sphinxcontrib.applehelp (1.0.2) from PATH\venv\lib\site-packages\sphinxcontrib\applehelp\__init__.py
sphinxcontrib.devhelp (1.0.2) from PATH\venv\lib\site-packages\sphinxcontrib\devhelp\__init__.py
sphinxcontrib.htmlhelp (1.0.3) from PATH\venv\lib\site-packages\sphinxcontrib\htmlhelp\__init__.py
sphinxcontrib.serializinghtml (1.1.4) from PATH\venv\lib\site-packages\sphinxcontrib\serializinghtml\__init__.py
sphinxcontrib.qthelp (1.0.3) from PATH\venv\lib\site-packages\sphinxcontrib\qthelp\__init__.py
alabaster (0.7.12) from PATH\venv\lib\site-packages\alabaster\__init__.py
sphinx.ext.autodoc.type_comment (3.2.1) from PATH\venv\lib\site-packages\sphinx\ext\autodoc\type_comment.py
sphinx.ext.autodoc (3.2.1) from PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py
sphinxcontrib.napoleon (0.7) from PATH\venv\lib\site-packages\sphinxcontrib\napoleon\__init__.py
Traceback (most recent call last):
File "PATH\venv\lib\site-packages\sphinx\cmd\build.py", line 280, in build_main
app.build(args.force_all, filenames)
File "PATH\venv\lib\site-packages\sphinx\application.py", line 348, in build
self.builder.build_update()
File "PATH\venv\lib\site-packages\sphinx\builders\__init__.py", line 297, in build_update
self.build(to_build,
File "PATH\venv\lib\site-packages\sphinx\builders\__init__.py", line 311, in build
updated_docnames = set(self.read())
File "PATH\venv\lib\site-packages\sphinx\builders\__init__.py", line 418, in read
self._read_serial(docnames)
File "PATH\venv\lib\site-packages\sphinx\builders\__init__.py", line 439, in _read_serial
self.read_doc(docname)
File "PATH\venv\lib\site-packages\sphinx\builders\__init__.py", line 479, in read_doc
doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
File "PATH\venv\lib\site-packages\sphinx\io.py", line 223, in read_doc
pub.publish()
File "PATH\venv\lib\site-packages\docutils\core.py", line 217, in publish
self.document = self.reader.read(self.source, self.parser,
File "PATH\venv\lib\site-packages\sphinx\io.py", line 128, in read
self.parse()
File "PATH\venv\lib\site-packages\docutils\readers\__init__.py", line 77, in parse
self.parser.parse(self.input, document)
File "PATH\venv\lib\site-packages\sphinx\parsers.py", line 102, in parse
self.statemachine.run(inputlines, document, inliner=self.inliner)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 170, in run
results = StateMachineWS.run(self, input_lines, input_offset,
File "PATH\venv\lib\site-packages\docutils\statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "PATH\venv\lib\site-packages\docutils\statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 2769, in underline
self.section(title, source, style, lineno - 1, messages)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 327, in section
self.new_subsection(title, lineno, messages)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 393, in new_subsection
newabsoffset = self.nested_parse(
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 281, in nested_parse
state_machine.run(block, input_offset, memo=self.memo,
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 196, in run
results = StateMachineWS.run(self, input_lines, input_offset)
File "PATH\venv\lib\site-packages\docutils\statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "PATH\venv\lib\site-packages\docutils\statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 2769, in underline
self.section(title, source, style, lineno - 1, messages)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 327, in section
self.new_subsection(title, lineno, messages)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 393, in new_subsection
newabsoffset = self.nested_parse(
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 281, in nested_parse
state_machine.run(block, input_offset, memo=self.memo,
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 196, in run
results = StateMachineWS.run(self, input_lines, input_offset)
File "PATH\venv\lib\site-packages\docutils\statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "PATH\venv\lib\site-packages\docutils\statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 2342, in explicit_markup
nodelist, blank_finish = self.explicit_construct(match)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 2354, in explicit_construct
return method(self, expmatch)
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 2096, in directive
return self.run_directive(
File "PATH\venv\lib\site-packages\docutils\parsers\rst\states.py", line 2146, in run_directive
result = directive_instance.run()
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\directive.py", line 146, in run
documenter.generate(more_content=self.content)
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 894, in generate
self.document_members(all_members)
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 775, in document_members
documenter.generate(
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 1568, in generate
return super().generate(more_content=more_content,
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 894, in generate
self.document_members(all_members)
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 1559, in document_members
super().document_members(all_members)
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 775, in document_members
documenter.generate(
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 884, in generate
self.add_directive_header(sig)
File "PATH\venv\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 2003, in add_directive_header
objrepr = stringify_typehint(annotations.get(self.objpath[-1]))
File "PATH\venv\lib\site-packages\sphinx\util\typing.py", line 80, in stringify
return _stringify_py37(annotation)
File "PATH\venv\lib\site-packages\sphinx\util\typing.py", line 116, in _stringify_py37
args = ', '.join(stringify(a) for a in annotation.__args__)
File "PATH\venv\lib\site-packages\sphinx\util\typing.py", line 116, in <genexpr>
args = ', '.join(stringify(a) for a in annotation.__args__)
File "PATH\venv\lib\site-packages\sphinx\util\typing.py", line 80, in stringify
return _stringify_py37(annotation)
File "PATH\venv\lib\site-packages\sphinx\util\typing.py", line 124, in _stringify_py37
elif all(is_system_TypeVar(a) for a in annotation.__args__):
TypeError: 'type' object is not iterable

# Fixed code
def _stringify_py37(annotation: Any) -> str:
    """stringify() for py37+."""
    module = getattr(annotation, "__module__", None)
    if module == "typing":
        if getattr(annotation, "_name", None):
            qualname = annotation._name
        elif getattr(annotation, "__qualname__", None):
            qualname = annotation.__qualname__
        elif getattr(annotation, "__forward_arg__", None):
            qualname = annotation.__forward_arg__
        else:
            qualname = stringify(annotation.__origin__)  # ex. Union
    elif hasattr(annotation, "__qualname__"):
        qualname = "%s.%s" % (module, annotation.__qualname__)
    elif hasattr(annotation, "__origin__"):
        # instantiated generic provided by a user
        qualname = stringify(annotation.__origin__)
    else:
        # we weren't able to extract the base type, appending arguments would
        # only make them appear twice
        return repr(annotation)

    if getattr(annotation, "__args__", None):
        if not isinstance(annotation.__args__, (list, tuple)):
            # broken __args__ found
            pass
        elif qualname == "Union":
            if len(annotation.__args__) > 1 and annotation.__args__[-1] is NoneType:
                if len(annotation.__args__) > 2:
                    args = ", ".join(stringify(a) for a in annotation.__args__[:-1])
                    return "Optional[Union[%s]]" % args
                else:
                    return "Optional[%s]" % stringify(annotation.__args__[0])
            else:
                args = ", ".join(stringify(a) for a in annotation.__args__)
                return "Union[%s]" % args
        elif qualname == "Callable":
            args = ", ".join(stringify(a) for a in annotation.__args__[:-1])
            returns = stringify(annotation.__args__[-1])
            return "%s[[%s], %s]" % (qualname, args, returns)
        elif str(annotation).startswith("typing.Annotated"):  # for py39+
            return stringify(annotation.__args__[0])
        elif all(is_system_TypeVar(a) for a in annotation.__args__):
            # Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT])
            return qualname
        else:
            args = ", ".join(stringify(a) for a in annotation.__args__)
            return "%s[%s]" % (qualname, args)

    return qualname