Kaydet (Commit) 4b779b37 authored tarafından Raymond Hettinger's avatar Raymond Hettinger

Issue 13177: Make tracebacks more readable by avoiding chained exceptions in the lru_cache.

üst 9be57231
...@@ -141,7 +141,7 @@ def lru_cache(maxsize=100): ...@@ -141,7 +141,7 @@ def lru_cache(maxsize=100):
hits = misses = 0 hits = misses = 0
kwd_mark = (object(),) # separates positional and keyword args kwd_mark = (object(),) # separates positional and keyword args
lock = Lock() # needed because ordereddicts aren't threadsafe lock = Lock() # needed because OrderedDict isn't threadsafe
if maxsize is None: if maxsize is None:
cache = dict() # simple cache without ordering or size limit cache = dict() # simple cache without ordering or size limit
...@@ -155,7 +155,9 @@ def lru_cache(maxsize=100): ...@@ -155,7 +155,9 @@ def lru_cache(maxsize=100):
try: try:
result = cache[key] result = cache[key]
hits += 1 hits += 1
return result
except KeyError: except KeyError:
pass
result = user_function(*args, **kwds) result = user_function(*args, **kwds)
cache[key] = result cache[key] = result
misses += 1 misses += 1
...@@ -171,12 +173,14 @@ def lru_cache(maxsize=100): ...@@ -171,12 +173,14 @@ def lru_cache(maxsize=100):
key = args key = args
if kwds: if kwds:
key += kwd_mark + tuple(sorted(kwds.items())) key += kwd_mark + tuple(sorted(kwds.items()))
try:
with lock: with lock:
try:
result = cache[key] result = cache[key]
cache_renew(key) # record recent use of this key cache_renew(key) # record recent use of this key
hits += 1 hits += 1
return result
except KeyError: except KeyError:
pass
result = user_function(*args, **kwds) result = user_function(*args, **kwds)
with lock: with lock:
cache[key] = result # record recent use of this key cache[key] = result # record recent use of this key
......
...@@ -655,6 +655,22 @@ class TestLRU(unittest.TestCase): ...@@ -655,6 +655,22 @@ class TestLRU(unittest.TestCase):
self.assertEqual(fib.cache_info(), self.assertEqual(fib.cache_info(),
functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
def test_lru_with_exceptions(self):
# Verify that user_function exceptions get passed through without
# creating a hard-to-read chained exception.
# http://bugs.python.org/issue13177
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__)
# Verify that the previous exception did not result in a cached entry
with self.assertRaises(IndexError):
func(15)
def test_main(verbose=None): def test_main(verbose=None):
test_classes = ( test_classes = (
TestPartial, TestPartial,
......
...@@ -46,6 +46,10 @@ Library ...@@ -46,6 +46,10 @@ Library
- Issue #13158: Fix decoding and encoding of GNU tar specific base-256 number - Issue #13158: Fix decoding and encoding of GNU tar specific base-256 number
fields in tarfile. fields in tarfile.
- Issue #13177: Functools lru_cache() no longer calls the original function
inside an exception handler. This makes tracebacks easier to read because
chained exceptions are avoided.
- Issue #13025: mimetypes is now reading MIME types using the UTF-8 encoding, - Issue #13025: mimetypes is now reading MIME types using the UTF-8 encoding,
instead of the locale encoding. instead of the locale encoding.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment