diff options
author | Guido van Rossum <guido@python.org> | 2007-11-22 00:55:51 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2007-11-22 00:55:51 (GMT) |
commit | 64c06e327d48150fc548cf18a4a7ae0b890e69fa (patch) | |
tree | daf53ab57c369a3d92c5a9deafc41df2ccd96127 /Lib/test | |
parent | cc7f26bf207ee17e2c1b3e6545e145942aff612d (diff) | |
download | cpython-64c06e327d48150fc548cf18a4a7ae0b890e69fa.zip cpython-64c06e327d48150fc548cf18a4a7ae0b890e69fa.tar.gz cpython-64c06e327d48150fc548cf18a4a7ae0b890e69fa.tar.bz2 |
Backport of _abccoll.py by Benjamin Arangueren, issue 1383.
With some changes of my own thrown in (e.g. backport of r58107).
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/mapping_tests.py | 4 | ||||
-rwxr-xr-x | Lib/test/regrtest.py | 23 | ||||
-rw-r--r-- | Lib/test/test_abc.py | 14 | ||||
-rw-r--r-- | Lib/test/test_collections.py | 186 | ||||
-rw-r--r-- | Lib/test/test_dict.py | 4 |
5 files changed, 225 insertions, 6 deletions
diff --git a/Lib/test/mapping_tests.py b/Lib/test/mapping_tests.py index 4b0f797..c6857ab 100644 --- a/Lib/test/mapping_tests.py +++ b/Lib/test/mapping_tests.py @@ -557,6 +557,8 @@ class TestHashMappingProtocol(TestMappingProtocol): class BadEq(object): def __eq__(self, other): raise Exc() + def __hash__(self): + return 24 d = self._empty_mapping() d[BadEq()] = 42 @@ -642,6 +644,8 @@ class TestHashMappingProtocol(TestMappingProtocol): class BadCmp(object): def __eq__(self, other): raise Exc() + def __hash__(self): + return 42 d1 = self._full_mapping({BadCmp(): 1}) d2 = self._full_mapping({1: 1}) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index 7973b23..9694e2a 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -648,7 +648,7 @@ def cleanup_test_droppings(testname, verbose): def dash_R(the_module, test, indirect_test, huntrleaks): # This code is hackish and inelegant, but it seems to do the job. - import copy_reg + import copy_reg, _abcoll if not hasattr(sys, 'gettotalrefcount'): raise Exception("Tracking reference leaks requires a debug build " @@ -658,6 +658,12 @@ def dash_R(the_module, test, indirect_test, huntrleaks): fs = warnings.filters[:] ps = copy_reg.dispatch_table.copy() pic = sys.path_importer_cache.copy() + abcs = {} + for abc in [getattr(_abcoll, a) for a in _abcoll.__all__]: + for obj in abc.__subclasses__() + [abc]: + abcs[obj] = obj._abc_registry.copy() + + print >> sys.stderr, abcs if indirect_test: def run_the_test(): @@ -671,12 +677,12 @@ def dash_R(the_module, test, indirect_test, huntrleaks): repcount = nwarmup + ntracked print >> sys.stderr, "beginning", repcount, "repetitions" print >> sys.stderr, ("1234567890"*(repcount//10 + 1))[:repcount] - dash_R_cleanup(fs, ps, pic) + dash_R_cleanup(fs, ps, pic, abcs) for i in range(repcount): rc = sys.gettotalrefcount() run_the_test() sys.stderr.write('.') - dash_R_cleanup(fs, ps, pic) + dash_R_cleanup(fs, ps, pic, abcs) if i >= nwarmup: deltas.append(sys.gettotalrefcount() - rc - 2) print >> sys.stderr @@ -687,11 +693,11 @@ def dash_R(the_module, test, indirect_test, huntrleaks): print >> refrep, msg refrep.close() -def dash_R_cleanup(fs, ps, pic): +def dash_R_cleanup(fs, ps, pic, abcs): import gc, copy_reg import _strptime, linecache, dircache import urlparse, urllib, urllib2, mimetypes, doctest - import struct, filecmp + import struct, filecmp, _abcoll from distutils.dir_util import _path_created # Restore some original values. @@ -701,6 +707,13 @@ def dash_R_cleanup(fs, ps, pic): sys.path_importer_cache.clear() sys.path_importer_cache.update(pic) + # Clear ABC registries, restoring previously saved ABC registries. + for abc in [getattr(_abcoll, a) for a in _abcoll.__all__]: + for obj in abc.__subclasses__() + [abc]: + obj._abc_registry = abcs.get(obj, {}).copy() + obj._abc_cache.clear() + obj._abc_negative_cache.clear() + # Clear assorted module caches. _path_created.clear() re.purge() diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py index 3fd9bde..c760356 100644 --- a/Lib/test/test_abc.py +++ b/Lib/test/test_abc.py @@ -133,6 +133,20 @@ class TestABC(unittest.TestCase): self.failUnless(issubclass(MyInt, A)) self.failUnless(isinstance(42, A)) + def test_all_new_methods_are_called(self): + class A: + __metaclass__ = abc.ABCMeta + class B: + counter = 0 + def __new__(cls): + B.counter += 1 + return super(B, cls).__new__(cls) + class C(A, B): + pass + self.assertEqual(B.counter, 0) + C() + self.assertEqual(B.counter, 1) + def test_main(): test_support.run_unittest(TestABC) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 7c5b2dc..52bae9a 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1,6 +1,12 @@ import unittest from test import test_support from collections import namedtuple +from collections import Hashable, Iterable, Iterator +from collections import Sized, Container, Callable +from collections import Set, MutableSet +from collections import Mapping, MutableMapping +from collections import Sequence, MutableSequence + class TestNamedTuple(unittest.TestCase): @@ -86,9 +92,187 @@ class TestNamedTuple(unittest.TestCase): Dot = namedtuple('Dot', 'd') self.assertEqual(Dot(1), (1,)) + +class TestOneTrickPonyABCs(unittest.TestCase): + + def test_Hashable(self): + # Check some non-hashables + non_samples = [list(), set(), dict()] + for x in non_samples: + self.failIf(isinstance(x, Hashable), repr(x)) + self.failIf(issubclass(type(x), Hashable), repr(type(x))) + # Check some hashables + samples = [None, + int(), float(), complex(), + str(), + tuple(), frozenset(), + int, list, object, type, + ] + for x in samples: + self.failUnless(isinstance(x, Hashable), repr(x)) + self.failUnless(issubclass(type(x), Hashable), repr(type(x))) + self.assertRaises(TypeError, Hashable) + # Check direct subclassing + class H(Hashable): + def __hash__(self): + return super(H, self).__hash__() + self.assertEqual(hash(H()), 0) + self.failIf(issubclass(int, H)) + + def test_Iterable(self): + # Check some non-iterables + non_samples = [None, 42, 3.14, 1j] + for x in non_samples: + self.failIf(isinstance(x, Iterable), repr(x)) + self.failIf(issubclass(type(x), Iterable), repr(type(x))) + # Check some iterables + samples = [str(), + tuple(), list(), set(), frozenset(), dict(), + dict().keys(), dict().items(), dict().values(), + (lambda: (yield))(), + (x for x in []), + ] + for x in samples: + self.failUnless(isinstance(x, Iterable), repr(x)) + self.failUnless(issubclass(type(x), Iterable), repr(type(x))) + # Check direct subclassing + class I(Iterable): + def __iter__(self): + return super(I, self).__iter__() + self.assertEqual(list(I()), []) + self.failIf(issubclass(str, I)) + + def test_Iterator(self): + non_samples = [None, 42, 3.14, 1j, "".encode('ascii'), "", (), [], + {}, set()] + for x in non_samples: + self.failIf(isinstance(x, Iterator), repr(x)) + self.failIf(issubclass(type(x), Iterator), repr(type(x))) + samples = [iter(str()), + iter(tuple()), iter(list()), iter(dict()), + iter(set()), iter(frozenset()), + iter(dict().keys()), iter(dict().items()), + iter(dict().values()), + (lambda: (yield))(), + (x for x in []), + ] + for x in samples: + self.failUnless(isinstance(x, Iterator), repr(x)) + self.failUnless(issubclass(type(x), Iterator), repr(type(x))) + + def test_Sized(self): + non_samples = [None, 42, 3.14, 1j, + (lambda: (yield))(), + (x for x in []), + ] + for x in non_samples: + self.failIf(isinstance(x, Sized), repr(x)) + self.failIf(issubclass(type(x), Sized), repr(type(x))) + samples = [str(), + tuple(), list(), set(), frozenset(), dict(), + dict().keys(), dict().items(), dict().values(), + ] + for x in samples: + self.failUnless(isinstance(x, Sized), repr(x)) + self.failUnless(issubclass(type(x), Sized), repr(type(x))) + + def test_Container(self): + non_samples = [None, 42, 3.14, 1j, + (lambda: (yield))(), + (x for x in []), + ] + for x in non_samples: + self.failIf(isinstance(x, Container), repr(x)) + self.failIf(issubclass(type(x), Container), repr(type(x))) + samples = [str(), + tuple(), list(), set(), frozenset(), dict(), + dict().keys(), dict().items(), + ] + for x in samples: + self.failUnless(isinstance(x, Container), repr(x)) + self.failUnless(issubclass(type(x), Container), repr(type(x))) + + def test_Callable(self): + non_samples = [None, 42, 3.14, 1j, + "", "".encode('ascii'), (), [], {}, set(), + (lambda: (yield))(), + (x for x in []), + ] + for x in non_samples: + self.failIf(isinstance(x, Callable), repr(x)) + self.failIf(issubclass(type(x), Callable), repr(type(x))) + samples = [lambda: None, + type, int, object, + len, + list.append, [].append, + ] + for x in samples: + self.failUnless(isinstance(x, Callable), repr(x)) + self.failUnless(issubclass(type(x), Callable), repr(type(x))) + + def test_direct_subclassing(self): + for B in Hashable, Iterable, Iterator, Sized, Container, Callable: + class C(B): + pass + self.failUnless(issubclass(C, B)) + self.failIf(issubclass(int, C)) + + def test_registration(self): + for B in Hashable, Iterable, Iterator, Sized, Container, Callable: + class C: + __metaclass__ = type + __hash__ = None # Make sure it isn't hashable by default + self.failIf(issubclass(C, B), B.__name__) + B.register(C) + self.failUnless(issubclass(C, B)) + + +class TestCollectionABCs(unittest.TestCase): + + # XXX For now, we only test some virtual inheritance properties. + # We should also test the proper behavior of the collection ABCs + # as real base classes or mix-in classes. + + def test_Set(self): + for sample in [set, frozenset]: + self.failUnless(isinstance(sample(), Set)) + self.failUnless(issubclass(sample, Set)) + + def test_MutableSet(self): + self.failUnless(isinstance(set(), MutableSet)) + self.failUnless(issubclass(set, MutableSet)) + self.failIf(isinstance(frozenset(), MutableSet)) + self.failIf(issubclass(frozenset, MutableSet)) + + def test_Mapping(self): + for sample in [dict]: + self.failUnless(isinstance(sample(), Mapping)) + self.failUnless(issubclass(sample, Mapping)) + + def test_MutableMapping(self): + for sample in [dict]: + self.failUnless(isinstance(sample(), MutableMapping)) + self.failUnless(issubclass(sample, MutableMapping)) + + def test_Sequence(self): + for sample in [tuple, list, str]: + self.failUnless(isinstance(sample(), Sequence)) + self.failUnless(issubclass(sample, Sequence)) + self.failUnless(issubclass(basestring, Sequence)) + + def test_MutableSequence(self): + for sample in [tuple, str]: + self.failIf(isinstance(sample(), MutableSequence)) + self.failIf(issubclass(sample, MutableSequence)) + for sample in [list]: + self.failUnless(isinstance(sample(), MutableSequence)) + self.failUnless(issubclass(sample, MutableSequence)) + self.failIf(issubclass(basestring, MutableSequence)) + + def test_main(verbose=None): import collections as CollectionsModule - test_classes = [TestNamedTuple] + test_classes = [TestNamedTuple, TestOneTrickPonyABCs, TestCollectionABCs] test_support.run_unittest(*test_classes) test_support.run_doctest(CollectionsModule, verbose) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 9f049ad..342e775 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -86,6 +86,8 @@ class DictTest(unittest.TestCase): class BadEq(object): def __eq__(self, other): raise Exc() + def __hash__(self): + return 24 d = {} d[BadEq()] = 42 @@ -397,6 +399,8 @@ class DictTest(unittest.TestCase): class BadCmp(object): def __eq__(self, other): raise Exc() + def __hash__(self): + return 42 d1 = {BadCmp(): 1} d2 = {1: 1} |