Skip to content

Fix #1325: Put cached properties in class __dict__ (not the nonexistent instance __dict__) for slotted classes#1516

Closed
clayote wants to merge 9 commits into
python-attrs:mainfrom
clayote:cache_prop_slots_doc
Closed

Fix #1325: Put cached properties in class __dict__ (not the nonexistent instance __dict__) for slotted classes#1516
clayote wants to merge 9 commits into
python-attrs:mainfrom
clayote:cache_prop_slots_doc

Conversation

@clayote

@clayote clayote commented Feb 20, 2026

Copy link
Copy Markdown

Summary

I couldn't get Sphinx to generate docstrings for @cached_propertys on attrs' default slots=True classes. Trying to replace the generated __getattr__ didn't perform so well...but, __slots__ can be a dictionary, and that dictionary can have docstrings in it. This PR makes attrs generate __slots__ as a dictionary, with docstrings copied from the decorated @cached_property functions.

I still wanted Sphinx to document these like normal @cached_property, so I looked into Sphinx's code, and it turns out that it looks specifically at the class's __dict__ to find members to document. So I put the cached_property objects back into that __dict__ after class instantiation, and it worked! Those cached_property objects are never called, but they look just like usual from Sphinx's point of view.

That makes the __slots__ dictionary somewhat redundant, but I'd rather keep it, since it means help() works on those instance attributes.

Fixes #1325.

Pull Request Check List

  • Do not open pull requests from your main branch – use a separate branch!
    • There's a ton of footguns waiting if you don't heed this warning. You can still go back to your project, create a branch from your main branch, push it, and open the pull request from the new branch.
    • This is not a pre-requisite for your pull request to be accepted, but you have been warned.
  • Added tests for changed code.
    Our CI fails if coverage is not 100%.
  • Changes or additions to public APIs are reflected in our type stubs (files ending in .pyi).
    • ...and used in the stub test file typing-examples/baseline.py or, if necessary, typing-examples/mypy.py.
    • If they've been added to attr/__init__.pyi, they've also been re-imported in attrs/__init__.pyi.
  • Updated documentation for changed code.
    • New functions/classes have to be added to docs/api.rst by hand.
    • Changes to the signatures of @attr.s() and @attrs.define() have to be added by hand too.
    • Changed/added classes/methods/functions have appropriate versionadded, versionchanged, or deprecated directives.
      The next version is the second number in the current release + 1.
      The first number represents the current year.
      So if the current version on PyPI is 22.2.0, the next version is gonna be 22.3.0.
      If the next version is the first in the new year, it'll be 23.1.0.
      • If something changed that affects both attrs.define() and attr.s(), you have to add version directives to both.
  • Documentation in .rst and .md files is written using semantic newlines.
  • Changes (and possible deprecations) have news fragments in changelog.d.
  • Consider granting push permissions to the PR branch, so maintainers can fix minor issues themselves without pestering you.

@clayote clayote force-pushed the cache_prop_slots_doc branch from 8f37ad1 to 4545f0b Compare February 20, 2026 08:05
I have not worked out how to make the annotation really show up in generated Sphinx output. At least the docstring is there.
@clayote clayote force-pushed the cache_prop_slots_doc branch from 4ecfa51 to 8bfb9f1 Compare February 20, 2026 08:15
pre-commit-ci Bot and others added 8 commits February 20, 2026 08:15
They still don't say they're `property`s
The property objects do nothing, because they're not accessible from the instance -- slotted instances have no __dict__, but their *class object* does have __dict__, and that's the __dict__ that Sphinx looks at to find class members to document.
@clayote clayote changed the title Generate a dictionary with docstrings for slots that are @cached_propertys Fix #1325: Put cached properties in class __dict__ (not the nonexistent instance __dict__) for slotted classes Feb 20, 2026
@clayote

clayote commented Feb 20, 2026

Copy link
Copy Markdown
Author

Well, the dictionary __slots__ turns out to be impossible to unit test, so I'll make another PR without it.

@clayote clayote closed this Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

slots + cached_property + sphinx

1 participant