mirror of
https://github.com/python/cpython.git
synced 2025-10-22 09:23:54 +00:00

*ordering* between objects; there is only a default equality test (defined by an object being equal to itself only). Read the comment in object.c. The current implementation never uses a three-way comparison to compute a rich comparison, but it does use a rich comparison to compute a three-way comparison. I'm not quite done ripping out all the calls to PyObject_Compare/Cmp, or replacing tp_compare implementations with tp_richcompare implementations; but much of that has happened (to make most unit tests pass). The following tests still fail, because I need help deciding or understanding: test_codeop -- depends on comparing code objects test_datetime -- need Tim Peters' opinion test_marshal -- depends on comparing code objects test_mutants -- need help understanding it The problem with test_codeop and test_marshal is this: these tests compare two different code objects and expect them to be equal. Is that still a feature we'd like to support? I've temporarily removed the comparison and hash code from code objects, so they use the default (equality by pointer only) comparison. For the other two tests, run them to see for yourself. (There may be more failing test with "-u all".) A general problem with getting lots of these tests to pass is the reality that for object types that have a natural total ordering, implementing __cmp__ is much more convenient than implementing __eq__, __ne__, __lt__, and so on. Should we go back to allowing __cmp__ to provide a total ordering? Should we provide some other way to implement rich comparison with a single method override? Alex proposed a __key__() method; I've considered a __richcmp__() method. Or perhaps __cmp__() just shouldn't be killed off...
1457 lines
48 KiB
Python
1457 lines
48 KiB
Python
import unittest
|
|
from test import test_support
|
|
from weakref import proxy
|
|
import operator
|
|
import copy
|
|
import pickle
|
|
import os
|
|
from random import randrange, shuffle
|
|
import sys
|
|
|
|
class PassThru(Exception):
|
|
pass
|
|
|
|
def check_pass_thru():
|
|
raise PassThru
|
|
yield 1
|
|
|
|
class BadCmp:
|
|
def __hash__(self):
|
|
return 1
|
|
def __eq__(self, other):
|
|
raise RuntimeError
|
|
|
|
class TestJointOps(unittest.TestCase):
|
|
# Tests common to both set and frozenset
|
|
|
|
def setUp(self):
|
|
self.word = word = 'simsalabim'
|
|
self.otherword = 'madagascar'
|
|
self.letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
self.s = self.thetype(word)
|
|
self.d = dict.fromkeys(word)
|
|
|
|
def test_new_or_init(self):
|
|
self.assertRaises(TypeError, self.thetype, [], 2)
|
|
|
|
def test_uniquification(self):
|
|
actual = sorted(self.s)
|
|
expected = sorted(self.d)
|
|
self.assertEqual(actual, expected)
|
|
self.assertRaises(PassThru, self.thetype, check_pass_thru())
|
|
self.assertRaises(TypeError, self.thetype, [[]])
|
|
|
|
def test_len(self):
|
|
self.assertEqual(len(self.s), len(self.d))
|
|
|
|
def test_contains(self):
|
|
for c in self.letters:
|
|
self.assertEqual(c in self.s, c in self.d)
|
|
self.assertRaises(TypeError, self.s.__contains__, [[]])
|
|
s = self.thetype([frozenset(self.letters)])
|
|
self.assert_(self.thetype(self.letters) in s)
|
|
|
|
def test_union(self):
|
|
u = self.s.union(self.otherword)
|
|
for c in self.letters:
|
|
self.assertEqual(c in u, c in self.d or c in self.otherword)
|
|
self.assertEqual(self.s, self.thetype(self.word))
|
|
self.assertEqual(type(u), self.thetype)
|
|
self.assertRaises(PassThru, self.s.union, check_pass_thru())
|
|
self.assertRaises(TypeError, self.s.union, [[]])
|
|
for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
|
self.assertEqual(self.thetype('abcba').union(C('cdc')), set('abcd'))
|
|
self.assertEqual(self.thetype('abcba').union(C('efgfe')), set('abcefg'))
|
|
self.assertEqual(self.thetype('abcba').union(C('ccb')), set('abc'))
|
|
self.assertEqual(self.thetype('abcba').union(C('ef')), set('abcef'))
|
|
|
|
def test_or(self):
|
|
i = self.s.union(self.otherword)
|
|
self.assertEqual(self.s | set(self.otherword), i)
|
|
self.assertEqual(self.s | frozenset(self.otherword), i)
|
|
try:
|
|
self.s | self.otherword
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
self.fail("s|t did not screen-out general iterables")
|
|
|
|
def test_intersection(self):
|
|
i = self.s.intersection(self.otherword)
|
|
for c in self.letters:
|
|
self.assertEqual(c in i, c in self.d and c in self.otherword)
|
|
self.assertEqual(self.s, self.thetype(self.word))
|
|
self.assertEqual(type(i), self.thetype)
|
|
self.assertRaises(PassThru, self.s.intersection, check_pass_thru())
|
|
for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
|
self.assertEqual(self.thetype('abcba').intersection(C('cdc')), set('cc'))
|
|
self.assertEqual(self.thetype('abcba').intersection(C('efgfe')), set(''))
|
|
self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc'))
|
|
self.assertEqual(self.thetype('abcba').intersection(C('ef')), set(''))
|
|
|
|
def test_and(self):
|
|
i = self.s.intersection(self.otherword)
|
|
self.assertEqual(self.s & set(self.otherword), i)
|
|
self.assertEqual(self.s & frozenset(self.otherword), i)
|
|
try:
|
|
self.s & self.otherword
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
self.fail("s&t did not screen-out general iterables")
|
|
|
|
def test_difference(self):
|
|
i = self.s.difference(self.otherword)
|
|
for c in self.letters:
|
|
self.assertEqual(c in i, c in self.d and c not in self.otherword)
|
|
self.assertEqual(self.s, self.thetype(self.word))
|
|
self.assertEqual(type(i), self.thetype)
|
|
self.assertRaises(PassThru, self.s.difference, check_pass_thru())
|
|
self.assertRaises(TypeError, self.s.difference, [[]])
|
|
for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
|
self.assertEqual(self.thetype('abcba').difference(C('cdc')), set('ab'))
|
|
self.assertEqual(self.thetype('abcba').difference(C('efgfe')), set('abc'))
|
|
self.assertEqual(self.thetype('abcba').difference(C('ccb')), set('a'))
|
|
self.assertEqual(self.thetype('abcba').difference(C('ef')), set('abc'))
|
|
|
|
def test_sub(self):
|
|
i = self.s.difference(self.otherword)
|
|
self.assertEqual(self.s - set(self.otherword), i)
|
|
self.assertEqual(self.s - frozenset(self.otherword), i)
|
|
try:
|
|
self.s - self.otherword
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
self.fail("s-t did not screen-out general iterables")
|
|
|
|
def test_symmetric_difference(self):
|
|
i = self.s.symmetric_difference(self.otherword)
|
|
for c in self.letters:
|
|
self.assertEqual(c in i, (c in self.d) ^ (c in self.otherword))
|
|
self.assertEqual(self.s, self.thetype(self.word))
|
|
self.assertEqual(type(i), self.thetype)
|
|
self.assertRaises(PassThru, self.s.symmetric_difference, check_pass_thru())
|
|
self.assertRaises(TypeError, self.s.symmetric_difference, [[]])
|
|
for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
|
self.assertEqual(self.thetype('abcba').symmetric_difference(C('cdc')), set('abd'))
|
|
self.assertEqual(self.thetype('abcba').symmetric_difference(C('efgfe')), set('abcefg'))
|
|
self.assertEqual(self.thetype('abcba').symmetric_difference(C('ccb')), set('a'))
|
|
self.assertEqual(self.thetype('abcba').symmetric_difference(C('ef')), set('abcef'))
|
|
|
|
def test_xor(self):
|
|
i = self.s.symmetric_difference(self.otherword)
|
|
self.assertEqual(self.s ^ set(self.otherword), i)
|
|
self.assertEqual(self.s ^ frozenset(self.otherword), i)
|
|
try:
|
|
self.s ^ self.otherword
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
self.fail("s^t did not screen-out general iterables")
|
|
|
|
def test_equality(self):
|
|
self.assertEqual(self.s, set(self.word))
|
|
self.assertEqual(self.s, frozenset(self.word))
|
|
self.assertEqual(self.s == self.word, False)
|
|
self.assertNotEqual(self.s, set(self.otherword))
|
|
self.assertNotEqual(self.s, frozenset(self.otherword))
|
|
self.assertEqual(self.s != self.word, True)
|
|
|
|
def test_setOfFrozensets(self):
|
|
t = map(frozenset, ['abcdef', 'bcd', 'bdcb', 'fed', 'fedccba'])
|
|
s = self.thetype(t)
|
|
self.assertEqual(len(s), 3)
|
|
|
|
def test_compare(self):
|
|
self.assertRaises(TypeError, self.s.__cmp__, self.s)
|
|
|
|
def test_sub_and_super(self):
|
|
p, q, r = map(self.thetype, ['ab', 'abcde', 'def'])
|
|
self.assert_(p < q)
|
|
self.assert_(p <= q)
|
|
self.assert_(q <= q)
|
|
self.assert_(q > p)
|
|
self.assert_(q >= p)
|
|
self.failIf(q < r)
|
|
self.failIf(q <= r)
|
|
self.failIf(q > r)
|
|
self.failIf(q >= r)
|
|
self.assert_(set('a').issubset('abc'))
|
|
self.assert_(set('abc').issuperset('a'))
|
|
self.failIf(set('a').issubset('cbs'))
|
|
self.failIf(set('cbs').issuperset('a'))
|
|
|
|
def test_pickling(self):
|
|
for i in (0, 1, 2):
|
|
p = pickle.dumps(self.s, i)
|
|
dup = pickle.loads(p)
|
|
self.assertEqual(self.s, dup, "%s != %s" % (self.s, dup))
|
|
if type(self.s) not in (set, frozenset):
|
|
self.s.x = 10
|
|
p = pickle.dumps(self.s)
|
|
dup = pickle.loads(p)
|
|
self.assertEqual(self.s.x, dup.x)
|
|
|
|
def test_deepcopy(self):
|
|
class Tracer:
|
|
def __init__(self, value):
|
|
self.value = value
|
|
def __hash__(self):
|
|
return self.value
|
|
def __deepcopy__(self, memo=None):
|
|
return Tracer(self.value + 1)
|
|
t = Tracer(10)
|
|
s = self.thetype([t])
|
|
dup = copy.deepcopy(s)
|
|
self.assertNotEqual(id(s), id(dup))
|
|
for elem in dup:
|
|
newt = elem
|
|
self.assertNotEqual(id(t), id(newt))
|
|
self.assertEqual(t.value + 1, newt.value)
|
|
|
|
def test_gc(self):
|
|
# Create a nest of cycles to exercise overall ref count check
|
|
class A:
|
|
pass
|
|
s = set(A() for i in xrange(1000))
|
|
for elem in s:
|
|
elem.cycle = s
|
|
elem.sub = elem
|
|
elem.set = set([elem])
|
|
|
|
def test_subclass_with_custom_hash(self):
|
|
# Bug #1257731
|
|
class H(self.thetype):
|
|
def __hash__(self):
|
|
return int(id(self) & 0x7fffffff)
|
|
s=H()
|
|
f=set()
|
|
f.add(s)
|
|
self.assert_(s in f)
|
|
f.remove(s)
|
|
f.add(s)
|
|
f.discard(s)
|
|
|
|
def test_badcmp(self):
|
|
s = self.thetype([BadCmp()])
|
|
# Detect comparison errors during insertion and lookup
|
|
self.assertRaises(RuntimeError, self.thetype, [BadCmp(), BadCmp()])
|
|
self.assertRaises(RuntimeError, s.__contains__, BadCmp())
|
|
# Detect errors during mutating operations
|
|
if hasattr(s, 'add'):
|
|
self.assertRaises(RuntimeError, s.add, BadCmp())
|
|
self.assertRaises(RuntimeError, s.discard, BadCmp())
|
|
self.assertRaises(RuntimeError, s.remove, BadCmp())
|
|
|
|
class TestSet(TestJointOps):
|
|
thetype = set
|
|
|
|
def test_init(self):
|
|
s = self.thetype()
|
|
s.__init__(self.word)
|
|
self.assertEqual(s, set(self.word))
|
|
s.__init__(self.otherword)
|
|
self.assertEqual(s, set(self.otherword))
|
|
self.assertRaises(TypeError, s.__init__, s, 2);
|
|
self.assertRaises(TypeError, s.__init__, 1);
|
|
|
|
def test_constructor_identity(self):
|
|
s = self.thetype(range(3))
|
|
t = self.thetype(s)
|
|
self.assertNotEqual(id(s), id(t))
|
|
|
|
def test_hash(self):
|
|
self.assertRaises(TypeError, hash, self.s)
|
|
|
|
def test_clear(self):
|
|
self.s.clear()
|
|
self.assertEqual(self.s, set())
|
|
self.assertEqual(len(self.s), 0)
|
|
|
|
def test_copy(self):
|
|
dup = self.s.copy()
|
|
self.assertEqual(self.s, dup)
|
|
self.assertNotEqual(id(self.s), id(dup))
|
|
|
|
def test_add(self):
|
|
self.s.add('Q')
|
|
self.assert_('Q' in self.s)
|
|
dup = self.s.copy()
|
|
self.s.add('Q')
|
|
self.assertEqual(self.s, dup)
|
|
self.assertRaises(TypeError, self.s.add, [])
|
|
|
|
def test_remove(self):
|
|
self.s.remove('a')
|
|
self.assert_('a' not in self.s)
|
|
self.assertRaises(KeyError, self.s.remove, 'Q')
|
|
self.assertRaises(TypeError, self.s.remove, [])
|
|
s = self.thetype([frozenset(self.word)])
|
|
self.assert_(self.thetype(self.word) in s)
|
|
s.remove(self.thetype(self.word))
|
|
self.assert_(self.thetype(self.word) not in s)
|
|
self.assertRaises(KeyError, self.s.remove, self.thetype(self.word))
|
|
|
|
def test_discard(self):
|
|
self.s.discard('a')
|
|
self.assert_('a' not in self.s)
|
|
self.s.discard('Q')
|
|
self.assertRaises(TypeError, self.s.discard, [])
|
|
s = self.thetype([frozenset(self.word)])
|
|
self.assert_(self.thetype(self.word) in s)
|
|
s.discard(self.thetype(self.word))
|
|
self.assert_(self.thetype(self.word) not in s)
|
|
s.discard(self.thetype(self.word))
|
|
|
|
def test_pop(self):
|
|
for i in xrange(len(self.s)):
|
|
elem = self.s.pop()
|
|
self.assert_(elem not in self.s)
|
|
self.assertRaises(KeyError, self.s.pop)
|
|
|
|
def test_update(self):
|
|
retval = self.s.update(self.otherword)
|
|
self.assertEqual(retval, None)
|
|
for c in (self.word + self.otherword):
|
|
self.assert_(c in self.s)
|
|
self.assertRaises(PassThru, self.s.update, check_pass_thru())
|
|
self.assertRaises(TypeError, self.s.update, [[]])
|
|
for p, q in (('cdc', 'abcd'), ('efgfe', 'abcefg'), ('ccb', 'abc'), ('ef', 'abcef')):
|
|
for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
|
s = self.thetype('abcba')
|
|
self.assertEqual(s.update(C(p)), None)
|
|
self.assertEqual(s, set(q))
|
|
|
|
def test_ior(self):
|
|
self.s |= set(self.otherword)
|
|
for c in (self.word + self.otherword):
|
|
self.assert_(c in self.s)
|
|
|
|
def test_intersection_update(self):
|
|
retval = self.s.intersection_update(self.otherword)
|
|
self.assertEqual(retval, None)
|
|
for c in (self.word + self.otherword):
|
|
if c in self.otherword and c in self.word:
|
|
self.assert_(c in self.s)
|
|
else:
|
|
self.assert_(c not in self.s)
|
|
self.assertRaises(PassThru, self.s.intersection_update, check_pass_thru())
|
|
self.assertRaises(TypeError, self.s.intersection_update, [[]])
|
|
for p, q in (('cdc', 'c'), ('efgfe', ''), ('ccb', 'bc'), ('ef', '')):
|
|
for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
|
s = self.thetype('abcba')
|
|
self.assertEqual(s.intersection_update(C(p)), None)
|
|
self.assertEqual(s, set(q))
|
|
|
|
def test_iand(self):
|
|
self.s &= set(self.otherword)
|
|
for c in (self.word + self.otherword):
|
|
if c in self.otherword and c in self.word:
|
|
self.assert_(c in self.s)
|
|
else:
|
|
self.assert_(c not in self.s)
|
|
|
|
def test_difference_update(self):
|
|
retval = self.s.difference_update(self.otherword)
|
|
self.assertEqual(retval, None)
|
|
for c in (self.word + self.otherword):
|
|
if c in self.word and c not in self.otherword:
|
|
self.assert_(c in self.s)
|
|
else:
|
|
self.assert_(c not in self.s)
|
|
self.assertRaises(PassThru, self.s.difference_update, check_pass_thru())
|
|
self.assertRaises(TypeError, self.s.difference_update, [[]])
|
|
self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
|
|
for p, q in (('cdc', 'ab'), ('efgfe', 'abc'), ('ccb', 'a'), ('ef', 'abc')):
|
|
for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
|
s = self.thetype('abcba')
|
|
self.assertEqual(s.difference_update(C(p)), None)
|
|
self.assertEqual(s, set(q))
|
|
|
|
def test_isub(self):
|
|
self.s -= set(self.otherword)
|
|
for c in (self.word + self.otherword):
|
|
if c in self.word and c not in self.otherword:
|
|
self.assert_(c in self.s)
|
|
else:
|
|
self.assert_(c not in self.s)
|
|
|
|
def test_symmetric_difference_update(self):
|
|
retval = self.s.symmetric_difference_update(self.otherword)
|
|
self.assertEqual(retval, None)
|
|
for c in (self.word + self.otherword):
|
|
if (c in self.word) ^ (c in self.otherword):
|
|
self.assert_(c in self.s)
|
|
else:
|
|
self.assert_(c not in self.s)
|
|
self.assertRaises(PassThru, self.s.symmetric_difference_update, check_pass_thru())
|
|
self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
|
|
for p, q in (('cdc', 'abd'), ('efgfe', 'abcefg'), ('ccb', 'a'), ('ef', 'abcef')):
|
|
for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
|
s = self.thetype('abcba')
|
|
self.assertEqual(s.symmetric_difference_update(C(p)), None)
|
|
self.assertEqual(s, set(q))
|
|
|
|
def test_ixor(self):
|
|
self.s ^= set(self.otherword)
|
|
for c in (self.word + self.otherword):
|
|
if (c in self.word) ^ (c in self.otherword):
|
|
self.assert_(c in self.s)
|
|
else:
|
|
self.assert_(c not in self.s)
|
|
|
|
def test_inplace_on_self(self):
|
|
t = self.s.copy()
|
|
t |= t
|
|
self.assertEqual(t, self.s)
|
|
t &= t
|
|
self.assertEqual(t, self.s)
|
|
t -= t
|
|
self.assertEqual(t, self.thetype())
|
|
t = self.s.copy()
|
|
t ^= t
|
|
self.assertEqual(t, self.thetype())
|
|
|
|
def test_weakref(self):
|
|
s = self.thetype('gallahad')
|
|
p = proxy(s)
|
|
self.assertEqual(str(p), str(s))
|
|
s = None
|
|
self.assertRaises(ReferenceError, str, p)
|
|
|
|
# C API test only available in a debug build
|
|
if hasattr(set, "test_c_api"):
|
|
def test_c_api(self):
|
|
self.assertEqual(set('abc').test_c_api(), True)
|
|
|
|
class SetSubclass(set):
|
|
pass
|
|
|
|
class TestSetSubclass(TestSet):
|
|
thetype = SetSubclass
|
|
|
|
class TestFrozenSet(TestJointOps):
|
|
thetype = frozenset
|
|
|
|
def test_init(self):
|
|
s = self.thetype(self.word)
|
|
s.__init__(self.otherword)
|
|
self.assertEqual(s, set(self.word))
|
|
|
|
def test_singleton_empty_frozenset(self):
|
|
f = frozenset()
|
|
efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''),
|
|
frozenset(), frozenset([]), frozenset(()), frozenset(''),
|
|
frozenset(xrange(0)), frozenset(frozenset()),
|
|
frozenset(f), f]
|
|
# All of the empty frozensets should have just one id()
|
|
self.assertEqual(len(set(map(id, efs))), 1)
|
|
|
|
def test_constructor_identity(self):
|
|
s = self.thetype(range(3))
|
|
t = self.thetype(s)
|
|
self.assertEqual(id(s), id(t))
|
|
|
|
def test_hash(self):
|
|
self.assertEqual(hash(self.thetype('abcdeb')),
|
|
hash(self.thetype('ebecda')))
|
|
|
|
# make sure that all permutations give the same hash value
|
|
n = 100
|
|
seq = [randrange(n) for i in xrange(n)]
|
|
results = set()
|
|
for i in xrange(200):
|
|
shuffle(seq)
|
|
results.add(hash(self.thetype(seq)))
|
|
self.assertEqual(len(results), 1)
|
|
|
|
def test_copy(self):
|
|
dup = self.s.copy()
|
|
self.assertEqual(id(self.s), id(dup))
|
|
|
|
def test_frozen_as_dictkey(self):
|
|
seq = range(10) + list('abcdefg') + ['apple']
|
|
key1 = self.thetype(seq)
|
|
key2 = self.thetype(reversed(seq))
|
|
self.assertEqual(key1, key2)
|
|
self.assertNotEqual(id(key1), id(key2))
|
|
d = {}
|
|
d[key1] = 42
|
|
self.assertEqual(d[key2], 42)
|
|
|
|
def test_hash_caching(self):
|
|
f = self.thetype('abcdcda')
|
|
self.assertEqual(hash(f), hash(f))
|
|
|
|
def test_hash_effectiveness(self):
|
|
n = 13
|
|
hashvalues = set()
|
|
addhashvalue = hashvalues.add
|
|
elemmasks = [(i+1, 1<<i) for i in range(n)]
|
|
for i in xrange(2**n):
|
|
addhashvalue(hash(frozenset([e for e, m in elemmasks if m&i])))
|
|
self.assertEqual(len(hashvalues), 2**n)
|
|
|
|
class FrozenSetSubclass(frozenset):
|
|
pass
|
|
|
|
class TestFrozenSetSubclass(TestFrozenSet):
|
|
thetype = FrozenSetSubclass
|
|
|
|
def test_constructor_identity(self):
|
|
s = self.thetype(range(3))
|
|
t = self.thetype(s)
|
|
self.assertNotEqual(id(s), id(t))
|
|
|
|
def test_copy(self):
|
|
dup = self.s.copy()
|
|
self.assertNotEqual(id(self.s), id(dup))
|
|
|
|
def test_nested_empty_constructor(self):
|
|
s = self.thetype()
|
|
t = self.thetype(s)
|
|
self.assertEqual(s, t)
|
|
|
|
def test_singleton_empty_frozenset(self):
|
|
Frozenset = self.thetype
|
|
f = frozenset()
|
|
F = Frozenset()
|
|
efs = [Frozenset(), Frozenset([]), Frozenset(()), Frozenset(''),
|
|
Frozenset(), Frozenset([]), Frozenset(()), Frozenset(''),
|
|
Frozenset(xrange(0)), Frozenset(Frozenset()),
|
|
Frozenset(frozenset()), f, F, Frozenset(f), Frozenset(F)]
|
|
# All empty frozenset subclass instances should have different ids
|
|
self.assertEqual(len(set(map(id, efs))), len(efs))
|
|
|
|
# Tests taken from test_sets.py =============================================
|
|
|
|
empty_set = set()
|
|
|
|
#==============================================================================
|
|
|
|
class TestBasicOps(unittest.TestCase):
|
|
|
|
def test_repr(self):
|
|
if self.repr is not None:
|
|
self.assertEqual(repr(self.set), self.repr)
|
|
|
|
def test_print(self):
|
|
try:
|
|
fo = open(test_support.TESTFN, "wb")
|
|
print >> fo, self.set,
|
|
fo.close()
|
|
fo = open(test_support.TESTFN, "rb")
|
|
self.assertEqual(fo.read(), repr(self.set))
|
|
finally:
|
|
fo.close()
|
|
os.remove(test_support.TESTFN)
|
|
|
|
def test_length(self):
|
|
self.assertEqual(len(self.set), self.length)
|
|
|
|
def test_self_equality(self):
|
|
self.assertEqual(self.set, self.set)
|
|
|
|
def test_equivalent_equality(self):
|
|
self.assertEqual(self.set, self.dup)
|
|
|
|
def test_copy(self):
|
|
self.assertEqual(self.set.copy(), self.dup)
|
|
|
|
def test_self_union(self):
|
|
result = self.set | self.set
|
|
self.assertEqual(result, self.dup)
|
|
|
|
def test_empty_union(self):
|
|
result = self.set | empty_set
|
|
self.assertEqual(result, self.dup)
|
|
|
|
def test_union_empty(self):
|
|
result = empty_set | self.set
|
|
self.assertEqual(result, self.dup)
|
|
|
|
def test_self_intersection(self):
|
|
result = self.set & self.set
|
|
self.assertEqual(result, self.dup)
|
|
|
|
def test_empty_intersection(self):
|
|
result = self.set & empty_set
|
|
self.assertEqual(result, empty_set)
|
|
|
|
def test_intersection_empty(self):
|
|
result = empty_set & self.set
|
|
self.assertEqual(result, empty_set)
|
|
|
|
def test_self_symmetric_difference(self):
|
|
result = self.set ^ self.set
|
|
self.assertEqual(result, empty_set)
|
|
|
|
def checkempty_symmetric_difference(self):
|
|
result = self.set ^ empty_set
|
|
self.assertEqual(result, self.set)
|
|
|
|
def test_self_difference(self):
|
|
result = self.set - self.set
|
|
self.assertEqual(result, empty_set)
|
|
|
|
def test_empty_difference(self):
|
|
result = self.set - empty_set
|
|
self.assertEqual(result, self.dup)
|
|
|
|
def test_empty_difference_rev(self):
|
|
result = empty_set - self.set
|
|
self.assertEqual(result, empty_set)
|
|
|
|
def test_iteration(self):
|
|
for v in self.set:
|
|
self.assert_(v in self.values)
|
|
setiter = iter(self.set)
|
|
# note: __length_hint__ is an internal undocumented API,
|
|
# don't rely on it in your own programs
|
|
self.assertEqual(setiter.__length_hint__(), len(self.set))
|
|
|
|
def test_pickling(self):
|
|
p = pickle.dumps(self.set)
|
|
copy = pickle.loads(p)
|
|
self.assertEqual(self.set, copy,
|
|
"%s != %s" % (self.set, copy))
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestBasicOpsEmpty(TestBasicOps):
|
|
def setUp(self):
|
|
self.case = "empty set"
|
|
self.values = []
|
|
self.set = set(self.values)
|
|
self.dup = set(self.values)
|
|
self.length = 0
|
|
self.repr = "set([])"
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestBasicOpsSingleton(TestBasicOps):
|
|
def setUp(self):
|
|
self.case = "unit set (number)"
|
|
self.values = [3]
|
|
self.set = set(self.values)
|
|
self.dup = set(self.values)
|
|
self.length = 1
|
|
self.repr = "set([3])"
|
|
|
|
def test_in(self):
|
|
self.failUnless(3 in self.set)
|
|
|
|
def test_not_in(self):
|
|
self.failUnless(2 not in self.set)
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestBasicOpsTuple(TestBasicOps):
|
|
def setUp(self):
|
|
self.case = "unit set (tuple)"
|
|
self.values = [(0, "zero")]
|
|
self.set = set(self.values)
|
|
self.dup = set(self.values)
|
|
self.length = 1
|
|
self.repr = "set([(0, 'zero')])"
|
|
|
|
def test_in(self):
|
|
self.failUnless((0, "zero") in self.set)
|
|
|
|
def test_not_in(self):
|
|
self.failUnless(9 not in self.set)
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestBasicOpsTriple(TestBasicOps):
|
|
def setUp(self):
|
|
self.case = "triple set"
|
|
self.values = [0, "zero", operator.add]
|
|
self.set = set(self.values)
|
|
self.dup = set(self.values)
|
|
self.length = 3
|
|
self.repr = None
|
|
|
|
#==============================================================================
|
|
|
|
def baditer():
|
|
raise TypeError
|
|
yield True
|
|
|
|
def gooditer():
|
|
yield True
|
|
|
|
class TestExceptionPropagation(unittest.TestCase):
|
|
"""SF 628246: Set constructor should not trap iterator TypeErrors"""
|
|
|
|
def test_instanceWithException(self):
|
|
self.assertRaises(TypeError, set, baditer())
|
|
|
|
def test_instancesWithoutException(self):
|
|
# All of these iterables should load without exception.
|
|
set([1,2,3])
|
|
set((1,2,3))
|
|
set({'one':1, 'two':2, 'three':3})
|
|
set(xrange(3))
|
|
set('abc')
|
|
set(gooditer())
|
|
|
|
def test_changingSizeWhileIterating(self):
|
|
s = set([1,2,3])
|
|
try:
|
|
for i in s:
|
|
s.update([4])
|
|
except RuntimeError:
|
|
pass
|
|
else:
|
|
self.fail("no exception when changing size during iteration")
|
|
|
|
#==============================================================================
|
|
|
|
class TestSetOfSets(unittest.TestCase):
|
|
def test_constructor(self):
|
|
inner = frozenset([1])
|
|
outer = set([inner])
|
|
element = outer.pop()
|
|
self.assertEqual(type(element), frozenset)
|
|
outer.add(inner) # Rebuild set of sets with .add method
|
|
outer.remove(inner)
|
|
self.assertEqual(outer, set()) # Verify that remove worked
|
|
outer.discard(inner) # Absence of KeyError indicates working fine
|
|
|
|
#==============================================================================
|
|
|
|
class TestBinaryOps(unittest.TestCase):
|
|
def setUp(self):
|
|
self.set = set((2, 4, 6))
|
|
|
|
def test_eq(self): # SF bug 643115
|
|
self.assertEqual(self.set, set({2:1,4:3,6:5}))
|
|
|
|
def test_union_subset(self):
|
|
result = self.set | set([2])
|
|
self.assertEqual(result, set((2, 4, 6)))
|
|
|
|
def test_union_superset(self):
|
|
result = self.set | set([2, 4, 6, 8])
|
|
self.assertEqual(result, set([2, 4, 6, 8]))
|
|
|
|
def test_union_overlap(self):
|
|
result = self.set | set([3, 4, 5])
|
|
self.assertEqual(result, set([2, 3, 4, 5, 6]))
|
|
|
|
def test_union_non_overlap(self):
|
|
result = self.set | set([8])
|
|
self.assertEqual(result, set([2, 4, 6, 8]))
|
|
|
|
def test_intersection_subset(self):
|
|
result = self.set & set((2, 4))
|
|
self.assertEqual(result, set((2, 4)))
|
|
|
|
def test_intersection_superset(self):
|
|
result = self.set & set([2, 4, 6, 8])
|
|
self.assertEqual(result, set([2, 4, 6]))
|
|
|
|
def test_intersection_overlap(self):
|
|
result = self.set & set([3, 4, 5])
|
|
self.assertEqual(result, set([4]))
|
|
|
|
def test_intersection_non_overlap(self):
|
|
result = self.set & set([8])
|
|
self.assertEqual(result, empty_set)
|
|
|
|
def test_sym_difference_subset(self):
|
|
result = self.set ^ set((2, 4))
|
|
self.assertEqual(result, set([6]))
|
|
|
|
def test_sym_difference_superset(self):
|
|
result = self.set ^ set((2, 4, 6, 8))
|
|
self.assertEqual(result, set([8]))
|
|
|
|
def test_sym_difference_overlap(self):
|
|
result = self.set ^ set((3, 4, 5))
|
|
self.assertEqual(result, set([2, 3, 5, 6]))
|
|
|
|
def test_sym_difference_non_overlap(self):
|
|
result = self.set ^ set([8])
|
|
self.assertEqual(result, set([2, 4, 6, 8]))
|
|
|
|
def test_cmp(self):
|
|
a, b = set('a'), set('b')
|
|
self.assertRaises(TypeError, cmp, a, b)
|
|
|
|
# In py3k, this works!
|
|
self.assertRaises(TypeError, cmp, a, a)
|
|
|
|
self.assertRaises(TypeError, cmp, a, 12)
|
|
self.assertRaises(TypeError, cmp, "abc", a)
|
|
|
|
#==============================================================================
|
|
|
|
class TestUpdateOps(unittest.TestCase):
|
|
def setUp(self):
|
|
self.set = set((2, 4, 6))
|
|
|
|
def test_union_subset(self):
|
|
self.set |= set([2])
|
|
self.assertEqual(self.set, set((2, 4, 6)))
|
|
|
|
def test_union_superset(self):
|
|
self.set |= set([2, 4, 6, 8])
|
|
self.assertEqual(self.set, set([2, 4, 6, 8]))
|
|
|
|
def test_union_overlap(self):
|
|
self.set |= set([3, 4, 5])
|
|
self.assertEqual(self.set, set([2, 3, 4, 5, 6]))
|
|
|
|
def test_union_non_overlap(self):
|
|
self.set |= set([8])
|
|
self.assertEqual(self.set, set([2, 4, 6, 8]))
|
|
|
|
def test_union_method_call(self):
|
|
self.set.update(set([3, 4, 5]))
|
|
self.assertEqual(self.set, set([2, 3, 4, 5, 6]))
|
|
|
|
def test_intersection_subset(self):
|
|
self.set &= set((2, 4))
|
|
self.assertEqual(self.set, set((2, 4)))
|
|
|
|
def test_intersection_superset(self):
|
|
self.set &= set([2, 4, 6, 8])
|
|
self.assertEqual(self.set, set([2, 4, 6]))
|
|
|
|
def test_intersection_overlap(self):
|
|
self.set &= set([3, 4, 5])
|
|
self.assertEqual(self.set, set([4]))
|
|
|
|
def test_intersection_non_overlap(self):
|
|
self.set &= set([8])
|
|
self.assertEqual(self.set, empty_set)
|
|
|
|
def test_intersection_method_call(self):
|
|
self.set.intersection_update(set([3, 4, 5]))
|
|
self.assertEqual(self.set, set([4]))
|
|
|
|
def test_sym_difference_subset(self):
|
|
self.set ^= set((2, 4))
|
|
self.assertEqual(self.set, set([6]))
|
|
|
|
def test_sym_difference_superset(self):
|
|
self.set ^= set((2, 4, 6, 8))
|
|
self.assertEqual(self.set, set([8]))
|
|
|
|
def test_sym_difference_overlap(self):
|
|
self.set ^= set((3, 4, 5))
|
|
self.assertEqual(self.set, set([2, 3, 5, 6]))
|
|
|
|
def test_sym_difference_non_overlap(self):
|
|
self.set ^= set([8])
|
|
self.assertEqual(self.set, set([2, 4, 6, 8]))
|
|
|
|
def test_sym_difference_method_call(self):
|
|
self.set.symmetric_difference_update(set([3, 4, 5]))
|
|
self.assertEqual(self.set, set([2, 3, 5, 6]))
|
|
|
|
def test_difference_subset(self):
|
|
self.set -= set((2, 4))
|
|
self.assertEqual(self.set, set([6]))
|
|
|
|
def test_difference_superset(self):
|
|
self.set -= set((2, 4, 6, 8))
|
|
self.assertEqual(self.set, set([]))
|
|
|
|
def test_difference_overlap(self):
|
|
self.set -= set((3, 4, 5))
|
|
self.assertEqual(self.set, set([2, 6]))
|
|
|
|
def test_difference_non_overlap(self):
|
|
self.set -= set([8])
|
|
self.assertEqual(self.set, set([2, 4, 6]))
|
|
|
|
def test_difference_method_call(self):
|
|
self.set.difference_update(set([3, 4, 5]))
|
|
self.assertEqual(self.set, set([2, 6]))
|
|
|
|
#==============================================================================
|
|
|
|
class TestMutate(unittest.TestCase):
|
|
def setUp(self):
|
|
self.values = ["a", "b", "c"]
|
|
self.set = set(self.values)
|
|
|
|
def test_add_present(self):
|
|
self.set.add("c")
|
|
self.assertEqual(self.set, set("abc"))
|
|
|
|
def test_add_absent(self):
|
|
self.set.add("d")
|
|
self.assertEqual(self.set, set("abcd"))
|
|
|
|
def test_add_until_full(self):
|
|
tmp = set()
|
|
expected_len = 0
|
|
for v in self.values:
|
|
tmp.add(v)
|
|
expected_len += 1
|
|
self.assertEqual(len(tmp), expected_len)
|
|
self.assertEqual(tmp, self.set)
|
|
|
|
def test_remove_present(self):
|
|
self.set.remove("b")
|
|
self.assertEqual(self.set, set("ac"))
|
|
|
|
def test_remove_absent(self):
|
|
try:
|
|
self.set.remove("d")
|
|
self.fail("Removing missing element should have raised LookupError")
|
|
except LookupError:
|
|
pass
|
|
|
|
def test_remove_until_empty(self):
|
|
expected_len = len(self.set)
|
|
for v in self.values:
|
|
self.set.remove(v)
|
|
expected_len -= 1
|
|
self.assertEqual(len(self.set), expected_len)
|
|
|
|
def test_discard_present(self):
|
|
self.set.discard("c")
|
|
self.assertEqual(self.set, set("ab"))
|
|
|
|
def test_discard_absent(self):
|
|
self.set.discard("d")
|
|
self.assertEqual(self.set, set("abc"))
|
|
|
|
def test_clear(self):
|
|
self.set.clear()
|
|
self.assertEqual(len(self.set), 0)
|
|
|
|
def test_pop(self):
|
|
popped = {}
|
|
while self.set:
|
|
popped[self.set.pop()] = None
|
|
self.assertEqual(len(popped), len(self.values))
|
|
for v in self.values:
|
|
self.failUnless(v in popped)
|
|
|
|
def test_update_empty_tuple(self):
|
|
self.set.update(())
|
|
self.assertEqual(self.set, set(self.values))
|
|
|
|
def test_update_unit_tuple_overlap(self):
|
|
self.set.update(("a",))
|
|
self.assertEqual(self.set, set(self.values))
|
|
|
|
def test_update_unit_tuple_non_overlap(self):
|
|
self.set.update(("a", "z"))
|
|
self.assertEqual(self.set, set(self.values + ["z"]))
|
|
|
|
#==============================================================================
|
|
|
|
class TestSubsets(unittest.TestCase):
|
|
|
|
case2method = {"<=": "issubset",
|
|
">=": "issuperset",
|
|
}
|
|
|
|
reverse = {"==": "==",
|
|
"!=": "!=",
|
|
"<": ">",
|
|
">": "<",
|
|
"<=": ">=",
|
|
">=": "<=",
|
|
}
|
|
|
|
def test_issubset(self):
|
|
x = self.left
|
|
y = self.right
|
|
for case in "!=", "==", "<", "<=", ">", ">=":
|
|
expected = case in self.cases
|
|
# Test the binary infix spelling.
|
|
result = eval("x" + case + "y", locals())
|
|
self.assertEqual(result, expected)
|
|
# Test the "friendly" method-name spelling, if one exists.
|
|
if case in TestSubsets.case2method:
|
|
method = getattr(x, TestSubsets.case2method[case])
|
|
result = method(y)
|
|
self.assertEqual(result, expected)
|
|
|
|
# Now do the same for the operands reversed.
|
|
rcase = TestSubsets.reverse[case]
|
|
result = eval("y" + rcase + "x", locals())
|
|
self.assertEqual(result, expected)
|
|
if rcase in TestSubsets.case2method:
|
|
method = getattr(y, TestSubsets.case2method[rcase])
|
|
result = method(x)
|
|
self.assertEqual(result, expected)
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestSubsetEqualEmpty(TestSubsets):
|
|
left = set()
|
|
right = set()
|
|
name = "both empty"
|
|
cases = "==", "<=", ">="
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestSubsetEqualNonEmpty(TestSubsets):
|
|
left = set([1, 2])
|
|
right = set([1, 2])
|
|
name = "equal pair"
|
|
cases = "==", "<=", ">="
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestSubsetEmptyNonEmpty(TestSubsets):
|
|
left = set()
|
|
right = set([1, 2])
|
|
name = "one empty, one non-empty"
|
|
cases = "!=", "<", "<="
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestSubsetPartial(TestSubsets):
|
|
left = set([1])
|
|
right = set([1, 2])
|
|
name = "one a non-empty proper subset of other"
|
|
cases = "!=", "<", "<="
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestSubsetNonOverlap(TestSubsets):
|
|
left = set([1])
|
|
right = set([2])
|
|
name = "neither empty, neither contains"
|
|
cases = "!="
|
|
|
|
#==============================================================================
|
|
|
|
class TestOnlySetsInBinaryOps(unittest.TestCase):
|
|
|
|
def test_eq_ne(self):
|
|
# Unlike the others, this is testing that == and != *are* allowed.
|
|
self.assertEqual(self.other == self.set, False)
|
|
self.assertEqual(self.set == self.other, False)
|
|
self.assertEqual(self.other != self.set, True)
|
|
self.assertEqual(self.set != self.other, True)
|
|
|
|
def test_ge_gt_le_lt(self):
|
|
self.assertRaises(TypeError, lambda: self.set < self.other)
|
|
self.assertRaises(TypeError, lambda: self.set <= self.other)
|
|
self.assertRaises(TypeError, lambda: self.set > self.other)
|
|
self.assertRaises(TypeError, lambda: self.set >= self.other)
|
|
|
|
self.assertRaises(TypeError, lambda: self.other < self.set)
|
|
self.assertRaises(TypeError, lambda: self.other <= self.set)
|
|
self.assertRaises(TypeError, lambda: self.other > self.set)
|
|
self.assertRaises(TypeError, lambda: self.other >= self.set)
|
|
|
|
def test_update_operator(self):
|
|
try:
|
|
self.set |= self.other
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
self.fail("expected TypeError")
|
|
|
|
def test_update(self):
|
|
if self.otherIsIterable:
|
|
self.set.update(self.other)
|
|
else:
|
|
self.assertRaises(TypeError, self.set.update, self.other)
|
|
|
|
def test_union(self):
|
|
self.assertRaises(TypeError, lambda: self.set | self.other)
|
|
self.assertRaises(TypeError, lambda: self.other | self.set)
|
|
if self.otherIsIterable:
|
|
self.set.union(self.other)
|
|
else:
|
|
self.assertRaises(TypeError, self.set.union, self.other)
|
|
|
|
def test_intersection_update_operator(self):
|
|
try:
|
|
self.set &= self.other
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
self.fail("expected TypeError")
|
|
|
|
def test_intersection_update(self):
|
|
if self.otherIsIterable:
|
|
self.set.intersection_update(self.other)
|
|
else:
|
|
self.assertRaises(TypeError,
|
|
self.set.intersection_update,
|
|
self.other)
|
|
|
|
def test_intersection(self):
|
|
self.assertRaises(TypeError, lambda: self.set & self.other)
|
|
self.assertRaises(TypeError, lambda: self.other & self.set)
|
|
if self.otherIsIterable:
|
|
self.set.intersection(self.other)
|
|
else:
|
|
self.assertRaises(TypeError, self.set.intersection, self.other)
|
|
|
|
def test_sym_difference_update_operator(self):
|
|
try:
|
|
self.set ^= self.other
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
self.fail("expected TypeError")
|
|
|
|
def test_sym_difference_update(self):
|
|
if self.otherIsIterable:
|
|
self.set.symmetric_difference_update(self.other)
|
|
else:
|
|
self.assertRaises(TypeError,
|
|
self.set.symmetric_difference_update,
|
|
self.other)
|
|
|
|
def test_sym_difference(self):
|
|
self.assertRaises(TypeError, lambda: self.set ^ self.other)
|
|
self.assertRaises(TypeError, lambda: self.other ^ self.set)
|
|
if self.otherIsIterable:
|
|
self.set.symmetric_difference(self.other)
|
|
else:
|
|
self.assertRaises(TypeError, self.set.symmetric_difference, self.other)
|
|
|
|
def test_difference_update_operator(self):
|
|
try:
|
|
self.set -= self.other
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
self.fail("expected TypeError")
|
|
|
|
def test_difference_update(self):
|
|
if self.otherIsIterable:
|
|
self.set.difference_update(self.other)
|
|
else:
|
|
self.assertRaises(TypeError,
|
|
self.set.difference_update,
|
|
self.other)
|
|
|
|
def test_difference(self):
|
|
self.assertRaises(TypeError, lambda: self.set - self.other)
|
|
self.assertRaises(TypeError, lambda: self.other - self.set)
|
|
if self.otherIsIterable:
|
|
self.set.difference(self.other)
|
|
else:
|
|
self.assertRaises(TypeError, self.set.difference, self.other)
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestOnlySetsNumeric(TestOnlySetsInBinaryOps):
|
|
def setUp(self):
|
|
self.set = set((1, 2, 3))
|
|
self.other = 19
|
|
self.otherIsIterable = False
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestOnlySetsDict(TestOnlySetsInBinaryOps):
|
|
def setUp(self):
|
|
self.set = set((1, 2, 3))
|
|
self.other = {1:2, 3:4}
|
|
self.otherIsIterable = True
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestOnlySetsOperator(TestOnlySetsInBinaryOps):
|
|
def setUp(self):
|
|
self.set = set((1, 2, 3))
|
|
self.other = operator.add
|
|
self.otherIsIterable = False
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestOnlySetsTuple(TestOnlySetsInBinaryOps):
|
|
def setUp(self):
|
|
self.set = set((1, 2, 3))
|
|
self.other = (2, 4, 6)
|
|
self.otherIsIterable = True
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestOnlySetsString(TestOnlySetsInBinaryOps):
|
|
def setUp(self):
|
|
self.set = set((1, 2, 3))
|
|
self.other = 'abc'
|
|
self.otherIsIterable = True
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestOnlySetsGenerator(TestOnlySetsInBinaryOps):
|
|
def setUp(self):
|
|
def gen():
|
|
for i in xrange(0, 10, 2):
|
|
yield i
|
|
self.set = set((1, 2, 3))
|
|
self.other = gen()
|
|
self.otherIsIterable = True
|
|
|
|
#==============================================================================
|
|
|
|
class TestCopying(unittest.TestCase):
|
|
|
|
def test_copy(self):
|
|
dup = self.set.copy()
|
|
dup_list = sorted(dup, key=repr)
|
|
set_list = sorted(self.set, key=repr)
|
|
self.assertEqual(len(dup_list), len(set_list))
|
|
for i in range(len(dup_list)):
|
|
self.failUnless(dup_list[i] is set_list[i])
|
|
|
|
def test_deep_copy(self):
|
|
dup = copy.deepcopy(self.set)
|
|
##print type(dup), repr(dup)
|
|
dup_list = sorted(dup, key=repr)
|
|
set_list = sorted(self.set, key=repr)
|
|
self.assertEqual(len(dup_list), len(set_list))
|
|
for i in range(len(dup_list)):
|
|
self.assertEqual(dup_list[i], set_list[i])
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestCopyingEmpty(TestCopying):
|
|
def setUp(self):
|
|
self.set = set()
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestCopyingSingleton(TestCopying):
|
|
def setUp(self):
|
|
self.set = set(["hello"])
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestCopyingTriple(TestCopying):
|
|
def setUp(self):
|
|
self.set = set(["zero", 0, None])
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestCopyingTuple(TestCopying):
|
|
def setUp(self):
|
|
self.set = set([(1, 2)])
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
class TestCopyingNested(TestCopying):
|
|
def setUp(self):
|
|
self.set = set([((1, 2), (3, 4))])
|
|
|
|
#==============================================================================
|
|
|
|
class TestIdentities(unittest.TestCase):
|
|
def setUp(self):
|
|
self.a = set('abracadabra')
|
|
self.b = set('alacazam')
|
|
|
|
def test_binopsVsSubsets(self):
|
|
a, b = self.a, self.b
|
|
self.assert_(a - b < a)
|
|
self.assert_(b - a < b)
|
|
self.assert_(a & b < a)
|
|
self.assert_(a & b < b)
|
|
self.assert_(a | b > a)
|
|
self.assert_(a | b > b)
|
|
self.assert_(a ^ b < a | b)
|
|
|
|
def test_commutativity(self):
|
|
a, b = self.a, self.b
|
|
self.assertEqual(a&b, b&a)
|
|
self.assertEqual(a|b, b|a)
|
|
self.assertEqual(a^b, b^a)
|
|
if a != b:
|
|
self.assertNotEqual(a-b, b-a)
|
|
|
|
def test_summations(self):
|
|
# check that sums of parts equal the whole
|
|
a, b = self.a, self.b
|
|
self.assertEqual((a-b)|(a&b)|(b-a), a|b)
|
|
self.assertEqual((a&b)|(a^b), a|b)
|
|
self.assertEqual(a|(b-a), a|b)
|
|
self.assertEqual((a-b)|b, a|b)
|
|
self.assertEqual((a-b)|(a&b), a)
|
|
self.assertEqual((b-a)|(a&b), b)
|
|
self.assertEqual((a-b)|(b-a), a^b)
|
|
|
|
def test_exclusion(self):
|
|
# check that inverse operations show non-overlap
|
|
a, b, zero = self.a, self.b, set()
|
|
self.assertEqual((a-b)&b, zero)
|
|
self.assertEqual((b-a)&a, zero)
|
|
self.assertEqual((a&b)&(a^b), zero)
|
|
|
|
# Tests derived from test_itertools.py =======================================
|
|
|
|
def R(seqn):
|
|
'Regular generator'
|
|
for i in seqn:
|
|
yield i
|
|
|
|
class G:
|
|
'Sequence using __getitem__'
|
|
def __init__(self, seqn):
|
|
self.seqn = seqn
|
|
def __getitem__(self, i):
|
|
return self.seqn[i]
|
|
|
|
class I:
|
|
'Sequence using iterator protocol'
|
|
def __init__(self, seqn):
|
|
self.seqn = seqn
|
|
self.i = 0
|
|
def __iter__(self):
|
|
return self
|
|
def next(self):
|
|
if self.i >= len(self.seqn): raise StopIteration
|
|
v = self.seqn[self.i]
|
|
self.i += 1
|
|
return v
|
|
|
|
class Ig:
|
|
'Sequence using iterator protocol defined with a generator'
|
|
def __init__(self, seqn):
|
|
self.seqn = seqn
|
|
self.i = 0
|
|
def __iter__(self):
|
|
for val in self.seqn:
|
|
yield val
|
|
|
|
class X:
|
|
'Missing __getitem__ and __iter__'
|
|
def __init__(self, seqn):
|
|
self.seqn = seqn
|
|
self.i = 0
|
|
def next(self):
|
|
if self.i >= len(self.seqn): raise StopIteration
|
|
v = self.seqn[self.i]
|
|
self.i += 1
|
|
return v
|
|
|
|
class N:
|
|
'Iterator missing next()'
|
|
def __init__(self, seqn):
|
|
self.seqn = seqn
|
|
self.i = 0
|
|
def __iter__(self):
|
|
return self
|
|
|
|
class E:
|
|
'Test propagation of exceptions'
|
|
def __init__(self, seqn):
|
|
self.seqn = seqn
|
|
self.i = 0
|
|
def __iter__(self):
|
|
return self
|
|
def next(self):
|
|
3 // 0
|
|
|
|
class S:
|
|
'Test immediate stop'
|
|
def __init__(self, seqn):
|
|
pass
|
|
def __iter__(self):
|
|
return self
|
|
def next(self):
|
|
raise StopIteration
|
|
|
|
from itertools import chain, imap
|
|
def L(seqn):
|
|
'Test multiple tiers of iterators'
|
|
return chain(imap(lambda x:x, R(Ig(G(seqn)))))
|
|
|
|
class TestVariousIteratorArgs(unittest.TestCase):
|
|
|
|
def test_constructor(self):
|
|
for cons in (set, frozenset):
|
|
for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)):
|
|
for g in (G, I, Ig, S, L, R):
|
|
self.assertEqual(sorted(cons(g(s)), key=repr), sorted(g(s), key=repr))
|
|
self.assertRaises(TypeError, cons , X(s))
|
|
self.assertRaises(TypeError, cons , N(s))
|
|
self.assertRaises(ZeroDivisionError, cons , E(s))
|
|
|
|
def test_inline_methods(self):
|
|
s = set('november')
|
|
for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'):
|
|
for meth in (s.union, s.intersection, s.difference, s.symmetric_difference):
|
|
for g in (G, I, Ig, L, R):
|
|
expected = meth(data)
|
|
actual = meth(G(data))
|
|
self.assertEqual(sorted(actual, key=repr), sorted(expected, key=repr))
|
|
self.assertRaises(TypeError, meth, X(s))
|
|
self.assertRaises(TypeError, meth, N(s))
|
|
self.assertRaises(ZeroDivisionError, meth, E(s))
|
|
|
|
def test_inplace_methods(self):
|
|
for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'):
|
|
for methname in ('update', 'intersection_update',
|
|
'difference_update', 'symmetric_difference_update'):
|
|
for g in (G, I, Ig, S, L, R):
|
|
s = set('january')
|
|
t = s.copy()
|
|
getattr(s, methname)(list(g(data)))
|
|
getattr(t, methname)(g(data))
|
|
self.assertEqual(sorted(s, key=repr), sorted(t, key=repr))
|
|
|
|
self.assertRaises(TypeError, getattr(set('january'), methname), X(data))
|
|
self.assertRaises(TypeError, getattr(set('january'), methname), N(data))
|
|
self.assertRaises(ZeroDivisionError, getattr(set('january'), methname), E(data))
|
|
|
|
#==============================================================================
|
|
|
|
def test_main(verbose=None):
|
|
from test import test_sets
|
|
test_classes = (
|
|
TestSet,
|
|
TestSetSubclass,
|
|
TestFrozenSet,
|
|
TestFrozenSetSubclass,
|
|
TestSetOfSets,
|
|
TestExceptionPropagation,
|
|
TestBasicOpsEmpty,
|
|
TestBasicOpsSingleton,
|
|
TestBasicOpsTuple,
|
|
TestBasicOpsTriple,
|
|
TestBinaryOps,
|
|
TestUpdateOps,
|
|
TestMutate,
|
|
TestSubsetEqualEmpty,
|
|
TestSubsetEqualNonEmpty,
|
|
TestSubsetEmptyNonEmpty,
|
|
TestSubsetPartial,
|
|
TestSubsetNonOverlap,
|
|
TestOnlySetsNumeric,
|
|
TestOnlySetsDict,
|
|
TestOnlySetsOperator,
|
|
TestOnlySetsTuple,
|
|
TestOnlySetsString,
|
|
TestOnlySetsGenerator,
|
|
TestCopyingEmpty,
|
|
TestCopyingSingleton,
|
|
TestCopyingTriple,
|
|
TestCopyingTuple,
|
|
TestCopyingNested,
|
|
TestIdentities,
|
|
TestVariousIteratorArgs,
|
|
)
|
|
|
|
test_support.run_unittest(*test_classes)
|
|
|
|
# verify reference counting
|
|
if verbose and hasattr(sys, "gettotalrefcount"):
|
|
import gc
|
|
counts = [None] * 5
|
|
for i in xrange(len(counts)):
|
|
test_support.run_unittest(*test_classes)
|
|
gc.collect()
|
|
counts[i] = sys.gettotalrefcount()
|
|
print counts
|
|
|
|
if __name__ == "__main__":
|
|
test_main(verbose=True)
|