Skip to content

Docs from dataclass descriptor fields #11672

@nstarman

Description

@nstarman

Is your feature request related to a problem? Please describe.

If you define a dataclass descriptor field then it doesn't return self, so sphinx doesn't know to look for the descriptor's __doc__ attribute, which could be settable.

class Attribute:
    def __init__(self, default, doc):
        self.default = default
        self.__doc_ = doc

    def __set_name__(self, owner, name):
        self.name = name 

    def __get__(self, instance, owner):
        if isinstance(instance, None):
            return self.default
        return getattr(instance, self.name)

    def __set__(self, instance, value):
        setattr(instance, self.name, value)

@dataclass
class Class:
    attr = Attribute(1, doc="this is a docstring")

Describe the solution you'd like

I know that one can add a docstring after defining the attribute, but that's not always desired. It would be great if
sphinx, when looking at attributes on a class, also used vars to check if that attribute is actually a descriptor with a __doc__ attribute.

A hierarchy of docs preference will be required. I imagine this might be:

  1. Explicit docstring added to attribute
@dataclass
class Class:
    attr = Attribute(1, doc="this is a docstring")
    """This overrides the doc argument"""
  1. docstring on descriptor
@dataclass
class Class:
    attr = Attribute(1, doc="this is a docstring")

Describe alternatives you've considered

Developing a plugin to do this. However, this is a pretty common code pattern, e.g. doc in @property and dataclases are likewise property.

Activity

picnixz

picnixz commented on Sep 3, 2023

@picnixz
Member

Related to data descriptors for dataclasses: #11588

Upon my return I can have a look at both of them at the same time (for dataclasses, that would help a lot).

I won't be able to do anything until mid October though so if anyone wants to take on the task, feel free to do it (I'll still be able to review).

self-assigned this
on Sep 3, 2023
added this to the some future version milestone on Sep 3, 2023
picnixz

picnixz commented on Feb 3, 2024

@picnixz
Member

I investigated a bit but I'm not really sure how to properly fix this issue. It's quite easy to make it recognize descriptors and then extract the __doc__ from it but it's actually really difficult to ensure that we are not using a "bad" docstring, e.g., one that is due to Python.

One thing I can do is specialize the descriptor detection for dataclasses but I'm not really happy with this approach. Instead, a more careful analysis should be done but I don't really have the time today. I tried to implement something but observed that I would likely touch too many parts of autodoc which I don't want to (for now).

So, sorry but this feature needs to wait (again) :(

removed their assignment
on Feb 3, 2024
nstarman

nstarman commented on Feb 8, 2024

@nstarman
Author

I've found this function useful for resolving attributes on classes.

def all_cls_vars(obj: object | type, /) -> dict[str, Any]:
     """Return all variables in the whole class hierarchy."""
     cls = obj if isinstance(obj, type) else obj.__class__
     return functools.reduce(operator.__or__, map(vars, cls.mro()[::-1]))

Then

def is_descriptor(obj: Any) -> TypeGuard[SupportsGet]:
    return hasattr(obj, "__get__")

is_descriptor(all_cls_vars(Class)["attribute"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Development

    No branches or pull requests

      Participants

      @nstarman@picnixz

      Issue actions

        Docs from dataclass descriptor fields · Issue #11672 · sphinx-doc/sphinx