[Python-checkins] cpython (merge 3.2 -> default): Merge

raymond.hettinger python-checkins at python.org
Sun Oct 16 09:01:28 CEST 2011


http://hg.python.org/cpython/rev/5f4a871759ea
changeset:   72944:5f4a871759ea
parent:      72941:c63087ac1f6c
parent:      72943:8365f82f8a13
user:        Raymond Hettinger <python at rcn.com>
date:        Sun Oct 16 00:00:51 2011 -0700
summary:
  Merge

files:
  Lib/functools.py           |  34 ++++++++++++++-----------
  Lib/test/test_functools.py |  16 ++++++++++++
  2 files changed, 35 insertions(+), 15 deletions(-)


diff --git a/Lib/functools.py b/Lib/functools.py
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -146,7 +146,7 @@
 
         hits = misses = 0
         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:
             cache = dict()              # simple cache without ordering or size limit
@@ -160,13 +160,15 @@
                 try:
                     result = cache[key]
                     hits += 1
+                    return result
                 except KeyError:
-                    result = user_function(*args, **kwds)
-                    cache[key] = result
-                    misses += 1
+                    pass
+                result = user_function(*args, **kwds)
+                cache[key] = result
+                misses += 1
                 return result
         else:
-            cache = OrderedDict()       # ordered least recent to most recent
+            cache = OrderedDict()           # ordered least recent to most recent
             cache_popitem = cache.popitem
             cache_renew = cache.move_to_end
 
@@ -176,18 +178,20 @@
                 key = args
                 if kwds:
                     key += kwd_mark + tuple(sorted(kwds.items()))
-                try:
-                    with lock:
+                with lock:
+                    try:
                         result = cache[key]
-                        cache_renew(key)        # record recent use of this key
+                        cache_renew(key)    # record recent use of this key
                         hits += 1
-                except KeyError:
-                    result = user_function(*args, **kwds)
-                    with lock:
-                        cache[key] = result     # record recent use of this key
-                        misses += 1
-                        if len(cache) > maxsize:
-                            cache_popitem(0)    # purge least recently used cache entry
+                        return result
+                    except KeyError:
+                        pass
+                result = user_function(*args, **kwds)
+                with lock:
+                    cache[key] = result     # record recent use of this key
+                    misses += 1
+                    if len(cache) > maxsize:
+                        cache_popitem(0)    # purge least recently used cache entry
                 return result
 
         def cache_info():
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,22 @@
         self.assertEqual(fib.cache_info(),
             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):
     test_classes = (
         TestPartial,

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list