cpython: cd8b5b5b6356 (original) (raw)
Mercurial > cpython
changeset 90840:cd8b5b5b6356 3.4
Issue 8743: Improve interoperability between sets and the collections.Set abstract base class.
Raymond Hettinger python@rcn.com | |
---|---|
date | Mon, 26 May 2014 00:09:04 -0700 |
parents | ebeade01bd8e |
children | 754fcc099834 510c8dc38749 |
files | Lib/_collections_abc.py Lib/test/test_collections.py Misc/NEWS |
diffstat | 3 files changed, 181 insertions(+), 7 deletions(-)[+] [-] Lib/_collections_abc.py 23 Lib/test/test_collections.py 162 Misc/NEWS 3 |
line wrap: on
line diff
--- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -207,12 +207,17 @@ class Set(Sized, Iterable, Container): def gt(self, other): if not isinstance(other, Set): return NotImplemented
return other.__lt__(self)[](#l1.7)
return len(self) > len(other) and self.__ge__(other)[](#l1.8)
def ge(self, other): if not isinstance(other, Set): return NotImplemented
return other.__le__(self)[](#l1.13)
if len(self) < len(other):[](#l1.14)
return False[](#l1.15)
for elem in other:[](#l1.16)
if elem not in self:[](#l1.17)
return False[](#l1.18)
return True[](#l1.19)
def eq(self, other): if not isinstance(other, Set): @@ -236,6 +241,8 @@ class Set(Sized, Iterable, Container): return NotImplemented return self._from_iterable(value for value in other if value in self)
+ def isdisjoint(self, other): 'Return True if two sets have a null intersection.' for value in other: @@ -249,6 +256,8 @@ class Set(Sized, Iterable, Container): chain = (e for s in (self, other) for e in s) return self._from_iterable(chain)
+ def sub(self, other): if not isinstance(other, Set): if not isinstance(other, Iterable): @@ -257,6 +266,14 @@ class Set(Sized, Iterable, Container): return self._from_iterable(value for value in self if value not in other)
- def rsub(self, other):
if not isinstance(other, Set):[](#l1.46)
if not isinstance(other, Iterable):[](#l1.47)
return NotImplemented[](#l1.48)
other = self._from_iterable(other)[](#l1.49)
return self._from_iterable(value for value in other[](#l1.50)
if value not in self)[](#l1.51)
+ def xor(self, other): if not isinstance(other, Set): if not isinstance(other, Iterable): @@ -264,6 +281,8 @@ class Set(Sized, Iterable, Container): other = self._from_iterable(other) return (self - other) | (other - self)
+ def _hash(self): """Compute the hash value of a set.
--- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -720,14 +720,166 @@ class TestCollectionABCs(ABCTestCase): cs = MyComparableSet() ncs = MyNonComparableSet()
with self.assertRaises(TypeError):[](#l2.7)
ncs < cs[](#l2.8)
self.assertFalse(ncs < cs)[](#l2.9)
self.assertTrue(ncs <= cs)[](#l2.10)
self.assertFalse(ncs > cs)[](#l2.11)
self.assertTrue(ncs >= cs)[](#l2.12)
- def assertSameSet(self, s1, s2):
# coerce both to a real set then check equality[](#l2.15)
self.assertSetEqual(set(s1), set(s2))[](#l2.16)
- def test_Set_interoperability_with_real_sets(self):
# Issue: 8743[](#l2.19)
class ListSet(Set):[](#l2.20)
def __init__(self, elements=()):[](#l2.21)
self.data = [][](#l2.22)
for elem in elements:[](#l2.23)
if elem not in self.data:[](#l2.24)
self.data.append(elem)[](#l2.25)
def __contains__(self, elem):[](#l2.26)
return elem in self.data[](#l2.27)
def __iter__(self):[](#l2.28)
return iter(self.data)[](#l2.29)
def __len__(self):[](#l2.30)
return len(self.data)[](#l2.31)
def __repr__(self):[](#l2.32)
return 'Set({!r})'.format(self.data)[](#l2.33)
r1 = set('abc')[](#l2.35)
r2 = set('bcd')[](#l2.36)
r3 = set('abcde')[](#l2.37)
f1 = ListSet('abc')[](#l2.38)
f2 = ListSet('bcd')[](#l2.39)
f3 = ListSet('abcde')[](#l2.40)
l1 = list('abccba')[](#l2.41)
l2 = list('bcddcb')[](#l2.42)
l3 = list('abcdeedcba')[](#l2.43)
target = r1 & r2[](#l2.45)
self.assertSameSet(f1 & f2, target)[](#l2.46)
self.assertSameSet(f1 & r2, target)[](#l2.47)
self.assertSameSet(r2 & f1, target)[](#l2.48)
self.assertSameSet(f1 & l2, target)[](#l2.49)
target = r1 | r2[](#l2.51)
self.assertSameSet(f1 | f2, target)[](#l2.52)
self.assertSameSet(f1 | r2, target)[](#l2.53)
self.assertSameSet(r2 | f1, target)[](#l2.54)
self.assertSameSet(f1 | l2, target)[](#l2.55)
fwd_target = r1 - r2[](#l2.57)
rev_target = r2 - r1[](#l2.58)
self.assertSameSet(f1 - f2, fwd_target)[](#l2.59)
self.assertSameSet(f2 - f1, rev_target)[](#l2.60)
self.assertSameSet(f1 - r2, fwd_target)[](#l2.61)
self.assertSameSet(f2 - r1, rev_target)[](#l2.62)
self.assertSameSet(r1 - f2, fwd_target)[](#l2.63)
self.assertSameSet(r2 - f1, rev_target)[](#l2.64)
self.assertSameSet(f1 - l2, fwd_target)[](#l2.65)
self.assertSameSet(f2 - l1, rev_target)[](#l2.66)
target = r1 ^ r2[](#l2.68)
self.assertSameSet(f1 ^ f2, target)[](#l2.69)
self.assertSameSet(f1 ^ r2, target)[](#l2.70)
self.assertSameSet(r2 ^ f1, target)[](#l2.71)
self.assertSameSet(f1 ^ l2, target)[](#l2.72)
# Don't change the following to use assertLess or other[](#l2.74)
# "more specific" unittest assertions. The current[](#l2.75)
# assertTrue/assertFalse style makes the pattern of test[](#l2.76)
# case combinations clear and allows us to know for sure[](#l2.77)
# the exact operator being invoked.[](#l2.78)
# proper subset[](#l2.80)
self.assertTrue(f1 < f3)[](#l2.81)
self.assertFalse(f1 < f1)[](#l2.82)
self.assertFalse(f1 < f2)[](#l2.83)
self.assertTrue(r1 < f3)[](#l2.84)
self.assertFalse(r1 < f1)[](#l2.85)
self.assertFalse(r1 < f2)[](#l2.86)
self.assertTrue(r1 < r3)[](#l2.87)
self.assertFalse(r1 < r1)[](#l2.88)
self.assertFalse(r1 < r2)[](#l2.89) with self.assertRaises(TypeError):[](#l2.90)
ncs <= cs[](#l2.91)
f1 < l3[](#l2.92)
with self.assertRaises(TypeError):[](#l2.93)
f1 < l1[](#l2.94)
with self.assertRaises(TypeError):[](#l2.95)
f1 < l2[](#l2.96)
# any subset[](#l2.98)
self.assertTrue(f1 <= f3)[](#l2.99)
self.assertTrue(f1 <= f1)[](#l2.100)
self.assertFalse(f1 <= f2)[](#l2.101)
self.assertTrue(r1 <= f3)[](#l2.102)
self.assertTrue(r1 <= f1)[](#l2.103)
self.assertFalse(r1 <= f2)[](#l2.104)
self.assertTrue(r1 <= r3)[](#l2.105)
self.assertTrue(r1 <= r1)[](#l2.106)
self.assertFalse(r1 <= r2)[](#l2.107)
with self.assertRaises(TypeError):[](#l2.108)
f1 <= l3[](#l2.109)
with self.assertRaises(TypeError):[](#l2.110)
f1 <= l1[](#l2.111)
with self.assertRaises(TypeError):[](#l2.112)
f1 <= l2[](#l2.113)
# proper superset[](#l2.115)
self.assertTrue(f3 > f1)[](#l2.116)
self.assertFalse(f1 > f1)[](#l2.117)
self.assertFalse(f2 > f1)[](#l2.118)
self.assertTrue(r3 > r1)[](#l2.119)
self.assertFalse(f1 > r1)[](#l2.120)
self.assertFalse(f2 > r1)[](#l2.121)
self.assertTrue(r3 > r1)[](#l2.122)
self.assertFalse(r1 > r1)[](#l2.123)
self.assertFalse(r2 > r1)[](#l2.124)
with self.assertRaises(TypeError):[](#l2.125)
f1 > l3[](#l2.126)
with self.assertRaises(TypeError):[](#l2.127)
f1 > l1[](#l2.128) with self.assertRaises(TypeError):[](#l2.129)
cs > ncs[](#l2.130)
f1 > l2[](#l2.131)
# any superset[](#l2.133)
self.assertTrue(f3 >= f1)[](#l2.134)
self.assertTrue(f1 >= f1)[](#l2.135)
self.assertFalse(f2 >= f1)[](#l2.136)
self.assertTrue(r3 >= r1)[](#l2.137)
self.assertTrue(f1 >= r1)[](#l2.138)
self.assertFalse(f2 >= r1)[](#l2.139)
self.assertTrue(r3 >= r1)[](#l2.140)
self.assertTrue(r1 >= r1)[](#l2.141)
self.assertFalse(r2 >= r1)[](#l2.142)
with self.assertRaises(TypeError):[](#l2.143)
f1 >= l3[](#l2.144)
with self.assertRaises(TypeError):[](#l2.145)
f1 >=l1[](#l2.146) with self.assertRaises(TypeError):[](#l2.147)
cs >= ncs[](#l2.148)
f1 >= l2[](#l2.149)
# equality[](#l2.151)
self.assertTrue(f1 == f1)[](#l2.152)
self.assertTrue(r1 == f1)[](#l2.153)
self.assertTrue(f1 == r1)[](#l2.154)
self.assertFalse(f1 == f3)[](#l2.155)
self.assertFalse(r1 == f3)[](#l2.156)
self.assertFalse(f1 == r3)[](#l2.157)
self.assertFalse(f1 == l3)[](#l2.158)
self.assertFalse(f1 == l1)[](#l2.159)
self.assertFalse(f1 == l2)[](#l2.160)
# inequality[](#l2.162)
self.assertFalse(f1 != f1)[](#l2.163)
self.assertFalse(r1 != f1)[](#l2.164)
self.assertFalse(f1 != r1)[](#l2.165)
self.assertTrue(f1 != f3)[](#l2.166)
self.assertTrue(r1 != f3)[](#l2.167)
self.assertTrue(f1 != r3)[](#l2.168)
self.assertTrue(f1 != l3)[](#l2.169)
self.assertTrue(f1 != l1)[](#l2.170)
self.assertTrue(f1 != l2)[](#l2.171)
def test_Mapping(self): for sample in [dict]: