mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-35780: Fix errors in lru_cache() C code (GH-11623)
This commit is contained in:
parent
adad9e6801
commit
d8080c0119
4 changed files with 234 additions and 89 deletions
|
@ -1233,6 +1233,33 @@ class TestLRU:
|
|||
self.assertEqual(misses, 4)
|
||||
self.assertEqual(currsize, 2)
|
||||
|
||||
def test_lru_bug_35780(self):
|
||||
# C version of the lru_cache was not checking to see if
|
||||
# the user function call has already modified the cache
|
||||
# (this arises in recursive calls and in multi-threading).
|
||||
# This cause the cache to have orphan links not referenced
|
||||
# by the cache dictionary.
|
||||
|
||||
once = True # Modified by f(x) below
|
||||
|
||||
@self.module.lru_cache(maxsize=10)
|
||||
def f(x):
|
||||
nonlocal once
|
||||
rv = f'.{x}.'
|
||||
if x == 20 and once:
|
||||
once = False
|
||||
rv = f(x)
|
||||
return rv
|
||||
|
||||
# Fill the cache
|
||||
for x in range(15):
|
||||
self.assertEqual(f(x), f'.{x}.')
|
||||
self.assertEqual(f.cache_info().currsize, 10)
|
||||
|
||||
# Make a recursive call and make sure the cache remains full
|
||||
self.assertEqual(f(20), '.20.')
|
||||
self.assertEqual(f.cache_info().currsize, 10)
|
||||
|
||||
def test_lru_hash_only_once(self):
|
||||
# To protect against weird reentrancy bugs and to improve
|
||||
# efficiency when faced with slow __hash__ methods, the
|
||||
|
@ -1329,7 +1356,7 @@ class TestLRU:
|
|||
for i in (0, 1):
|
||||
self.assertEqual([eq(n) for n in range(150)], list(range(150)))
|
||||
self.assertEqual(eq.cache_info(),
|
||||
self.module._CacheInfo(hits=0, misses=300, maxsize=-10, currsize=1))
|
||||
self.module._CacheInfo(hits=0, misses=300, maxsize=0, currsize=0))
|
||||
|
||||
def test_lru_with_exceptions(self):
|
||||
# Verify that user_function exceptions get passed through without
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue