diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -142,7 +142,7 @@ # to allow the implementation to change (including a possible C version). def decorating_function(user_function, - tuple=tuple, sorted=sorted, len=len, KeyError=KeyError): + tuple=tuple, sorted=sorted, len=len): hits = misses = 0 kwd_mark = (object(),) # separates positional and keyword args @@ -157,10 +157,10 @@ key = args if kwds: key += kwd_mark + tuple(sorted(kwds.items())) - try: + if key in cache: result = cache[key] hits += 1 - except KeyError: + else: result = user_function(*args, **kwds) cache[key] = result misses += 1 @@ -176,12 +176,12 @@ key = args if kwds: key += kwd_mark + tuple(sorted(kwds.items())) - try: + if key in cache: with lock: result = cache[key] cache_renew(key) # record recent use of this key hits += 1 - except KeyError: + else: result = user_function(*args, **kwds) with lock: cache[key] = result # record recent use of this key diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -718,6 +718,16 @@ self.assertEqual(fib.cache_info(), functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + def test_lru_with_exceptions(self): + for maxsize in (None, 100): + @functools.lru_cache(maxsize) + def func(i): + return 'abc'[i] + self.assertEqual(func(0), 'a') + with self.assertRaises(IndexError) as cm: + func(15) + self.assertIsNone(cm.exception.__context__) + def test_main(verbose=None): test_classes = ( TestPartial,