summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setup.py8
-rw-r--r--singledispatch.py18
-rw-r--r--singledispatch_helpers.py12
-rw-r--r--test_singledispatch.py63
-rw-r--r--tox.ini8
5 files changed, 72 insertions, 37 deletions
diff --git a/setup.py b/setup.py
index 338905e..58af41c 100644
--- a/setup.py
+++ b/setup.py
@@ -41,6 +41,10 @@ with codecs.open(
# We let it die a horrible tracebacking death if reading the file fails.
# We couldn't sensibly recover anyway: we need the long description.
+install_requires = ['six']
+if sys.version_info[:2] < (2, 7):
+ install_requires.append('ordereddict')
+
setup (
name = 'singledispatch',
version = '3.4.0.2',
@@ -56,9 +60,7 @@ setup (
license = 'MIT',
py_modules = ('singledispatch', 'singledispatch_helpers'),
zip_safe = True,
- install_requires = [
- 'six',
- ],
+ install_requires = install_requires,
classifiers = [
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
diff --git a/singledispatch.py b/singledispatch.py
index b428920..87603fd 100644
--- a/singledispatch.py
+++ b/singledispatch.py
@@ -148,7 +148,7 @@ def _find_impl(cls, registry):
if (t in registry and t not in cls.__mro__
and match not in cls.__mro__
and not issubclass(match, t)):
- raise RuntimeError("Ambiguous dispatch: {} or {}".format(
+ raise RuntimeError("Ambiguous dispatch: {0} or {1}".format(
match, t))
break
if t in registry:
@@ -167,7 +167,8 @@ def singledispatch(func):
"""
registry = {}
dispatch_cache = WeakKeyDictionary()
- cache_token = None
+ def ns(): pass
+ ns.cache_token = None
def dispatch(cls):
"""generic_func.dispatch(cls) -> <function implementation>
@@ -176,12 +177,11 @@ def singledispatch(func):
for the given *cls* registered on *generic_func*.
"""
- nonlocal cache_token
- if cache_token is not None:
+ if ns.cache_token is not None:
current_token = get_cache_token()
- if cache_token != current_token:
+ if ns.cache_token != current_token:
dispatch_cache.clear()
- cache_token = current_token
+ ns.cache_token = current_token
try:
impl = dispatch_cache[cls]
except KeyError:
@@ -198,12 +198,11 @@ def singledispatch(func):
Registers a new implementation for the given *cls* on a *generic_func*.
"""
- nonlocal cache_token
if func is None:
return lambda f: register(cls, f)
registry[cls] = func
- if cache_token is None and hasattr(cls, '__abstractmethods__'):
- cache_token = get_cache_token()
+ if ns.cache_token is None and hasattr(cls, '__abstractmethods__'):
+ ns.cache_token = get_cache_token()
dispatch_cache.clear()
return func
@@ -217,3 +216,4 @@ def singledispatch(func):
wrapper._clear_cache = dispatch_cache.clear
update_wrapper(wrapper, func)
return wrapper
+
diff --git a/singledispatch_helpers.py b/singledispatch_helpers.py
index 3a71831..8fcdce4 100644
--- a/singledispatch_helpers.py
+++ b/singledispatch_helpers.py
@@ -7,9 +7,17 @@ from __future__ import print_function
from __future__ import unicode_literals
from abc import ABCMeta
-from collections import MutableMapping, UserDict
+from collections import MutableMapping
import sys
try:
+ from collections import UserDict
+except ImportError:
+ from UserDict import UserDict
+try:
+ from collections import OrderedDict
+except ImportError:
+ from ordereddict import OrderedDict
+try:
from thread import get_ident
except ImportError:
try:
@@ -143,7 +151,7 @@ class ChainMap(MutableMapping):
class MappingProxyType(UserDict):
def __init__(self, data):
- super(MappingProxyType, self).__init__()
+ UserDict.__init__(self)
self.data = data
diff --git a/test_singledispatch.py b/test_singledispatch.py
index 0705cff..779cb6d 100644
--- a/test_singledispatch.py
+++ b/test_singledispatch.py
@@ -16,10 +16,25 @@ try:
except ImportError:
from singledispatch_helpers import ChainMap
collections.ChainMap = ChainMap
-import unittest
+try:
+ from collections import OrderedDict
+except ImportError:
+ from singledispatch_helpers import OrderedDict
+ collections.OrderedDict = OrderedDict
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
support = Support()
+for _prefix in ('collections.abc', '_abcoll'):
+ if _prefix in repr(collections.Container):
+ abcoll_prefix = _prefix
+ break
+else:
+ abcoll_prefix = '?'
+del _prefix
class TestSingleDispatch(unittest.TestCase):
@@ -38,7 +53,7 @@ class TestSingleDispatch(unittest.TestCase):
@functools.singledispatch
def g(obj):
return "base"
- class A:
+ class A(object):
pass
class C(A):
pass
@@ -153,7 +168,7 @@ class TestSingleDispatch(unittest.TestCase):
c = collections
d = {"a": "b"}
l = [1, 2, 3]
- s = {object(), None}
+ s = set([object(), None])
f = frozenset(s)
t = (1, 2, 3)
@functools.singledispatch
@@ -251,9 +266,10 @@ class TestSingleDispatch(unittest.TestCase):
class B(A):
def __len__(self):
return 0 # implies Sized
- @c.Container.register
+ #@c.Container.register
class C(object):
pass
+ c.Container.register(C)
class D(object):
pass # unrelated
class X(D, C, B):
@@ -288,7 +304,7 @@ class TestSingleDispatch(unittest.TestCase):
c.Set.register(O)
self.assertEqual(g(o), "set") # because c.Set is a subclass of
# c.Sized and c.Container
- class P:
+ class P(object):
pass
p = P()
self.assertEqual(g(p), "base")
@@ -299,10 +315,10 @@ class TestSingleDispatch(unittest.TestCase):
g(p)
self.assertIn(
str(re_one.exception),
- (("Ambiguous dispatch: <class 'collections.abc.Container'> "
- "or <class 'collections.abc.Iterable'>"),
- ("Ambiguous dispatch: <class 'collections.abc.Iterable'> "
- "or <class 'collections.abc.Container'>")),
+ (("Ambiguous dispatch: <class '{prefix}.Container'> "
+ "or <class '{prefix}.Iterable'>").format(prefix=abcoll_prefix),
+ ("Ambiguous dispatch: <class '{prefix}.Iterable'> "
+ "or <class '{prefix}.Container'>").format(prefix=abcoll_prefix)),
)
class Q(c.Sized):
def __len__(self):
@@ -331,10 +347,10 @@ class TestSingleDispatch(unittest.TestCase):
h(c.defaultdict(lambda: 0))
self.assertIn(
str(re_two.exception),
- (("Ambiguous dispatch: <class 'collections.abc.Container'> "
- "or <class 'collections.abc.Sized'>"),
- ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
- "or <class 'collections.abc.Container'>")),
+ (("Ambiguous dispatch: <class '{prefix}.Container'> "
+ "or <class '{prefix}.Sized'>").format(prefix=abcoll_prefix),
+ ("Ambiguous dispatch: <class '{prefix}.Sized'> "
+ "or <class '{prefix}.Container'>").format(prefix=abcoll_prefix)),
)
class R(c.defaultdict):
pass
@@ -350,7 +366,7 @@ class TestSingleDispatch(unittest.TestCase):
return "sequence"
r = R()
self.assertEqual(i(r), "sequence")
- class S:
+ class S(object):
pass
class T(S, c.Sized):
def __len__(self):
@@ -359,7 +375,7 @@ class TestSingleDispatch(unittest.TestCase):
self.assertEqual(h(t), "sized")
c.Container.register(T)
self.assertEqual(h(t), "sized") # because it's explicitly in the MRO
- class U:
+ class U(object):
def __len__(self):
return 0
u = U()
@@ -371,10 +387,10 @@ class TestSingleDispatch(unittest.TestCase):
h(u)
self.assertIn(
str(re_three.exception),
- (("Ambiguous dispatch: <class 'collections.abc.Container'> "
- "or <class 'collections.abc.Sized'>"),
- ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
- "or <class 'collections.abc.Container'>")),
+ (("Ambiguous dispatch: <class '{prefix}.Container'> "
+ "or <class '{prefix}.Sized'>").format(prefix=abcoll_prefix),
+ ("Ambiguous dispatch: <class '{prefix}.Sized'> "
+ "or <class '{prefix}.Container'>").format(prefix=abcoll_prefix)),
)
class V(c.Sized, S):
def __len__(self):
@@ -395,10 +411,13 @@ class TestSingleDispatch(unittest.TestCase):
# Sized in the MRO
def test_cache_invalidation(self):
- from collections import UserDict
+ try:
+ from collections import UserDict
+ except ImportError:
+ from UserDict import UserDict
class TracingDict(UserDict):
def __init__(self, *args, **kwargs):
- super(TracingDict, self).__init__(*args, **kwargs)
+ UserDict.__init__(self, *args, **kwargs)
self.set_ops = []
self.get_ops = []
def __getitem__(self, key):
@@ -451,7 +470,7 @@ class TestSingleDispatch(unittest.TestCase):
self.assertEqual(td.set_ops, [dict, list, dict, list])
self.assertEqual(td.data[list],
functools._find_impl(list, g.registry))
- class X:
+ class X(object):
pass
c.MutableMapping.register(X) # Will not invalidate the cache,
# not using ABCs yet.
diff --git a/tox.ini b/tox.ini
index b66e223..3026029 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,12 @@
[tox]
-envlist = py33
+envlist = py26,py27,py32,py33,pypy
[testenv]
commands =
{envbindir}/python test_singledispatch.py
+
+[testenv:py26]
+basepython = python2.6
+deps =
+ ordereddict
+ unittest2