Comment for bounded_lru_cache_wrapper seems incorrect
Open
@tim-one is already working on this.
Since Jul 17, 2022.
extension-modules
type-bug
- Dominant language
- Python
- Stars
- 77.2k
- Forks
- 36k
- PR merge metrics
- PR metrics pending
Description
https://github.com/python/cpython/blob/c22f134211743cd5ad14cec1dd4f527bee542b4c/Modules/_functoolsmodule.c#L975-L976
However the __eq__ method call actually could be made for the deletion of the oldest entry.
from functools import lru_cache
class A:
def __init__(self, name):
self.name = name
self.counter = []
def __hash__(self):
return 0 # mock hash collision
def __eq__(self, __o: 'A'):
self.counter.append(__o.name)
return self is __o
@lru_cache(maxsize=2)
def foo(_):
return 0
a, b, c = A('a'), A('b'), A('c')
foo(a)
foo(b)
# make 'b' be the oldest-used entry
# but not the oldest-inserted entry
foo(a)
a.counter.clear()
foo(c) # will evict 'b'
# The assertion shows that
# 'a' was compared with 'b' for the deletion of 'b'
assert 'b' in a.counter
print(a.counter) # ['c', 'c', 'b', 'c']
It seems that reentrant here might cause the assertion in L1092 failed:
https://github.com/python/cpython/blob/c22f134211743cd5ad14cec1dd4f527bee542b4c/Modules/_functoolsmodule.c#L1092-L1099
Since link has been extracted but hasn't been popped from cache dict, link list could be empty while cache dict is full.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.