[Python-3000-checkins] r55849 - in python/branches/p3yk/Lib: collections.py test/test_collections.py
guido.van.rossum
python-3000-checkins at python.org
Sun Jun 10 03:06:43 CEST 2007
Author: guido.van.rossum
Date: Sun Jun 10 03:06:38 2007
New Revision: 55849
Modified:
python/branches/p3yk/Lib/collections.py
python/branches/p3yk/Lib/test/test_collections.py
Log:
Make sure that the magic looking for __hash__ (etc.) doesn't apply to
real subclasses of Hashable.
Modified: python/branches/p3yk/Lib/collections.py
==============================================================================
--- python/branches/p3yk/Lib/collections.py (original)
+++ python/branches/p3yk/Lib/collections.py Sun Jun 10 03:06:38 2007
@@ -1,5 +1,7 @@
__all__ = ['deque', 'defaultdict', 'NamedTuple',
'Hashable', 'Iterable', 'Iterator', 'Sized', 'Container',
+ 'Sequence', 'Set', 'Mapping',
+ 'MutableSequence', 'MutableSet', 'MutableMapping',
]
from _collections import deque, defaultdict
@@ -7,6 +9,7 @@
import sys as _sys
from abc import abstractmethod as _abstractmethod, ABCMeta as _ABCMeta
+
def NamedTuple(typename, s):
"""Returns a new subclass of tuple with named fields.
@@ -57,6 +60,7 @@
def __subclasshook__(self, subclass):
return NotImplemented
+
class Hashable(_OneTrickPony):
@_abstractmethod
@@ -65,11 +69,12 @@
@classmethod
def __subclasshook__(cls, C):
- for B in C.__mro__:
- if "__hash__" in B.__dict__:
- if B.__dict__["__hash__"]:
- return True
- break
+ if cls is Hashable:
+ for B in C.__mro__:
+ if "__hash__" in B.__dict__:
+ if B.__dict__["__hash__"]:
+ return True
+ break
return NotImplemented
@@ -82,9 +87,10 @@
@classmethod
def __subclasshook__(cls, C):
- if any("__iter__" in B.__dict__ or "__getitem__" in B.__dict__
- for B in C.__mro__):
- return True
+ if cls is Iterable:
+ if any("__iter__" in B.__dict__ or "__getitem__" in B.__dict__
+ for B in C.__mro__):
+ return True
return NotImplemented
@@ -99,8 +105,9 @@
@classmethod
def __subclasshook__(cls, C):
- if any("__next__" in B.__dict__ for B in C.__mro__):
- return True
+ if cls is Iterator:
+ if any("__next__" in B.__dict__ for B in C.__mro__):
+ return True
return NotImplemented
@@ -112,8 +119,9 @@
@classmethod
def __subclasshook__(cls, C):
- if any("__len__" in B.__dict__ for B in C.__mro__):
- return True
+ if cls is Sized:
+ if any("__len__" in B.__dict__ for B in C.__mro__):
+ return True
return NotImplemented
@@ -125,7 +133,10 @@
@classmethod
def __subclasshook__(cls, C):
- return any("__contains__" in B.__dict__ for B in C.__mro__)
+ if cls is Container:
+ if any("__contains__" in B.__dict__ for B in C.__mro__):
+ return True
+ return NotImplemented
if __name__ == '__main__':
Modified: python/branches/p3yk/Lib/test/test_collections.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_collections.py (original)
+++ python/branches/p3yk/Lib/test/test_collections.py Sun Jun 10 03:06:38 2007
@@ -79,6 +79,7 @@
def __hash__(self):
return super(H, self).__hash__()
self.assertEqual(hash(H()), 0)
+ self.failIf(issubclass(int, H))
# Check registration
class C:
__hash__ = None
@@ -87,16 +88,30 @@
self.failUnless(issubclass(C, Hashable))
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 = [bytes(), str(), unicode(),
tuple(), list(), set(), frozenset(), dict(),
]
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))
+ # Check registration
+ class C:
+ pass
+ self.failIf(issubclass(C, Iterable))
+ Iterable.register(C)
+ self.failUnless(issubclass(C, Iterable))
def test_Iterator(self):
non_samples = [None, 42, 3.14, 1j, b"", "", u"", (), [], {}, set()]
@@ -142,5 +157,6 @@
test_support.run_unittest(*test_classes)
test_support.run_doctest(CollectionsModule, verbose)
+
if __name__ == "__main__":
test_main(verbose=True)
More information about the Python-3000-checkins
mailing list