summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2010-07-31 10:16:21 (GMT)
committerGeorg Brandl <georg@python.org>2010-07-31 10:16:21 (GMT)
commit014e0ca58efed657ae2b6bdd724e4721967d05ef (patch)
tree1078793b2f5cfbdf48f398bcfce6071c26878ecf
parent4821ef89d4ce166c735cad48a57c03eae01fa577 (diff)
downloadcpython-014e0ca58efed657ae2b6bdd724e4721967d05ef.zip
cpython-014e0ca58efed657ae2b6bdd724e4721967d05ef.tar.gz
cpython-014e0ca58efed657ae2b6bdd724e4721967d05ef.tar.bz2
Revert r83327. This will have to wait until after the alpha1 release.
-rw-r--r--Doc/library/functools.rst51
-rw-r--r--Lib/functools.py94
-rw-r--r--Lib/test/test_functools.py48
-rw-r--r--Misc/NEWS2
4 files changed, 2 insertions, 193 deletions
diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst
index b2d69de..a9819f2 100644
--- a/Doc/library/functools.rst
+++ b/Doc/library/functools.rst
@@ -37,57 +37,6 @@ The :mod:`functools` module defines the following functions:
.. versionadded:: 3.2
-.. decorator:: lfu_cache(maxsize)
-
- Decorator to wrap a function with a memoizing callable that saves up to the
- *maxsize* most frequent calls. It can save time when an expensive or I/O
- bound function is periodically called with the same arguments.
-
- The *maxsize* parameter defaults to 100. Since a dictionary is used to cache
- results, the positional and keyword arguments to the function must be
- hashable.
-
- The wrapped function is instrumented with two attributes, :attr:`hits`
- and :attr:`misses` which count the number of successful or unsuccessful
- cache lookups. These statistics are helpful for tuning the *maxsize*
- parameter and for measuring the cache's effectiveness.
-
- The wrapped function also has a :attr:`clear` attribute which can be
- called (with no arguments) to clear the cache.
-
- A `LFU (least frequently used) cache
- <http://en.wikipedia.org/wiki/Cache_algorithms#Least-Frequently_Used>`_
- is indicated when the pattern of calls does not change over time, when
- more the most common calls already seen are the best predictors of the
- most common upcoming calls.
-
- .. versionadded:: 3.2
-
-.. decorator:: lru_cache(maxsize)
-
- Decorator to wrap a function with a memoizing callable that saves up to the
- *maxsize* most recent calls. It can save time when an expensive or I/O bound
- function is periodically called with the same arguments.
-
- The *maxsize* parameter defaults to 100. Since a dictionary is used to cache
- results, the positional and keyword arguments to the function must be
- hashable.
-
- The wrapped function is instrumented with two attributes, :attr:`hits`
- and :attr:`misses` which count the number of successful or unsuccessful
- cache lookups. These statistics are helpful for tuning the *maxsize*
- parameter and for measuring the cache's effectiveness.
-
- The wrapped function also has a :attr:`clear` attribute which can be
- called (with no arguments) to clear the cache.
-
- A `LRU (least recently used) cache
- <http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used>`_
- is indicated when the pattern of calls changes over time, such as
- when more recent calls are the best predictors of upcoming calls.
-
- .. versionadded:: 3.2
-
.. decorator:: total_ordering
Given a class defining one or more rich comparison ordering methods, this
diff --git a/Lib/functools.py b/Lib/functools.py
index 863706d..1a1f22e 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -4,17 +4,10 @@
# to allow utilities written in Python to be added
# to the functools module.
# Written by Nick Coghlan <ncoghlan at gmail.com>
-# and Raymond Hettinger <python at rcn.com>
-# Copyright (C) 2006-2010 Python Software Foundation.
+# Copyright (C) 2006 Python Software Foundation.
# See C source code for _functools credits/copyright
-__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
- 'total_ordering', 'cmp_to_key', 'lfu_cache', 'lru_cache']
-
from _functools import partial, reduce
-from collections import OrderedDict, Counter
-from heapq import nsmallest
-from operator import itemgetter
# update_wrapper() and wraps() are tools to help write
# wrapper functions that can handle naive introspection
@@ -104,88 +97,3 @@ def cmp_to_key(mycmp):
def __hash__(self):
raise TypeError('hash not implemented')
return K
-
-def lfu_cache(maxsize=100):
- '''Least-frequently-used cache decorator.
-
- Arguments to the cached function must be hashable.
- Cache performance statistics stored in f.hits and f.misses.
- Clear the cache using f.clear().
- http://en.wikipedia.org/wiki/Cache_algorithms#Least-Frequently_Used
-
- '''
- def decorating_function(user_function):
- cache = {} # mapping of args to results
- use_count = Counter() # times each key has been accessed
- kwd_mark = object() # separate positional and keyword args
-
- @wraps(user_function)
- def wrapper(*args, **kwds):
- key = args
- if kwds:
- key += (kwd_mark,) + tuple(sorted(kwds.items()))
- use_count[key] += 1 # count a use of this key
- try:
- result = cache[key]
- wrapper.hits += 1
- except KeyError:
- result = user_function(*args, **kwds)
- cache[key] = result
- wrapper.misses += 1
- if len(cache) > maxsize:
- # purge the 10% least frequently used entries
- for key, _ in nsmallest(maxsize // 10,
- use_count.items(),
- key=itemgetter(1)):
- del cache[key], use_count[key]
- return result
-
- def clear():
- 'Clear the cache and cache statistics'
- cache.clear()
- use_count.clear()
- wrapper.hits = wrapper.misses = 0
-
- wrapper.hits = wrapper.misses = 0
- wrapper.clear = clear
- return wrapper
- return decorating_function
-
-def lru_cache(maxsize=100):
- '''Least-recently-used cache decorator.
-
- Arguments to the cached function must be hashable.
- Cache performance statistics stored in f.hits and f.misses.
- Clear the cache using f.clear().
- http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
-
- '''
- def decorating_function(user_function):
- cache = OrderedDict() # ordered least recent to most recent
- kwd_mark = object() # separate positional and keyword args
-
- @wraps(user_function)
- def wrapper(*args, **kwds):
- key = args
- if kwds:
- key += (kwd_mark,) + tuple(sorted(kwds.items()))
- try:
- result = cache.pop(key)
- wrapper.hits += 1
- except KeyError:
- result = user_function(*args, **kwds)
- wrapper.misses += 1
- if len(cache) >= maxsize:
- cache.popitem(0) # purge least recently used cache entry
- cache[key] = result # record recent use of this key
- return result
-
- def clear():
- 'Clear the cache and cache statistics'
- cache.clear()
- wrapper.hits = wrapper.misses = 0
-
- wrapper.hits = wrapper.misses = 0
- wrapper.clear = clear
- return wrapper
- return decorating_function
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index a02d37c..f6ccc87 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -4,7 +4,6 @@ import unittest
from test import support
from weakref import proxy
import pickle
-from random import choice
@staticmethod
def PythonPartial(func, *args, **keywords):
@@ -455,50 +454,6 @@ class TestTotalOrdering(unittest.TestCase):
class A:
pass
-class TestLRU(unittest.TestCase):
-
- def test_lru(self):
- def orig(x, y):
- return 3*x+y
- f = functools.lru_cache(maxsize=20)(orig)
-
- domain = range(5)
- for i in range(1000):
- x, y = choice(domain), choice(domain)
- actual = f(x, y)
- expected = orig(x, y)
- self.assertEquals(actual, expected)
- self.assert_(f.hits > f.misses)
- self.assertEquals(f.hits + f.misses, 1000)
-
- f.clear() # test clearing
- self.assertEqual(f.hits, 0)
- self.assertEqual(f.misses, 0)
- f(x, y)
- self.assertEqual(f.hits, 0)
- self.assertEqual(f.misses, 1)
-
- def test_lfu(self):
- def orig(x, y):
- return 3*x+y
- f = functools.lfu_cache(maxsize=20)(orig)
-
- domain = range(5)
- for i in range(1000):
- x, y = choice(domain), choice(domain)
- actual = f(x, y)
- expected = orig(x, y)
- self.assertEquals(actual, expected)
- self.assert_(f.hits > f.misses)
- self.assertEquals(f.hits + f.misses, 1000)
-
- f.clear() # test clearing
- self.assertEqual(f.hits, 0)
- self.assertEqual(f.misses, 0)
- f(x, y)
- self.assertEqual(f.hits, 0)
- self.assertEqual(f.misses, 1)
-
def test_main(verbose=None):
test_classes = (
TestPartial,
@@ -506,8 +461,7 @@ def test_main(verbose=None):
TestPythonPartial,
TestUpdateWrapper,
TestWraps,
- TestReduce,
- TestLRU,
+ TestReduce
)
support.run_unittest(*test_classes)
diff --git a/Misc/NEWS b/Misc/NEWS
index d8f64a4..d04beaa 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -504,8 +504,6 @@ Library
- Issue #4179: In pdb, allow "list ." as a command to return to the currently
debugged line.
-- Add lfu_cache() and lru_cache() decorators to the functools module.
-
- Issue #4108: In urllib.robotparser, if there are multiple 'User-agent: *'
entries, consider the first one.