Skip to content

4.1.2: autodoc for classes with _name property is broken #9521

@mathiasertl

Description

@mathiasertl

Describe the bug

In #9490, or more precisely 68fb548, Sphinx started preferring cls._name over cls.__qualname__. This breaks autodoc for classes that define a _name property for other purposes. I don't know of any PEPs or similar (but I might be wrong?) that define _name as something special, so implementing classes can use it to be anything.

A concrete example is cryptography.x509.ObjectIdentifier, which defines a property called _name. At a minimal level, generating autodoc documentation for this class will trigger the error:

from cryptography import x509

class Demo(x509.ObjectIdentifier):
    """Docstring"""

(note: I use this workaround to work around non-canonical name issues, partly(?) fixed in #4826).

Generating autodoc documentation for this class will yield the following warning:

...:docstring of path.to.Demo:1:py:obj reference target not found: property object at 0x...

Reverting the switch in the aforementioned commit makes the warning go away. A possible refinement would be to check if _name is a string, e.g.:

diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py
index fd5735c57..81f110bff 100644
--- a/sphinx/util/typing.py
+++ b/sphinx/util/typing.py
@@ -174,7 +174,7 @@ def _restify_py37(cls: Optional[Type]) -> str:
             text += r"\ [%s]" % ", ".join(restify(a) for a in cls.__args__)
 
         return text
-    elif hasattr(cls, '_name'):
+    elif hasattr(cls, '_name') and isinstance(cls._name, str):
         # SpecialForm
         if cls.__module__ == 'typing':
             return ':obj:`~%s.%s`' % (cls.__module__, cls._name)

How to Reproduce

My project defines a more complex class, but I have verified this with the simple class defined above as well (I assume you know how to use a virtualenv ;-)). In this example, I clone my repo, build with Sphinx==4.1.1 (which works) and then update to Sphinx==4.1.2, which no longer works:

$ git clone https://github.com/mathiasertl/django-ca.git
$ cd django-ca
$ git checkout e8e93c358304b5f9cfa235ff7743e824994c32aa
$ pip install -r requirements.txt -r requirements/requirements-docs.txt
$ make -C docs html
... ok
$ pip install Sphinx==4.1.2
$ make -C docs html
...
Warning, treated as error:
/home/mertl/git/mati/test/django-ca/ca/django_ca/extensions/extensions.py:docstring of django_ca.extensions.extensions.ExtendedKeyUsage:1:py:obj reference target not found: property object at 0x7ff7717a1db0

If you change ExtendedKeyUsage in ca/django_ca/extensions/extensions.py to use any other class instead of x509.ObjectIdentifier, it will also work with 4.1.2. If you instead invert the "elif" order back to the state before 68fb548, it will also start working again.

Expected behavior

Sphinx should still build the documentation, obviously. Either the order should be reversed again, or it should be checked if cls._name is a str.

If you agree to either of the proposed solutions, I would volunteer for a PR.

Your project

https://github.com/mathiasertl/django-ca/

Screenshots

No response

OS

Ubuntu

Python version

tested with 3.8, 3.9

Sphinx version

4.1.2

Sphinx extensions

sphinx.ext.autodoc, celery.contrib.sphinx, numpydoc (but likely not relevant)

Extra tools

No response

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions