From d34e46184983c8ed25abe98a08d8831c7a8791ec Mon Sep 17 00:00:00 2001 From: Kurt Rose Date: Tue, 7 May 2019 14:01:45 -0700 Subject: [PATCH 1/2] added __rsub__ to complement-set so that expressions of form set() - complement(set()) eval correctly --- boltons/setutils.py | 16 ++++++++++++++++ tests/test_setutils.py | 1 + 2 files changed, 17 insertions(+) diff --git a/boltons/setutils.py b/boltons/setutils.py index 5ac478a..03d7b1b 100644 --- a/boltons/setutils.py +++ b/boltons/setutils.py @@ -858,6 +858,22 @@ class _ComplementSet(object): else: # + + return _ComplementSet(included=self._included.difference(inc)) + def __rsub__(self, other): + inc, exc = _norm_args_notimplemented(other) + if inc is NotImplemented: + return NotImplemented + # rsub, so the expression being evaluated is "other - self" + if self._included is None: + if exc is None: # - + + return _ComplementSet(included=inc & self._excluded) + else: # - - + return _ComplementSet(included=self._excluded - exc) + else: + if inc is None: # + - + return _ComplementSet(excluded=exc | self._included) + else: # + + + return _ComplementSet(included=inc.difference(self._included)) + def difference_update(self, other): try: self -= other diff --git a/tests/test_setutils.py b/tests/test_setutils.py index 4b1c5a0..92d5c90 100644 --- a/tests/test_setutils.py +++ b/tests/test_setutils.py @@ -113,6 +113,7 @@ def test_complement_set(): assert (sab ^ cab) == (cbc ^ sbc) assert cab - cc == sc assert cab - sab == cab + assert sab - cab == sab assert (cab ^ cbc | set('b')) == (sab | sbc) everything = complement(frozenset()) assert everything in everything # https://en.wikipedia.org/wiki/Russell%27s_paradox From d28450f34b9438b654eadb5f6efd32a145c2c63e Mon Sep 17 00:00:00 2001 From: Kurt Rose Date: Tue, 7 May 2019 14:34:01 -0700 Subject: [PATCH 2/2] proper __bool__ on complement set and tests --- boltons/setutils.py | 11 +++++++++-- tests/test_setutils.py | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/boltons/setutils.py b/boltons/setutils.py index 03d7b1b..b426da6 100644 --- a/boltons/setutils.py +++ b/boltons/setutils.py @@ -907,11 +907,18 @@ class _ComplementSet(object): return hash(self._included) ^ hash(self._excluded) def __len__(self): - if self._included: + if self._included is not None: return len(self._included) raise NotImplementedError('complemented sets have undefined length') def __iter__(self): - if self._included: + if self._included is not None: return iter(self._included) raise NotImplementedError('complemented sets have undefined contents') + + def __bool__(self): + if self._included is not None: + return bool(self._included) + return True + + __nonzero__ = __bool__ # py2 compat diff --git a/tests/test_setutils.py b/tests/test_setutils.py index 92d5c90..a71d39a 100644 --- a/tests/test_setutils.py +++ b/tests/test_setutils.py @@ -117,6 +117,8 @@ def test_complement_set(): assert (cab ^ cbc | set('b')) == (sab | sbc) everything = complement(frozenset()) assert everything in everything # https://en.wikipedia.org/wiki/Russell%27s_paradox + assert bool(cab) + assert not complement(u) # destructive testing cab ^= sab cab ^= sab