cpython/Lib/test/test_collections.py
Christian Heimes 99170a5dbf Merged revisions 59541-59561 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r59544 | raymond.hettinger | 2007-12-18 01:13:45 +0100 (Tue, 18 Dec 2007) | 1 line

  Add more namedtuple() test cases.  Neaten the code and comments.
........
  r59545 | christian.heimes | 2007-12-18 04:38:03 +0100 (Tue, 18 Dec 2007) | 3 lines

  Fixed for #1601: IDLE not working correctly on Windows (Py30a2/IDLE30a1)

  Amaury's ideas works great. Should we build the Python core with WINVER=0x0500 and _WIN32_WINNT=0x0500, too?
........
  r59546 | christian.heimes | 2007-12-18 10:00:13 +0100 (Tue, 18 Dec 2007) | 1 line

  Make it a bit easier to test Tcl/Tk and idle from a build dir.
........
  r59547 | christian.heimes | 2007-12-18 10:12:10 +0100 (Tue, 18 Dec 2007) | 1 line

  Removed several unused files from the PCbuild9 directory. They are relics from the past.
........
  r59548 | raymond.hettinger | 2007-12-18 19:26:18 +0100 (Tue, 18 Dec 2007) | 29 lines

  Speed-up dictionary constructor by about 10%.

  New opcode, STORE_MAP saves the compiler from awkward stack manipulations
  and specializes for dicts using PyDict_SetItem instead of PyObject_SetItem.

  Old disassembly:
                0 BUILD_MAP                0
                3 DUP_TOP
                4 LOAD_CONST               1 (1)
                7 ROT_TWO
                8 LOAD_CONST               2 ('x')
               11 STORE_SUBSCR
               12 DUP_TOP
               13 LOAD_CONST               3 (2)
               16 ROT_TWO
               17 LOAD_CONST               4 ('y')
               20 STORE_SUBSCR

  New disassembly:
                0 BUILD_MAP                0
                3 LOAD_CONST               1 (1)
                6 LOAD_CONST               2 ('x')
                9 STORE_MAP
               10 LOAD_CONST               3 (2)
               13 LOAD_CONST               4 ('y')
               16 STORE_MAP
........
  r59549 | thomas.heller | 2007-12-18 20:00:34 +0100 (Tue, 18 Dec 2007) | 2 lines

  Issue #1642: Fix segfault in ctypes when trying to delete attributes.
........
  r59551 | guido.van.rossum | 2007-12-18 21:10:42 +0100 (Tue, 18 Dec 2007) | 2 lines

  Issue #1645 by Alberto Bertogli.  Fix a comment.
........
  r59553 | raymond.hettinger | 2007-12-18 22:24:09 +0100 (Tue, 18 Dec 2007) | 12 lines

  Give meaning to the oparg for BUILD_MAP:  estimated size of the dictionary.

  Allows dictionaries to be pre-sized (upto 255 elements) saving time lost
  to re-sizes with their attendant mallocs and re-insertions.

  Has zero effect on small dictionaries (5 elements or fewer), a slight
  benefit for dicts upto 22 elements (because they had to resize once
  anyway), and more benefit for dicts upto 255 elements (saving multiple
  resizes during the build-up and reducing the number of collisions on
  the first insertions).  Beyond 255 elements, there is no addional benefit.
........
  r59554 | christian.heimes | 2007-12-18 22:56:09 +0100 (Tue, 18 Dec 2007) | 1 line

  Fixed #1649: IDLE error: dictionary changed size during iteration
........
  r59557 | raymond.hettinger | 2007-12-18 23:21:27 +0100 (Tue, 18 Dec 2007) | 1 line

  Simplify and speedup _asdict() for named tuples.
........
  r59558 | christian.heimes | 2007-12-19 00:22:54 +0100 (Wed, 19 Dec 2007) | 3 lines

  Applied patch #1635: Float patch for inf and nan on Windows (and other platforms).

  The patch unifies float("inf") and repr(float("inf")) on all platforms.
........
  r59559 | raymond.hettinger | 2007-12-19 00:51:15 +0100 (Wed, 19 Dec 2007) | 1 line

  Users demand iterable input for named tuples. The author capitulates.
........
  r59560 | raymond.hettinger | 2007-12-19 01:21:06 +0100 (Wed, 19 Dec 2007) | 1 line

  Beef-up tests for dict literals
........
  r59561 | raymond.hettinger | 2007-12-19 01:27:21 +0100 (Wed, 19 Dec 2007) | 1 line

  Zap a duplicate line
........
2007-12-19 02:07:34 +00:00

325 lines
14 KiB
Python

"""Unit tests for collections.py."""
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
from collections import ByteString
class TestNamedTuple(unittest.TestCase):
def test_factory(self):
Point = namedtuple('Point', 'x y')
self.assertEqual(Point.__name__, 'Point')
self.assertEqual(Point.__doc__, 'Point(x, y)')
self.assertEqual(Point.__slots__, ())
self.assertEqual(Point.__module__, __name__)
self.assertEqual(Point.__getitem__, tuple.__getitem__)
self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
namedtuple('_', 'a b c') # Test leading underscores in a typename
def test_instance(self):
Point = namedtuple('Point', 'x y')
p = Point(11, 22)
self.assertEqual(p, Point(x=11, y=22))
self.assertEqual(p, Point(11, y=22))
self.assertEqual(p, Point(y=22, x=11))
self.assertEqual(p, Point(*(11, 22)))
self.assertEqual(p, Point(**dict(x=11, y=22)))
self.assertRaises(TypeError, Point, 1) # too few args
self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
self.assertEqual(repr(p), 'Point(x=11, y=22)')
self.assert_('__dict__' not in dir(p)) # verify instance has no dict
self.assert_('__weakref__' not in dir(p))
self.assertEqual(p, Point._cast([11, 22])) # test _cast classmethod
self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
# Verify that _fields is read-only
try:
p._fields = ('F1' ,'F2')
except AttributeError:
pass
else:
self.fail('The _fields attribute needs to be read-only')
# verify that field string can have commas
Point = namedtuple('Point', 'x, y')
p = Point(x=11, y=22)
self.assertEqual(repr(p), 'Point(x=11, y=22)')
# verify that fieldspec can be a non-string sequence
Point = namedtuple('Point', ('x', 'y'))
p = Point(x=11, y=22)
self.assertEqual(repr(p), 'Point(x=11, y=22)')
def test_tupleness(self):
Point = namedtuple('Point', 'x y')
p = Point(11, 22)
self.assert_(isinstance(p, tuple))
self.assertEqual(p, (11, 22)) # matches a real tuple
self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
self.assertEqual(list(p), [11, 22]) # coercable to a list
self.assertEqual(max(p), 22) # iterable
self.assertEqual(max(*p), 22) # star-able
x, y = p
self.assertEqual(p, (x, y)) # unpacks like a tuple
self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
self.assertRaises(IndexError, p.__getitem__, 3)
self.assertEqual(p.x, x)
self.assertEqual(p.y, y)
self.assertRaises(AttributeError, eval, 'p.z', locals())
def test_odd_sizes(self):
Zero = namedtuple('Zero', '')
self.assertEqual(Zero(), ())
self.assertEqual(Zero._cast([]), ())
self.assertEqual(repr(Zero()), 'Zero()')
self.assertEqual(Zero()._asdict(), {})
self.assertEqual(Zero()._fields, ())
Dot = namedtuple('Dot', 'd')
self.assertEqual(Dot(1), (1,))
self.assertEqual(Dot._cast([1]), (1,))
self.assertEqual(Dot(1).d, 1)
self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
self.assertEqual(Dot(1)._asdict(), {'d':1})
self.assertEqual(Dot(1)._replace(d=999), (999,))
self.assertEqual(Dot(1)._fields, ('d',))
# n = 10000
n = 254 # SyntaxError: more than 255 arguments:
import string, random
names = [''.join([random.choice(string.ascii_letters) for j in range(10)]) for i in range(n)]
Big = namedtuple('Big', names)
b = Big(*range(n))
self.assertEqual(b, tuple(range(n)))
self.assertEqual(Big._cast(range(n)), tuple(range(n)))
for pos, name in enumerate(names):
self.assertEqual(getattr(b, name), pos)
repr(b) # make sure repr() doesn't blow-up
d = b._asdict()
d_expected = dict(zip(names, range(n)))
self.assertEqual(d, d_expected)
b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
b2_expected = list(range(n))
b2_expected[1] = 999
b2_expected[-5] = 42
self.assertEqual(b2, tuple(b2_expected))
self.assertEqual(b._fields, tuple(names))
class TestOneTrickPonyABCs(unittest.TestCase):
def test_Hashable(self):
# Check some non-hashables
non_samples = [bytearray(), 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, bytes()
]
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().__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 = [bytes(), 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().__iter__()
self.assertEqual(list(I()), [])
self.failIf(issubclass(str, I))
def test_Iterator(self):
non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
for x in non_samples:
self.failIf(isinstance(x, Iterator), repr(x))
self.failIf(issubclass(type(x), Iterator), repr(type(x)))
samples = [iter(bytes()), 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 = [bytes(), 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 = [bytes(), 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,
"", b"", (), [], {}, 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:
__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, bytes, str]:
self.failUnless(isinstance(sample(), Sequence))
self.failUnless(issubclass(sample, Sequence))
self.failUnless(issubclass(str, Sequence))
def test_ByteString(self):
for sample in [bytes, bytearray]:
self.failUnless(isinstance(sample(), ByteString))
self.failUnless(issubclass(sample, ByteString))
for sample in [str, list, tuple]:
self.failIf(isinstance(sample(), ByteString))
self.failIf(issubclass(sample, ByteString))
self.failIf(isinstance(memoryview(b""), ByteString))
self.failIf(issubclass(memoryview, ByteString))
def test_MutableSequence(self):
for sample in [tuple, str, bytes]:
self.failIf(isinstance(sample(), MutableSequence))
self.failIf(issubclass(sample, MutableSequence))
for sample in [list, bytearray]:
self.failUnless(isinstance(sample(), MutableSequence))
self.failUnless(issubclass(sample, MutableSequence))
self.failIf(issubclass(str, MutableSequence))
def test_main(verbose=None):
import collections as CollectionsModule
test_classes = [TestNamedTuple, TestOneTrickPonyABCs, TestCollectionABCs]
test_support.run_unittest(*test_classes)
test_support.run_doctest(CollectionsModule, verbose)
if __name__ == "__main__":
test_main(verbose=True)