Hello community, here is the log from the commit of package python-repoze.lru for openSUSE:Factory checked in at 2017-12-04 10:01:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-repoze.lru (Old) and /work/SRC/openSUSE:Factory/.python-repoze.lru.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-repoze.lru" Mon Dec 4 10:01:16 2017 rev:9 rq:544313 version:0.7 Changes: -------- --- /work/SRC/openSUSE:Factory/python-repoze.lru/python-repoze.lru.changes 2017-08-24 18:33:01.281177712 +0200 +++ /work/SRC/openSUSE:Factory/.python-repoze.lru.new/python-repoze.lru.changes 2017-12-04 10:01:17.694770238 +0100 @@ -1,0 +2,5 @@ +Wed Nov 15 00:06:03 UTC 2017 - [email protected] + +- update to 0.7 + +------------------------------------------------------------------- Old: ---- repoze.lru-0.6.tar.gz New: ---- repoze.lru-0.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-repoze.lru.spec ++++++ --- /var/tmp/diff_new_pack.3vpkev/_old 2017-12-04 10:01:18.462742365 +0100 +++ /var/tmp/diff_new_pack.3vpkev/_new 2017-12-04 10:01:18.466742219 +0100 @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-repoze.lru -Version: 0.6 +Version: 0.7 Release: 0 Summary: A tiny LRU cache implementation and decorator License: SUSE-Repoze @@ -50,7 +50,7 @@ %files %{python_files} %defattr(-,root,root,-) -%doc CHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt +%doc LICENSE.txt %{python_sitelib}/* %changelog ++++++ repoze.lru-0.6.tar.gz -> repoze.lru-0.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/.coveragerc new/repoze.lru-0.7/.coveragerc --- old/repoze.lru-0.6/.coveragerc 1970-01-01 01:00:00.000000000 +0100 +++ new/repoze.lru-0.7/.coveragerc 2016-11-12 23:29:27.000000000 +0100 @@ -0,0 +1,3 @@ +[report] +show_missing = True + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/.travis.yml new/repoze.lru-0.7/.travis.yml --- old/repoze.lru-0.6/.travis.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/repoze.lru-0.7/.travis.yml 2016-11-12 23:48:42.000000000 +0100 @@ -0,0 +1,26 @@ +# Wire up travis +language: python +sudo: false + +matrix: + include: + - python: 3.5 + env: TOXENV=py35 + +env: + - TOXENV=py27 + - TOXENV=py33 + - TOXENV=py34 + - TOXENV=pypy + - TOXENV=pypy3 + - TOXENV=cover + +install: + - travis_retry pip install tox + +script: + - travis_retry tox + +notifications: + email: + - [email protected] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/CHANGES.txt new/repoze.lru-0.7/CHANGES.txt --- old/repoze.lru-0.6/CHANGES.txt 2012-07-12 20:45:06.000000000 +0200 +++ new/repoze.lru-0.7/CHANGES.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,72 +0,0 @@ -Changelog -========= - -0.6 (2012-07-12) ----------------- - -- Added a 'CacheMaker' helper class: a maker keeps references (by name) - to the caches it creates, to permit them to be cleared. - -- Added statistics to each cache, tracking lookups, hits, misses, and - evictions. - -- Automated building Sphinx docs and testing example snippets under ``tox``. - -- Added Sphinx documentation. - -- Dropped support for Python 2.5. - -- Added support for PyPy. - -- Added ``setup.py docs`` alias (installs ``Sphinx`` and dependencies). - -- Added ``setup.py dev`` alias (runs ``develop`` plus installs ``nose`` - and ``coverage``). - -- Added support for CI under supported Pythons using ``tox``. - -- Bug: Remove potential race condition on lock in face of interrupts - (Issue #10). - -0.5 (2012-03-24) ----------------- - -- Feature: added a new "invalidate()" method to allow removal of items from - the cache (issue #8). - -- Bug: LRUCache.put() could take multiple seconds on large caches (Issue #7). - -- Bug: LRUCache was not thread safe (Issue #6). - -- Bug: LRUCache.clock would waste RAM (Issue #4). - -- Bug: repeated pushing of an entry would remove other cache entries - (Issue #3). - -- Bug: LRUCache would evict entries even when not full (Issue #2). - -0.4 (2011-09-04) ----------------- - -- Moved to GitHub (https://github.com/repoze/repoze.lru). - -- Added Python 3.2 support. - -- Python 2.4 no longer supported. - -- Added tox.ini for easier testing. - -0.3 (2009/06/16) ----------------- - -- Add a thread lock around ``clear`` logic. - -0.2 (2009/06/15) ----------------- - -- Add a ``clear`` method. - -0.1 (2009/06/14) ----------------- - -- Initial release. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/CONTRIBUTORS.txt new/repoze.lru-0.7/CONTRIBUTORS.txt --- old/repoze.lru-0.6/CONTRIBUTORS.txt 2012-07-05 15:36:30.000000000 +0200 +++ new/repoze.lru-0.7/CONTRIBUTORS.txt 2016-11-12 23:10:28.000000000 +0100 @@ -106,3 +106,4 @@ - Tres Seaver, 2011/02/22 - Joel Bohman, 2011/08/16 - Julien Tayon, 2012/07/04 +- Cosmin Basca, 2014/07/12 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/PKG-INFO new/repoze.lru-0.7/PKG-INFO --- old/repoze.lru-0.6/PKG-INFO 2012-07-12 20:48:37.000000000 +0200 +++ new/repoze.lru-0.7/PKG-INFO 2017-09-07 07:00:09.000000000 +0200 @@ -1,103 +1,24 @@ Metadata-Version: 1.1 Name: repoze.lru -Version: 0.6 +Version: 0.7 Summary: A tiny LRU cache implementation and decorator Home-page: http://www.repoze.org Author: Agendaless Consulting Author-email: [email protected] License: BSD-derived (http://www.repoze.org/LICENSE.txt) -Description: repoze.lru - ========== +Description: - ``repoze.lru`` is a LRU (least recently used) cache implementation. Keys and - values that are not used frequently will be evicted from the cache faster - than keys and values that are used frequently. It works under Python 2.5, - Python 2.6, Python 2.7, and Python 3.2. - - Please see ``docs/index.rst`` for detailed documentation. - - - Changelog - ========= - - 0.6 (2012-07-12) - ---------------- - - - Added a 'CacheMaker' helper class: a maker keeps references (by name) - to the caches it creates, to permit them to be cleared. - - - Added statistics to each cache, tracking lookups, hits, misses, and - evictions. - - - Automated building Sphinx docs and testing example snippets under ``tox``. - - - Added Sphinx documentation. - - - Dropped support for Python 2.5. - - - Added support for PyPy. - - - Added ``setup.py docs`` alias (installs ``Sphinx`` and dependencies). - - - Added ``setup.py dev`` alias (runs ``develop`` plus installs ``nose`` - and ``coverage``). - - - Added support for CI under supported Pythons using ``tox``. - - - Bug: Remove potential race condition on lock in face of interrupts - (Issue #10). - - 0.5 (2012-03-24) - ---------------- - - - Feature: added a new "invalidate()" method to allow removal of items from - the cache (issue #8). - - - Bug: LRUCache.put() could take multiple seconds on large caches (Issue #7). - - - Bug: LRUCache was not thread safe (Issue #6). - - - Bug: LRUCache.clock would waste RAM (Issue #4). - - - Bug: repeated pushing of an entry would remove other cache entries - (Issue #3). - - - Bug: LRUCache would evict entries even when not full (Issue #2). - - 0.4 (2011-09-04) - ---------------- - - - Moved to GitHub (https://github.com/repoze/repoze.lru). - - - Added Python 3.2 support. - - - Python 2.4 no longer supported. - - - Added tox.ini for easier testing. - - 0.3 (2009/06/16) - ---------------- - - - Add a thread lock around ``clear`` logic. - - 0.2 (2009/06/15) - ---------------- - - - Add a ``clear`` method. - - 0.1 (2009/06/14) - ---------------- - - - Initial release. Keywords: repoze lru cache Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: License :: Repoze Public License diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/README.rst new/repoze.lru-0.7/README.rst --- old/repoze.lru-0.6/README.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/repoze.lru-0.7/README.rst 2017-09-07 06:53:52.000000000 +0200 @@ -0,0 +1,9 @@ +repoze.lru +========== + +``repoze.lru`` is a LRU (least recently used) cache implementation. Keys and +values that are not used frequently will be evicted from the cache faster +than keys and values that are used frequently. It works under Python 2.7 and Python 3.4+. + +Please see ``docs/index.rst`` for detailed documentation, or view them +online at http://docs.repoze.org/lru/. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/README.txt new/repoze.lru-0.7/README.txt --- old/repoze.lru-0.6/README.txt 2012-06-11 23:14:39.000000000 +0200 +++ new/repoze.lru-0.7/README.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,9 +0,0 @@ -repoze.lru -========== - -``repoze.lru`` is a LRU (least recently used) cache implementation. Keys and -values that are not used frequently will be evicted from the cache faster -than keys and values that are used frequently. It works under Python 2.5, -Python 2.6, Python 2.7, and Python 3.2. - -Please see ``docs/index.rst`` for detailed documentation. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/repoze/__init__.py new/repoze.lru-0.7/repoze/__init__.py --- old/repoze.lru-0.6/repoze/__init__.py 2011-02-25 16:23:45.000000000 +0100 +++ new/repoze.lru-0.7/repoze/__init__.py 2013-06-24 20:58:51.000000000 +0200 @@ -1 +1,4 @@ -__import__('pkg_resources').declare_namespace(__name__) +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + __path__ = __import__('pkgutil').extend_path(__path__, __name__) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/repoze/lru/__init__.py new/repoze.lru-0.7/repoze/lru/__init__.py --- old/repoze.lru-0.6/repoze/lru/__init__.py 2012-07-05 15:36:30.000000000 +0200 +++ new/repoze.lru-0.7/repoze/lru/__init__.py 2016-11-13 00:58:23.000000000 +0100 @@ -1,5 +1,6 @@ """ LRU caching class and decorator """ -from __future__ import with_statement +from abc import abstractmethod +from abc import ABCMeta import threading import time @@ -12,7 +13,51 @@ _DEFAULT_TIMEOUT = 2 ** 60 -class LRUCache(object): +class Cache(object): + __metaclass__ = ABCMeta + + @abstractmethod + def clear(self): + """Remove all entries from the cache""" + + @abstractmethod + def get(self, key, default=None): + """Return value for key. If not in cache, return default""" + + @abstractmethod + def put(self, key, val): + """Add key to the cache with value val""" + + @abstractmethod + def invalidate(self, key): + """Remove key from the cache""" + + +class UnboundedCache(Cache): + """ + a simple unbounded cache backed by a dictionary + """ + + def __init__(self): + self._data = dict() + + def get(self, key, default=None): + return self._data.get(key, default) + + def clear(self): + self._data.clear() + + def invalidate(self, key): + try: + del self._data[key] + except KeyError: + pass + + def put(self, key, val): + self._data[key] = val + + +class LRUCache(Cache): """ Implements a pseudo-LRU algorithm (CLOCK) The Clock algorithm is not kept strictly to improve performance, e.g. to @@ -130,7 +175,7 @@ # else: key was not in cache. Nothing to do. -class ExpiringLRUCache(object): +class ExpiringLRUCache(Cache): """ Implements a pseudo-LRU algorithm (CLOCK) with expiration times The Clock algorithm is not kept strictly to improve performance, e.g. to @@ -270,27 +315,50 @@ timeout parameter specifies after how many seconds a cached entry should be considered invalid. """ - def __init__(self, maxsize, cache=None, timeout=None): # cache is an arg to serve tests + def __init__(self, + maxsize, + cache=None, # cache is an arg to serve tests + timeout=None, + ignore_unhashable_args=False): if cache is None: - if timeout is None: + if maxsize is None: + cache = UnboundedCache() + elif timeout is None: cache = LRUCache(maxsize) else: cache = ExpiringLRUCache(maxsize, default_timeout=timeout) self.cache = cache + self._ignore_unhashable_args = ignore_unhashable_args - def __call__(self, f): + def __call__(self, func): cache = self.cache marker = _MARKER - def lru_cached(*arg): - val = cache.get(arg, marker) - if val is marker: - val = f(*arg) - cache.put(arg, val) - return val - lru_cached.__module__ = f.__module__ - lru_cached.__name__ = f.__name__ - lru_cached.__doc__ = f.__doc__ - return lru_cached + + def cached_wrapper(*args, **kwargs): + try: + key = (args, frozenset(kwargs.items())) if kwargs else args + except TypeError as e: + if self._ignore_unhashable_args: + return func(*args, **kwargs) + else: + raise e + else: + val = cache.get(key, marker) + if val is marker: + val = func(*args, **kwargs) + cache.put(key, val) + return val + + def _maybe_copy(source, target, attr): + value = getattr(source, attr, source) + if value is not source: + setattr(target, attr, value) + + _maybe_copy(func, cached_wrapper, '__module__') + _maybe_copy(func, cached_wrapper, '__name__') + _maybe_copy(func, cached_wrapper, '__doc__') + cached_wrapper._cache = cache + return cached_wrapper class CacheMaker(object): @@ -312,7 +380,7 @@ while True: name = str(uuid.uuid4()) ## the probability of collision is so low .... - if name not in self._cache: + if name not in self._cache: # pragma: NO COVER break if name in self._cache: @@ -328,7 +396,12 @@ timeout = self._timeout return name, maxsize, timeout - + + def memoized(self, name=None): + name, maxsize, _ = self._resolve_setting(name, 0) + cache = self._cache[name] = UnboundedCache() + return lru_cache(None, cache) + def lrucache(self, name=None, maxsize=None): """Named arguments: @@ -350,12 +423,12 @@ the constructor - timeout (optional) is an int, overriding any default value set by - the constructor or the default value (%d seconds) + the constructor or the default value (%d seconds) """ % _DEFAULT_TIMEOUT name, maxsize, timeout = self._resolve_setting(name, maxsize, timeout) cache = self._cache[name] = ExpiringLRUCache(maxsize, timeout) return lru_cache(maxsize, cache, timeout) - + def clear(self, *names): """Clear the given cache(s). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/repoze/lru/tests.py new/repoze.lru-0.7/repoze/lru/tests.py --- old/repoze.lru-0.6/repoze/lru/tests.py 2012-07-05 15:36:30.000000000 +0200 +++ new/repoze.lru-0.7/repoze/lru/tests.py 2016-11-13 01:53:11.000000000 +0100 @@ -8,14 +8,67 @@ pass +class UnboundedCacheTests(unittest.TestCase): + + def _getTargetClass(self): + from repoze.lru import UnboundedCache + return UnboundedCache + + def _makeOne(self): + return self._getTargetClass()() + + def test_ctor(self): + cache = self._makeOne() + self.assertEqual(cache._data, {}) + + def test_get_miss_no_default(self): + cache = self._makeOne() + self.assertIsNone(cache.get('nonesuch')) + + def test_get_miss_explicit_default(self): + cache = self._makeOne() + default = object() + self.assertIs(cache.get('nonesuch', default), default) + + def test_get_hit(self): + cache = self._makeOne() + extant = cache._data['extant'] = object() + self.assertIs(cache.get('extant'), extant) + + def test_clear(self): + cache = self._makeOne() + extant = cache._data['extant'] = object() + cache.clear() + self.assertIsNone(cache.get('extant')) + + def test_invalidate_miss(self): + cache = self._makeOne() + cache.invalidate('nonesuch') # does not raise + + def test_invalidate_hit(self): + cache = self._makeOne() + extant = cache._data['extant'] = object() + cache.invalidate('extant') + self.assertIsNone(cache.get('extant')) + + def test_put(self): + cache = self._makeOne() + extant = object() + cache.put('extant', extant) + self.assertIs(cache._data['extant'], extant) + + class LRUCacheTests(unittest.TestCase): def _getTargetClass(self): from repoze.lru import LRUCache return LRUCache + def _makeOne(self, size): + return self._getTargetClass()(size) + def check_cache_is_consistent(self, cache): - """Return if cache is consistent, else raise fail test case.""" + #Return if cache is consistent, else raise fail test case. # cache.hand/maxpos/size self.assertTrue(cache.hand < len(cache.clock_keys)) self.assertTrue(cache.hand >= 0) @@ -45,21 +98,18 @@ for clock_ref in cache.clock_refs: self.assertTrue(clock_ref is True or clock_ref is False) - def _makeOne(self, size): - return self._getTargetClass()(size) - def test_size_lessthan_1(self): self.assertRaises(ValueError, self._makeOne, 0) def test_get(self): cache = self._makeOne(1) # Must support different types of keys - self.assertEqual(cache.get("foo"), None) - self.assertEqual(cache.get(42), None) - self.assertEqual(cache.get(("foo", 42)), None) - self.assertEqual(cache.get(None), None) - self.assertEqual(cache.get(""), None) - self.assertEqual(cache.get(object()), None) + self.assertIsNone(cache.get("foo")) + self.assertIsNone(cache.get(42)) + self.assertIsNone(cache.get(("foo", 42))) + self.assertIsNone(cache.get(None)) + self.assertIsNone(cache.get("")) + self.assertIsNone(cache.get(object())) # Check if default value is used self.assertEqual(cache.get("foo", "bar"), "bar") self.assertEqual(cache.get("foo", default="bar"), "bar") @@ -101,24 +151,24 @@ cache.put("FOO", "BAR") cache.invalidate("foo") - self.assertEqual(cache.get("foo"), None) + self.assertIsNone(cache.get("foo")) self.assertEqual(cache.get("FOO"), "BAR") self.check_cache_is_consistent(cache) cache.invalidate("FOO") - self.assertEqual(cache.get("foo"), None) - self.assertEqual(cache.get("FOO"), None) + self.assertIsNone(cache.get("foo")) + self.assertIsNone(cache.get("FOO")) self.assertEqual(cache.data, {}) self.check_cache_is_consistent(cache) cache.put("foo", "bar") cache.invalidate("nonexistingkey") self.assertEqual(cache.get("foo"), "bar") - self.assertEqual(cache.get("FOO"), None) + self.assertIsNone(cache.get("FOO")) self.check_cache_is_consistent(cache) def test_small_cache(self): - """Cache of size 1 must work""" + #Cache of size 1 must work cache = self._makeOne(1) cache.put("foo", "bar") @@ -127,31 +177,31 @@ cache.put("FOO", "BAR") self.assertEqual(cache.get("FOO"), "BAR") - self.assertEqual(cache.get("foo"), None) + self.assertIsNone(cache.get("foo")) self.check_cache_is_consistent(cache) # put() again cache.put("FOO", "BAR") self.assertEqual(cache.get("FOO"), "BAR") - self.assertEqual(cache.get("foo"), None) + self.assertIsNone(cache.get("foo")) self.check_cache_is_consistent(cache) # invalidate() cache.invalidate("FOO") self.check_cache_is_consistent(cache) - self.assertEqual(cache.get("FOO"), None) - self.assertEqual(cache.get("foo"), None) + self.assertIsNone(cache.get("FOO")) + self.assertIsNone(cache.get("foo")) # clear() cache.put("foo", "bar") self.assertEqual(cache.get("foo"), "bar") cache.clear() self.check_cache_is_consistent(cache) - self.assertEqual(cache.get("FOO"), None) - self.assertEqual(cache.get("foo"), None) + self.assertIsNone(cache.get("FOO")) + self.assertIsNone(cache.get("foo")) def test_equal_but_not_identical(self): - """equal but not identical keys must be treated the same""" + #equal but not identical keys must be treated the same cache = self._makeOne(1) tuple_one = (1, 1) tuple_two = (1, 1) @@ -164,11 +214,11 @@ cache = self._makeOne(1) cache.put(tuple_one, 42) cache.invalidate(tuple_two) - self.assertEqual(cache.get(tuple_one), None) - self.assertEqual(cache.get(tuple_two), None) + self.assertIsNone(cache.get(tuple_one)) + self.assertIsNone(cache.get(tuple_two)) def test_perfect_hitrate(self): - """If cache size equals number of items, expect 100% cache hits""" + #If cache size equals number of items, expect 100% cache hits size = 1000 cache = self._makeOne(size) @@ -188,7 +238,7 @@ self.check_cache_is_consistent(cache) def test_imperfect_hitrate(self): - """If cache size == half the number of items -> hit rate ~50%""" + #If cache size == half the number of items -> hit rate ~50% size = 1000 cache = self._makeOne(size / 2) @@ -250,7 +300,7 @@ def test_it(self): cache = self._makeOne(3) - self.assertEqual(cache.get('a'), None) + self.assertIsNone(cache.get('a')) cache.put('a', '1') pos, value = cache.data.get('a') @@ -286,17 +336,17 @@ # because "a" is the first item with ref==False that is found. cache.put('d', '4') self.assertEqual(len(cache.data), 3) - self.assertEqual(cache.data.get('a'), None) + self.assertIsNone(cache.data.get('a')) # Only item "d" has ref==True. cache.hand points at "b", so "b" # will be evicted when "e" is inserted. "c" will be left alone. cache.put('e', '5') self.assertEqual(len(cache.data), 3) - self.assertEqual(cache.data.get('b'), None) + self.assertIsNone(cache.data.get('b')) self.assertEqual(cache.get('d'), '4') self.assertEqual(cache.get('e'), '5') - self.assertEqual(cache.get('a'), None) - self.assertEqual(cache.get('b'), None) + self.assertIsNone(cache.get('a')) + self.assertIsNone(cache.get('b')) self.assertEqual(cache.get('c'), '3') self.check_cache_is_consistent(cache) @@ -312,14 +362,14 @@ if default_timeout is None: return self._getTargetClass()(size) else: - return self._getTargetClass()(size, default_timeout=default_timeout) + return self._getTargetClass()( + size, default_timeout=default_timeout) def check_cache_is_consistent(self, cache): - """Return if cache is consistent, else raise fail test case. - - This is slightly different for ExpiringLRUCache since self.data - contains 3-tuples instead of 2-tuples. - """ + #Return if cache is consistent, else raise fail test case. + # + #This is slightly different for ExpiringLRUCache since self.data + #contains 3-tuples instead of 2-tuples. # cache.hand/maxpos/size self.assertTrue(cache.hand < len(cache.clock_keys)) self.assertTrue(cache.hand >= 0) @@ -351,12 +401,11 @@ self.assertTrue(clock_ref is True or clock_ref is False) def test_it(self): - """Test a sequence of operations - - Looks at internal data, which is different for ExpiringLRUCache. - """ + #Test a sequence of operations + # + # Looks at internal data, which is different for ExpiringLRUCache. cache = self._makeOne(3) - self.assertEqual(cache.get('a'), None) + self.assertIsNone(cache.get('a')) cache.put('a', '1') pos, value, expires = cache.data.get('a') @@ -392,23 +441,23 @@ # because "a" is the first item with ref==False that is found. cache.put('d', '4') self.assertEqual(len(cache.data), 3) - self.assertEqual(cache.data.get('a'), None) + self.assertIsNone(cache.data.get('a')) # Only item "d" has ref==True. cache.hand points at "b", so "b" # will be evicted when "e" is inserted. "c" will be left alone. cache.put('e', '5') self.assertEqual(len(cache.data), 3) - self.assertEqual(cache.data.get('b'), None) + self.assertIsNone(cache.data.get('b')) self.assertEqual(cache.get('d'), '4') self.assertEqual(cache.get('e'), '5') - self.assertEqual(cache.get('a'), None) - self.assertEqual(cache.get('b'), None) + self.assertIsNone(cache.get('a')) + self.assertIsNone(cache.get('b')) self.assertEqual(cache.get('c'), '3') self.check_cache_is_consistent(cache) def test_default_timeout(self): - """Default timeout provided at init time must be applied""" + #Default timeout provided at init time must be applied. # Provide no default timeout -> entries must remain valid cache = self._makeOne(3) cache.put("foo", "bar") @@ -425,12 +474,12 @@ time.sleep(0.1) cache.put("FOO", "BAR") - self.assertEqual(cache.get("foo"), None) + self.assertIsNone(cache.get("foo")) self.assertEqual(cache.get("FOO"), "BAR") self.check_cache_is_consistent(cache) def test_different_timeouts(self): - """Timeouts must be per entry, default applied when none provided""" + #Timeouts must be per entry, default applied when none provided cache = self._makeOne(3, default_timeout=0.1) cache.put("one", 1) @@ -444,26 +493,26 @@ # Entry "one" must expire, "two"/"three" remain valid time.sleep(0.1) - self.assertEqual(cache.get("one"), None) + self.assertIsNone(cache.get("one")) self.assertEqual(cache.get("two"), 2) self.assertEqual(cache.get("three"), 3) # Only "three" remains valid time.sleep(0.1) - self.assertEqual(cache.get("one"), None) - self.assertEqual(cache.get("two"), None) + self.assertIsNone(cache.get("one")) + self.assertIsNone(cache.get("two")) self.assertEqual(cache.get("three"), 3) # All have expired time.sleep(0.1) - self.assertEqual(cache.get("one"), None) - self.assertEqual(cache.get("two"), None) - self.assertEqual(cache.get("three"), None) + self.assertIsNone(cache.get("one")) + self.assertIsNone(cache.get("two")) + self.assertIsNone(cache.get("three")) self.check_cache_is_consistent(cache) def test_renew_timeout(self): - """Re-putting an entry must update timeout""" + #Re-putting an entry must update timeout cache = self._makeOne(3, default_timeout=0.2) cache.put("foo", "bar") @@ -485,7 +534,7 @@ time.sleep(0.1) # "foo2" must have expired self.assertEqual(cache.get("foo"), "bar") - self.assertEqual(cache.get("foo2"), None) + self.assertIsNone(cache.get("foo2")) self.assertEqual(cache.get("foo3"), "bar3") self.check_cache_is_consistent(cache) @@ -496,8 +545,27 @@ from repoze.lru import lru_cache return lru_cache - def _makeOne(self, maxsize, cache, timeout=None): - return self._getTargetClass()(maxsize, timeout=timeout, cache=cache) + def _makeOne(self, *args, **kw): + return self._getTargetClass()(*args, **kw) + + def test_ctor_no_size(self): + from repoze.lru import UnboundedCache + decorator = self._makeOne(maxsize=None) + self.assertIsInstance(decorator.cache, UnboundedCache) + self.assertEqual(decorator.cache._data, {}) + + def test_ctor_w_size_no_timeout(self): + from repoze.lru import LRUCache + decorator = self._makeOne(maxsize=10) + self.assertIsInstance(decorator.cache, LRUCache) + self.assertEqual(decorator.cache.size, 10) + + def test_ctor_w_size_w_timeout(self): + from repoze.lru import ExpiringLRUCache + decorator = self._makeOne(maxsize=10, timeout=30) + self.assertIsInstance(decorator.cache, ExpiringLRUCache) + self.assertEqual(decorator.cache.size, 10) + self.assertEqual(decorator.cache.default_timeout, 30) def test_ctor_nocache(self): decorator = self._makeOne(10, None) @@ -522,6 +590,14 @@ self.assertEqual(result, 2) self.assertEqual(len(cache), 2) + def test_cache_attr(self): + cache = DummyLRUCache() + decorator = self._makeOne(0, cache) + def wrapped(key): #pragma NO COVER + return key + decorated = decorator(wrapped) + self.assertTrue(decorated._cache is cache) + def test_multiargs(self): cache = DummyLRUCache() decorator = self._makeOne(0, cache) @@ -533,8 +609,43 @@ self.assertEqual(result, (3, 4, 5)) self.assertEqual(len(cache), 1) + def test_multiargs_keywords(self): + cache = DummyLRUCache() + decorator = self._makeOne(0, cache) + def moreargs(*args, **kwargs): + return args, kwargs + decorated = decorator(moreargs) + result = decorated(3, 4, 5, a=1, b=2, c=3) + self.assertEqual( + cache[((3, 4, 5), frozenset([ ('a',1), ('b',2), ('c',3) ]))], + ((3, 4, 5), {'a':1, 'b':2, 'c':3})) + self.assertEqual(result, ((3, 4, 5), {'a':1, 'b':2, 'c':3})) + self.assertEqual(len(cache), 1) + + def test_multiargs_keywords_ignore_unhashable_true(self): + cache = DummyLRUCache() + decorator = self._makeOne(0, cache, ignore_unhashable_args=True) + def moreargs(*args, **kwargs): + return args, kwargs + decorated = decorator(moreargs) + result = decorated(3, 4, 5, a=1, b=[1, 2, 3]) + self.assertEqual(len(cache), 0) + self.assertEqual(result, ((3, 4, 5), {'a':1, 'b':[1, 2, 3]})) + + def test_multiargs_keywords_ignore_unhashable(self): + cache = DummyLRUCache() + decorator = self._makeOne(0, cache, ignore_unhashable_args=False) + + def moreargs(*args, **kwargs): # pragma: NO COVER + return args, kwargs + + decorated = decorator(moreargs) + + with self.assertRaises(TypeError): + decorated(3, 4, 5, a=1, b=[1, 2, 3]) + def test_expiry(self): - """When timeout is given, decorator must eventually forget entries""" + #When timeout is given, decorator must eventually forget entries @self._makeOne(1, None, timeout=0.1) def sleep_a_bit(param): time.sleep(0.1) @@ -562,6 +673,16 @@ self.assertEqual(result3, 2 * "hello") self.assertTrue(stop - start > 0.1) + def test_partial(self): + #lru_cache decorator must not crash on functools.partial instances + def add(a,b): + return a + b + from functools import partial + from repoze.lru import lru_cache + add_five = partial(add, 5) + decorated = lru_cache(20)(add_five) + self.assertEqual(decorated(3), 8) + class DummyLRUCache(dict): @@ -644,6 +765,15 @@ self.assertEqual(len(maker._cache['two'].data), 10) self.assertEqual(len(maker._cache['three'].data), 0) + def test_memoized(self): + from repoze.lru import lru_cache + from repoze.lru import UnboundedCache + maker = self._makeOne(maxsize=10) + memo = maker.memoized('test') + self.assertIsInstance(memo, lru_cache) + self.assertIsInstance(memo.cache, UnboundedCache) + self.assertIs(memo.cache, maker._cache['test']) + def test_expiring(self): size = 10 timeout = 10 @@ -651,10 +781,13 @@ cache = self._makeOne(maxsize=size, timeout=timeout) for i in range(100): if not i: - decorated = cache.expiring_lrucache(name=name)(_adder) + decorator = cache.expiring_lrucache(name=name) + decorated = decorator(_adder) self.assertEqual( cache._cache[name].size,size) else: - decorated = cache.expiring_lrucache()(_adder) + decorator = cache.expiring_lrucache() + decorated = decorator(_adder) + self.assertEqual(decorator.cache.default_timeout, timeout) decorated(10) self.assertEqual( len(cache._cache) , 100) @@ -668,5 +801,14 @@ self.assertEqual( _cache.size,size) self.assertEqual(len(_cache.data),0) + def test_expiring_w_timeout(self): + size = 10 + maker_timeout = 10 + timeout = 20 + name = "name" + cache = self._makeOne(maxsize=size, timeout=maker_timeout) + decorator = cache.expiring_lrucache(name=name, timeout=20) + self.assertEqual(decorator.cache.default_timeout, timeout) + def _adder(x): return x + 10 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/repoze.lru.egg-info/PKG-INFO new/repoze.lru-0.7/repoze.lru.egg-info/PKG-INFO --- old/repoze.lru-0.6/repoze.lru.egg-info/PKG-INFO 2012-07-12 20:48:37.000000000 +0200 +++ new/repoze.lru-0.7/repoze.lru.egg-info/PKG-INFO 2017-09-07 07:00:09.000000000 +0200 @@ -1,103 +1,24 @@ Metadata-Version: 1.1 Name: repoze.lru -Version: 0.6 +Version: 0.7 Summary: A tiny LRU cache implementation and decorator Home-page: http://www.repoze.org Author: Agendaless Consulting Author-email: [email protected] License: BSD-derived (http://www.repoze.org/LICENSE.txt) -Description: repoze.lru - ========== +Description: - ``repoze.lru`` is a LRU (least recently used) cache implementation. Keys and - values that are not used frequently will be evicted from the cache faster - than keys and values that are used frequently. It works under Python 2.5, - Python 2.6, Python 2.7, and Python 3.2. - - Please see ``docs/index.rst`` for detailed documentation. - - - Changelog - ========= - - 0.6 (2012-07-12) - ---------------- - - - Added a 'CacheMaker' helper class: a maker keeps references (by name) - to the caches it creates, to permit them to be cleared. - - - Added statistics to each cache, tracking lookups, hits, misses, and - evictions. - - - Automated building Sphinx docs and testing example snippets under ``tox``. - - - Added Sphinx documentation. - - - Dropped support for Python 2.5. - - - Added support for PyPy. - - - Added ``setup.py docs`` alias (installs ``Sphinx`` and dependencies). - - - Added ``setup.py dev`` alias (runs ``develop`` plus installs ``nose`` - and ``coverage``). - - - Added support for CI under supported Pythons using ``tox``. - - - Bug: Remove potential race condition on lock in face of interrupts - (Issue #10). - - 0.5 (2012-03-24) - ---------------- - - - Feature: added a new "invalidate()" method to allow removal of items from - the cache (issue #8). - - - Bug: LRUCache.put() could take multiple seconds on large caches (Issue #7). - - - Bug: LRUCache was not thread safe (Issue #6). - - - Bug: LRUCache.clock would waste RAM (Issue #4). - - - Bug: repeated pushing of an entry would remove other cache entries - (Issue #3). - - - Bug: LRUCache would evict entries even when not full (Issue #2). - - 0.4 (2011-09-04) - ---------------- - - - Moved to GitHub (https://github.com/repoze/repoze.lru). - - - Added Python 3.2 support. - - - Python 2.4 no longer supported. - - - Added tox.ini for easier testing. - - 0.3 (2009/06/16) - ---------------- - - - Add a thread lock around ``clear`` logic. - - 0.2 (2009/06/15) - ---------------- - - - Add a ``clear`` method. - - 0.1 (2009/06/14) - ---------------- - - - Initial release. Keywords: repoze lru cache Platform: UNKNOWN Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: License :: Repoze Public License diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/repoze.lru.egg-info/SOURCES.txt new/repoze.lru-0.7/repoze.lru.egg-info/SOURCES.txt --- old/repoze.lru-0.6/repoze.lru.egg-info/SOURCES.txt 2012-07-12 20:48:37.000000000 +0200 +++ new/repoze.lru-0.7/repoze.lru.egg-info/SOURCES.txt 2017-09-07 07:00:09.000000000 +0200 @@ -1,9 +1,10 @@ +.coveragerc .gitignore -CHANGES.txt +.travis.yml CONTRIBUTORS.txt COPYRIGHT.txt LICENSE.txt -README.txt +README.rst setup.cfg setup.py tox.ini diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/repoze.lru.egg-info/requires.txt new/repoze.lru-0.7/repoze.lru.egg-info/requires.txt --- old/repoze.lru-0.6/repoze.lru.egg-info/requires.txt 2012-07-12 20:48:37.000000000 +0200 +++ new/repoze.lru-0.7/repoze.lru.egg-info/requires.txt 2017-09-07 07:00:09.000000000 +0200 @@ -1,8 +1,7 @@ - [docs] Sphinx [testing] nose -coverage \ No newline at end of file +coverage diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/setup.cfg new/repoze.lru-0.7/setup.cfg --- old/repoze.lru-0.6/setup.cfg 2012-07-12 20:48:37.000000000 +0200 +++ new/repoze.lru-0.7/setup.cfg 2017-09-07 07:00:09.000000000 +0200 @@ -15,5 +15,4 @@ [egg_info] tag_build = tag_date = 0 -tag_svn_revision = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/setup.py new/repoze.lru-0.7/setup.py --- old/repoze.lru-0.6/setup.py 2012-07-12 20:45:17.000000000 +0200 +++ new/repoze.lru-0.7/setup.py 2017-09-07 06:59:19.000000000 +0200 @@ -1,4 +1,4 @@ -############################################################################## +# ############################################################################# # # Copyright (c) 2009 Agendaless Consulting and Contributors. # All Rights Reserved. @@ -18,8 +18,8 @@ here = os.path.abspath(os.path.dirname(__file__)) try: - README = open(os.path.join(here, 'README.txt')).read() - CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() + README = open(os.path.join(here, 'README.rst')).read() + CHANGES = open(os.path.join(here, 'CHANGESrsttxt')).read() except: README = '' CHANGES = '' @@ -27,20 +27,22 @@ testing_extras = ['nose', 'coverage'] setup(name='repoze.lru', - version='0.6', + version='0.7', description='A tiny LRU cache implementation and decorator', - long_description=README + '\n\n' + CHANGES, + long_description=README + '\n\n' + CHANGES, classifiers=[ - "Intended Audience :: Developers", - "Programming Language :: Python", - "Programming Language :: Python :: 2.6", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.2", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "License :: Repoze Public License", - ], + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "License :: Repoze Public License", + ], keywords='repoze lru cache', author="Agendaless Consulting", author_email="[email protected]", @@ -50,14 +52,14 @@ include_package_data=True, namespace_packages=['repoze'], zip_safe=False, - tests_require = [], - install_requires = [], + tests_require=[], + install_requires=[], test_suite="repoze.lru", - entry_points = """\ + entry_points="""\ """, - extras_require = { - 'testing': testing_extras, - 'docs': ['Sphinx',], + extras_require={ + 'testing': testing_extras, + 'docs': ['Sphinx', ], } ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/repoze.lru-0.6/tox.ini new/repoze.lru-0.7/tox.ini --- old/repoze.lru-0.6/tox.ini 2012-06-11 23:09:27.000000000 +0200 +++ new/repoze.lru-0.7/tox.ini 2017-09-07 06:53:22.000000000 +0200 @@ -1,22 +1,17 @@ [tox] envlist = - py26,py27,py32,pypy,cover,docs + py27,py34,py35,py36,pypy,pypy3,cover,docs [testenv] commands = - python setup.py test -q -deps = - setuptools-git - virtualenv + python setup.py -q test -q [testenv:cover] basepython = - python2.6 + python2.7 commands = - nosetests --with-xunit --with-xcoverage + nosetests --with-xunit --with-xcoverage --cover-branch --cover-min-percentage=100 deps = - setuptools-git - virtualenv nose coverage nosexcover @@ -27,7 +22,7 @@ [testenv:docs] basepython = - python2.6 + python2.7 commands = sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
