diff --git a/boltons/setutils.py b/boltons/setutils.py index 24af024..c6b53ca 100644 --- a/boltons/setutils.py +++ b/boltons/setutils.py @@ -861,6 +861,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 @@ -894,11 +910,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 4b1c5a0..a71d39a 100644 --- a/tests/test_setutils.py +++ b/tests/test_setutils.py @@ -113,9 +113,12 @@ 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 + assert bool(cab) + assert not complement(u) # destructive testing cab ^= sab cab ^= sab