changeset: 92768:e70b2b8ffe02 branch: counter_lt tag: tip parent: 88635:9bbb64e91913 user: Ram Rachum date: Fri Oct 03 12:02:02 2014 +0300 summary: Counter comparison diff -r 9bbb64e91913 -r e70b2b8ffe02 Lib/collections/__init__.py --- a/Lib/collections/__init__.py Wed Jan 22 03:05:49 2014 -0800 +++ b/Lib/collections/__init__.py Fri Oct 03 12:02:02 2014 +0300 @@ -751,6 +751,73 @@ if other_count < count: self[elem] = other_count return self._keep_positive() + + + def __lt__(self, other): + if not isinstance(other, Mapping): + raise TypeError("Can't compare %s to non-mapping %s" % + (type(self).__name__, type(other).__name__)) + found_strict_difference = False # Until challenged. + for element, count in self.items(): + try: + other_count = other[element] + except KeyError: + if count > 0: + return False + if not (count <= other_count): + return False + elif count < other_count: + found_strict_difference = True + + return found_strict_difference + + def __le__(self, other): + if not isinstance(other, Mapping): + raise TypeError("Can't compare %s to non-mapping %s" % + (type(self).__name__, type(other).__name__)) + for element, count in self.items(): + try: + other_count = other[element] + except KeyError: + if count > 0: + return False + if not (count <= other_count): + return False + + return True + + def __gt__(self, other): + if not isinstance(other, Mapping): + raise TypeError("Can't compare %s to non-mapping %s" % + (type(self).__name__, type(other).__name__)) + found_strict_difference = False # Until challenged. + for element, count in self.items(): + try: + other_count = other[element] + except KeyError: + continue + if not (count >= other_count): + return False + elif count > other_count: + found_strict_difference = True + + return found_strict_difference + + def __ge__(self, other): + if not isinstance(other, Mapping): + raise TypeError("Can't compare %s to non-mapping %s" % + (type(self).__name__, type(other).__name__)) + for element, count in self.items(): + try: + other_count = other[element] + except KeyError: + continue + if not (count >= other_count): + return False + + return True + + ######################################################################## diff -r 9bbb64e91913 -r e70b2b8ffe02 Lib/test/test_collections.py --- a/Lib/test/test_collections.py Wed Jan 22 03:05:49 2014 -0800 +++ b/Lib/test/test_collections.py Fri Oct 03 12:02:02 2014 +0300 @@ -1084,6 +1084,51 @@ c = CounterSubclassWithGet('abracadabra') self.assertTrue(c.called) self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 }) + + def test_comparison(self): + import decimal + + counter_0 = Counter('c') + counter_1 = Counter('abc') + counter_2 = Counter('aabc') + counter_3 = Counter('abbc') + counter_4 = Counter('aabbcc') + d = {'a': 1.5, 'b': 1.0, 'c': decimal.Decimal('1.0'), + 'd': float('inf'),} + + bad_d = {'a': 'a'} + + hierarchy = ( + (d, {counter_1}), + (counter_4, {d, counter_3, counter_2, counter_1, counter_0}), + (counter_3, {counter_1, counter_0}), + (counter_2, {counter_1, counter_0}), + (counter_1, {counter_0}), + (counter_0, set()), + ) + + for item, smaller_items in hierarchy: + if not isinstance(item, Counter): + continue + for smaller_item in smaller_items: + assert not item <= smaller_item + assert not item < smaller_item + assert item >= smaller_item + assert item > smaller_item + assert item != smaller_item + not_smaller_items = [item for item in zip(*hierarchy)[0] if + item not in smaller_item] + for not_smaller_item in not_smaller_items: + assert not item < smaller_item + + with self.assertRaises(TypeError): + item <= bad_d + with self.assertRaises(TypeError): + item < bad_d + with self.assertRaises(TypeError): + item >= bad_d + with self.assertRaises(TypeError): + item > bad_d ################################################################################