# Buggy code
def _restify_py37(cls: Optional["Type"]) -> str:
    """Convert python class to a reST reference."""
    from sphinx.util import inspect  # lazy loading

    if (
        inspect.isgenericalias(cls)
        and cls.__module__ == "typing"
        and cls.__origin__ is Union
    ):
        # Union
        if len(cls.__args__) > 1 and cls.__args__[-1] is NoneType:
            if len(cls.__args__) > 2:
                args = ", ".join(restify(a) for a in cls.__args__[:-1])
                return ":obj:`Optional`\\ [:obj:`Union`\\ [%s]]" % args
            else:
                return ":obj:`Optional`\\ [%s]" % restify(cls.__args__[0])
        else:
            args = ", ".join(restify(a) for a in cls.__args__)
            return ":obj:`Union`\\ [%s]" % args
    elif inspect.isgenericalias(cls):
        if getattr(cls, "_name", None):
            if cls.__module__ == "typing":
                text = ":class:`%s`" % cls._name
            else:
                text = ":class:`%s.%s`" % (cls.__module__, cls._name)
        else:
            text = restify(cls.__origin__)

        if not hasattr(cls, "__args__"):
            pass
        elif all(is_system_TypeVar(a) for a in cls.__args__):
            # Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT])
            pass
        elif cls.__module__ == "typing" and cls._name == "Callable":
            args = ", ".join(restify(a) for a in cls.__args__[:-1])
            text += r"\ [[%s], %s]" % (args, restify(cls.__args__[-1]))
        elif cls.__args__:
            text += r"\ [%s]" % ", ".join(restify(a) for a in cls.__args__)

        return text
    elif hasattr(cls, "__qualname__"):
        if cls.__module__ == "typing":
            return ":class:`%s`" % cls.__qualname__
        else:
            return ":class:`%s.%s`" % (cls.__module__, cls.__qualname__)
    elif hasattr(cls, "_name"):
        # SpecialForm
        if cls.__module__ == "typing":
            return ":obj:`%s`" % cls._name
        else:
            return ":obj:`%s.%s`" % (cls.__module__, cls._name)
    else:
        # not a class (ex. TypeVar)
        return ":obj:`%s.%s`" % (cls.__module__, cls.__name__)


# Traceback (AttributeError)
# Sphinx version: 3.4.0
# Python version: 3.8.5 (CPython)
# Docutils version: 0.16 release
# Jinja2 version: 2.11.2
# Last messages:
#   building [mo]: all of 0 po files
#   building [html]: all source files
#   updating environment:
#   [new config]
#   11 added, 0 changed, 0 removed
#   reading sources... [  9%] blueprints
#   reading sources... [ 18%] changelog
#   reading sources... [ 27%] client_generation
#   reading sources... [ 36%] customization
#   reading sources... [ 45%] drf_spectacular
# Loaded extensions:
#   sphinx.ext.mathjax (3.4.0) from PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/mathjax.py
#   sphinxcontrib.applehelp (1.0.2) from PATH/.tox/docs/lib/python3.8/site-packages/sphinxcontrib/applehelp/__init__.py
#   sphinxcontrib.devhelp (1.0.2) from PATH/.tox/docs/lib/python3.8/site-packages/sphinxcontrib/devhelp/__init__.py
#   sphinxcontrib.htmlhelp (1.0.3) from PATH/.tox/docs/lib/python3.8/site-packages/sphinxcontrib/htmlhelp/__init__.py
#   sphinxcontrib.serializinghtml (1.1.4) from PATH/.tox/docs/lib/python3.8/site-packages/sphinxcontrib/serializinghtml/__init__.py
#   sphinxcontrib.qthelp (1.0.3) from PATH/.tox/docs/lib/python3.8/site-packages/sphinxcontrib/qthelp/__init__.py
#   alabaster (0.7.12) from PATH/.tox/docs/lib/python3.8/site-packages/alabaster/__init__.py
#   sphinx.ext.autodoc.type_comment (3.4.0) from PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/type_comment.py
#   sphinx.ext.autodoc (3.4.0) from PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py
Traceback (most recent call last):
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/cmd/build.py", line 280, in build_main
app.build(args.force_all, filenames)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/application.py", line 346, in build
self.builder.build_all()
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 259, in build_all
self.build(None, summary=__('all source files'), method='all')
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 310, in build
updated_docnames = set(self.read())
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 417, in read
self._read_serial(docnames)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 438, in _read_serial
self.read_doc(docname)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 478, in read_doc
doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/io.py", line 221, in read_doc
pub.publish()
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/core.py", line 217, in publish
self.document = self.reader.read(self.source, self.parser,
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/io.py", line 126, in read
self.parse()
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/readers/__init__.py", line 77, in parse
self.parser.parse(self.input, document)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/parsers.py", line 104, in parse
self.statemachine.run(inputlines, document, inliner=self.inliner)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 170, in run
results = StateMachineWS.run(self, input_lines, input_offset,
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
self.section(title, source, style, lineno - 1, messages)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 327, in section
self.new_subsection(title, lineno, messages)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
newabsoffset = self.nested_parse(
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
state_machine.run(block, input_offset, memo=self.memo,
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 196, in run
results = StateMachineWS.run(self, input_lines, input_offset)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
self.section(title, source, style, lineno - 1, messages)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 327, in section
self.new_subsection(title, lineno, messages)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
newabsoffset = self.nested_parse(
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
state_machine.run(block, input_offset, memo=self.memo,
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 196, in run
results = StateMachineWS.run(self, input_lines, input_offset)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
nodelist, blank_finish = self.explicit_construct(match)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
return method(self, expmatch)
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2096, in directive
return self.run_directive(
File "PATH/.tox/docs/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
result = directive_instance.run()
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/directive.py", line 146, in run
documenter.generate(more_content=self.content)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 957, in generate
self.document_members(all_members)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 838, in document_members
documenter.generate(
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 1679, in generate
return super().generate(more_content=more_content,
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 947, in generate
self.add_directive_header(sig)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 1579, in add_directive_header
bases = [restify(cls) for cls in self.object.__orig_bases__]
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 1579, in <listcomp>
bases = [restify(cls) for cls in self.object.__orig_bases__]
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/util/typing.py", line 103, in restify
return _restify_py37(cls)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/util/typing.py", line 142, in _restify_py37
text += r"\ [%s]" % ", ".join(restify(a) for a in cls.__args__)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/util/typing.py", line 142, in <genexpr>
text += r"\ [%s]" % ", ".join(restify(a) for a in cls.__args__)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/util/typing.py", line 103, in restify
return _restify_py37(cls)
File "PATH/.tox/docs/lib/python3.8/site-packages/sphinx/util/typing.py", line 158, in _restify_py37
return ':obj:`%s.%s`' % (cls.__module__, cls.__name__)
AttributeError: 'ForwardRef' object has no attribute '__name__'

# Fixed code
def _restify_py37(cls: Optional["Type"]) -> str:
    """Convert python class to a reST reference."""
    from sphinx.util import inspect  # lazy loading

    if (
        inspect.isgenericalias(cls)
        and cls.__module__ == "typing"
        and cls.__origin__ is Union
    ):
        # Union
        if len(cls.__args__) > 1 and cls.__args__[-1] is NoneType:
            if len(cls.__args__) > 2:
                args = ", ".join(restify(a) for a in cls.__args__[:-1])
                return ":obj:`Optional`\\ [:obj:`Union`\\ [%s]]" % args
            else:
                return ":obj:`Optional`\\ [%s]" % restify(cls.__args__[0])
        else:
            args = ", ".join(restify(a) for a in cls.__args__)
            return ":obj:`Union`\\ [%s]" % args
    elif inspect.isgenericalias(cls):
        if getattr(cls, "_name", None):
            if cls.__module__ == "typing":
                text = ":class:`%s`" % cls._name
            else:
                text = ":class:`%s.%s`" % (cls.__module__, cls._name)
        else:
            text = restify(cls.__origin__)

        if not hasattr(cls, "__args__"):
            pass
        elif all(is_system_TypeVar(a) for a in cls.__args__):
            # Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT])
            pass
        elif cls.__module__ == "typing" and cls._name == "Callable":
            args = ", ".join(restify(a) for a in cls.__args__[:-1])
            text += r"\ [[%s], %s]" % (args, restify(cls.__args__[-1]))
        elif cls.__args__:
            text += r"\ [%s]" % ", ".join(restify(a) for a in cls.__args__)

        return text
    elif hasattr(cls, "__qualname__"):
        if cls.__module__ == "typing":
            return ":class:`%s`" % cls.__qualname__
        else:
            return ":class:`%s.%s`" % (cls.__module__, cls.__qualname__)
    elif hasattr(cls, "_name"):
        # SpecialForm
        if cls.__module__ == "typing":
            return ":obj:`%s`" % cls._name
        else:
            return ":obj:`%s.%s`" % (cls.__module__, cls._name)
    elif isinstance(cls, ForwardRef):
        return ":class:`%s`" % cls.__forward_arg__
    else:
        # not a class (ex. TypeVar)
        return ":obj:`%s.%s`" % (cls.__module__, cls.__name__)