Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-106292: restore checking __dict__ in cached_property.__get__ #106380

Merged
merged 5 commits into from Jul 5, 2023

Conversation

carljm
Copy link
Member

@carljm carljm commented Jul 3, 2023

When locking was removed from functools.cached_property in #101890, the __get__ method also stopped pre-checking the instance dictionary for a cached value.

This removed pre-check is not necessary for the correct behavior of cached_property in and of itself: since it's a non-data descriptor (does not define __set__ or __delete__), the instance dictionary takes precedence over __get__, so __get__ should never be reached if a cached value is set in the instance dictionary.

But it seems that some users (including at least one popular library; see issue for details) are subclassing cached_property and adding a __set__ method, turning it into a data descriptor, which takes precedence over the instance dictionary. Prior to 3.12, this still worked OK (did not recompute the value on every access) because of the additional check for cached value in __get__. But with 3.12 as it currently stands, this code would silently stop caching the value due to the added __set__ method.

Although it's nice and clever for cached_property to be maximally efficient by taking advantage of being a non-data descriptor, I think in this case backwards-compatibility and avoiding a footgun is more important. Clearly some people are subclassing cached_property and adding __set__ methods, and it's not realistic to expect every Python user to understand the subtleties of data vs non-data descriptors and how this could break cached_property. The cost here is also minimal: just one dictionary lookup, that should only occur once per instance (not on repeated access of the cached property).

@carljm carljm added the needs backport to 3.12 bug and security fixes label Jul 3, 2023
* main:
  pythongh-106368: Increase Argument Clinic test coverage (python#106389)
  pythongh-106320: Fix _PyImport_GetModuleAttr() declaration (python#106386)
  pythongh-106368: Harden Argument Clinic parser tests (python#106384)
  pythongh-106320: Remove private _PyImport C API functions (python#106383)
  pythongh-86085: Remove _PyCodec_Forget() declaration (python#106377)
  pythongh-106320: Remove more private _PyUnicode C API functions (python#106382)
  pythongh-104050: Annotate more Argument Clinic DSLParser state methods (python#106376)
  pythongh-106368: Clean up Argument Clinic tests (python#106373)
Copy link
Member

@corona10 corona10 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some nit comments.

Lib/functools.py Show resolved Hide resolved
Co-authored-by: Dong-hee Na <donghee.na92@gmail.com>
Copy link
Member

@corona10 corona10 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@carljm carljm merged commit 838406b into python:main Jul 5, 2023
23 checks passed
@miss-islington
Copy link
Contributor

Thanks @carljm for the PR 🌮🎉.. I'm working now to backport this PR to: 3.12.
🐍🍒⛏🤖

@carljm carljm deleted the cachedpropdoublecheck branch July 5, 2023 23:01
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Jul 5, 2023
…pythonGH-106380)

* pythongh-106292: restore checking __dict__ in cached_property.__get__

(cherry picked from commit 838406b)

Co-authored-by: Carl Meyer <carl@oddbird.net>
Co-authored-by: Dong-hee Na <donghee.na92@gmail.com>
@bedevere-bot
Copy link

GH-106469 is a backport of this pull request to the 3.12 branch.

@bedevere-bot bedevere-bot removed the needs backport to 3.12 bug and security fixes label Jul 5, 2023
carljm added a commit that referenced this pull request Jul 5, 2023
GH-106380) (#106469)

gh-106292: restore checking __dict__ in cached_property.__get__ (GH-106380)

* gh-106292: restore checking __dict__ in cached_property.__get__

(cherry picked from commit 838406b)

Co-authored-by: Carl Meyer <carl@oddbird.net>
Co-authored-by: Dong-hee Na <donghee.na92@gmail.com>
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.

None yet

4 participants