diff options
author | Timothy Edmund Crosley <timothy.crosley@gmail.com> | 2013-12-14 18:17:17 -0800 |
---|---|---|
committer | Timothy Edmund Crosley <timothy.crosley@gmail.com> | 2013-12-14 18:17:17 -0800 |
commit | 5ae96206ed544d7360ddd88086f611e0a1c2f2a5 (patch) | |
tree | 1b82a1c123c364133c773c2d56e352cd49c6a2c0 | |
parent | b42fe89fe28b6f9405fb4fc8d1272c72851eadc6 (diff) | |
parent | d3428185d881e380f3e233533d37a303bef78ec4 (diff) | |
download | pies-5ae96206ed544d7360ddd88086f611e0a1c2f2a5.tar.gz |
Merge pull request #10 from timothycrosley/feature/add-more-functools
Feature/add more functools
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | pies/ast.py | 10 | ||||
-rw-r--r-- | pies/collections.py | 5 | ||||
-rw-r--r-- | pies/functools.py | 89 | ||||
-rw-r--r-- | pies/unittest.py | 13 |
5 files changed, 118 insertions, 2 deletions
@@ -107,6 +107,7 @@ Full List: - pickle - StringIO - sys +- unittest Special Syntax (The Ugly) ====================== @@ -132,4 +133,4 @@ or email me at timothy.crosley@gmail.com. Thanks and I hope you enjoy pies! -~Timothy +~Timothy Crosley diff --git a/pies/ast.py b/pies/ast.py new file mode 100644 index 0000000..43739a1 --- /dev/null +++ b/pies/ast.py @@ -0,0 +1,10 @@ +from __future__ import absolute_import + +from ast import * + +from .version_info import PY2 + +if PY2: + Try = TryExcept +else: + TryFinally = () diff --git a/pies/collections.py b/pies/collections.py index 83e4611..a8a94cf 100644 --- a/pies/collections.py +++ b/pies/collections.py @@ -7,4 +7,7 @@ from .version_info import PY2 if PY2: from UserString import * from UserList import * - from ordereddict import OrderedDict + + import sys + if sys.version_info < (2, 7): + from ordereddict import OrderedDict diff --git a/pies/functools.py b/pies/functools.py index 29749cf..2f2c157 100644 --- a/pies/functools.py +++ b/pies/functools.py @@ -1,8 +1,97 @@ from __future__ import absolute_import +import sys from functools import * from .version_info import PY2 if PY2: reduce = reduce + +if sys.version_info < (3, 2): + try: + from threading import Lock + except ImportError: + from dummy_threading import Lock + + from .collections import OrderedDict + + def lru_cache(maxsize=100): + """Least-recently-used cache decorator. + + Taking from: https://github.com/MiCHiLU/python-functools32/blob/master/functools32/functools32.py + with slight modifications. + + If *maxsize* is set to None, the LRU features are disabled and the cache + can grow without bound. + + Arguments to the cached function must be hashable. + + View the cache statistics named tuple (hits, misses, maxsize, currsize) with + f.cache_info(). Clear the cache and statistics with f.cache_clear(). + Access the underlying function with f.__wrapped__. + + See: http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used + """ + def decorating_function(user_function, tuple=tuple, sorted=sorted, len=len, KeyError=KeyError): + hits, misses = [0], [0] + kwd_mark = (object(),) # separates positional and keyword args + lock = Lock() + + if maxsize is None: + CACHE = dict() + + @wraps(user_function) + def wrapper(*args, **kwds): + key = args + if kwds: + key += kwd_mark + tuple(sorted(kwds.items())) + try: + result = CACHE[key] + hits[0] += 1 + return result + except KeyError: + pass + result = user_function(*args, **kwds) + CACHE[key] = result + misses[0] += 1 + return result + else: + CACHE = OrderedDict() + + @wraps(user_function) + def wrapper(*args, **kwds): + key = args + if kwds: + key += kwd_mark + tuple(sorted(kwds.items())) + with lock: + cached = CACHE.get(key, None) + if cached: + del CACHE[key] + CACHE[key] = cached + hits[0] += 1 + return cached + result = user_function(*args, **kwds) + with lock: + CACHE[key] = result # record recent use of this key + misses[0] += 1 + while len(CACHE) > maxsize: + CACHE.popitem(last=False) + return result + + def cache_info(): + """Report CACHE statistics""" + with lock: + return _CacheInfo(hits[0], misses[0], maxsize, len(CACHE)) + + def cache_clear(): + """Clear the CACHE and CACHE statistics""" + with lock: + CACHE.clear() + hits[0] = misses[0] = 0 + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return wrapper + + return decorating_function diff --git a/pies/unittest.py b/pies/unittest.py new file mode 100644 index 0000000..03b130e --- /dev/null +++ b/pies/unittest.py @@ -0,0 +1,13 @@ +from __future__ import absolute_import + +import sys +from unittest import * + +if sys.version_info < (2, 7): + skip = lambda why: (lambda func: 'skip') + skipIf = lambda cond, why: (skip(why) if cond else lambda func: func) + + class TestCase(TestCase): + def assertIs(self, expr1, expr2, msg=None): + if expr1 is not expr2: + self.fail(msg or '%r is not %r' % (expr1, expr2)) |