summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Edmund Crosley <timothy.crosley@gmail.com>2013-12-14 18:17:17 -0800
committerTimothy Edmund Crosley <timothy.crosley@gmail.com>2013-12-14 18:17:17 -0800
commit5ae96206ed544d7360ddd88086f611e0a1c2f2a5 (patch)
tree1b82a1c123c364133c773c2d56e352cd49c6a2c0
parentb42fe89fe28b6f9405fb4fc8d1272c72851eadc6 (diff)
parentd3428185d881e380f3e233533d37a303bef78ec4 (diff)
downloadpies-5ae96206ed544d7360ddd88086f611e0a1c2f2a5.tar.gz
Merge pull request #10 from timothycrosley/feature/add-more-functools
Feature/add more functools
-rw-r--r--README.md3
-rw-r--r--pies/ast.py10
-rw-r--r--pies/collections.py5
-rw-r--r--pies/functools.py89
-rw-r--r--pies/unittest.py13
5 files changed, 118 insertions, 2 deletions
diff --git a/README.md b/README.md
index 2417ba1..e8aaa40 100644
--- a/README.md
+++ b/README.md
@@ -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))