From 8bb44f34441de2e2949a1021c25a4378a9a5c0b4 Mon Sep 17 00:00:00 2001 From: Chris Withers Date: Sun, 26 May 2013 21:20:40 +0100 Subject: [PATCH 1/5] more useful error message when comparing ranges with non-ranges --- lib/_range.py | 2 ++ tests/test_types_extras.py | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/_range.py b/lib/_range.py index 306f1f73..5803a8ab 100644 --- a/lib/_range.py +++ b/lib/_range.py @@ -121,6 +121,8 @@ class Range(object): return self._bounds is not None def __eq__(self, other): + if not isinstance(other, self.__class__): + raise TypeError('Cannot compare %r with %r' % (self, other)) return (self._lower == other._lower and self._upper == other._upper and self._bounds == other._bounds) diff --git a/tests/test_types_extras.py b/tests/test_types_extras.py index 98fbbadf..48074d7b 100755 --- a/tests/test_types_extras.py +++ b/tests/test_types_extras.py @@ -1212,6 +1212,16 @@ class RangeTestCase(unittest.TestCase): assert_not_equal(Range(10, 20), Range(11, 20)) assert_not_equal(Range(10, 20, '[)'), Range(10, 20, '[]')) + def test_eq_wrong_type(self): + from psycopg2.extras import Range + try: + Range(10, 20)==() + except TypeError, e: + self.assertEqual( + str(e), "Cannot compare Range(10, 20, '[)') with ()") + else: + self.fail('No exception raised') + def test_not_ordered(self): from psycopg2.extras import Range self.assertRaises(TypeError, lambda: Range(empty=True) < Range(0,4)) From b6a9e0ffaf4748d3019b8ab4bbcf9f794e49fc7a Mon Sep 17 00:00:00 2001 From: Chris Withers Date: Sun, 26 May 2013 21:58:39 +0100 Subject: [PATCH 2/5] raising an exception here rather than returning False causes problems with SQLAlchemy's internal state tracking --- lib/_range.py | 2 +- tests/test_types_extras.py | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/_range.py b/lib/_range.py index 5803a8ab..16b51a5f 100644 --- a/lib/_range.py +++ b/lib/_range.py @@ -122,7 +122,7 @@ class Range(object): def __eq__(self, other): if not isinstance(other, self.__class__): - raise TypeError('Cannot compare %r with %r' % (self, other)) + return False return (self._lower == other._lower and self._upper == other._upper and self._bounds == other._bounds) diff --git a/tests/test_types_extras.py b/tests/test_types_extras.py index 48074d7b..5b0c2af3 100755 --- a/tests/test_types_extras.py +++ b/tests/test_types_extras.py @@ -1214,13 +1214,7 @@ class RangeTestCase(unittest.TestCase): def test_eq_wrong_type(self): from psycopg2.extras import Range - try: - Range(10, 20)==() - except TypeError, e: - self.assertEqual( - str(e), "Cannot compare Range(10, 20, '[)') with ()") - else: - self.fail('No exception raised') + self.assertFalse(Range(10, 20)==()) def test_not_ordered(self): from psycopg2.extras import Range From 28276e3eb17eb67178d2fa742a799c693b4d995c Mon Sep 17 00:00:00 2001 From: Chris Withers Date: Sun, 26 May 2013 22:20:07 +0100 Subject: [PATCH 3/5] cater for comparison of subclasses --- lib/_range.py | 2 +- tests/test_types_extras.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/_range.py b/lib/_range.py index 16b51a5f..0f159908 100644 --- a/lib/_range.py +++ b/lib/_range.py @@ -121,7 +121,7 @@ class Range(object): return self._bounds is not None def __eq__(self, other): - if not isinstance(other, self.__class__): + if not isinstance(other, Range): return False return (self._lower == other._lower and self._upper == other._upper diff --git a/tests/test_types_extras.py b/tests/test_types_extras.py index 5b0c2af3..eded26a1 100755 --- a/tests/test_types_extras.py +++ b/tests/test_types_extras.py @@ -1216,6 +1216,15 @@ class RangeTestCase(unittest.TestCase): from psycopg2.extras import Range self.assertFalse(Range(10, 20)==()) + def test_eq_subclass(self): + from psycopg2.extras import Range, NumericRange + + class IntRange(NumericRange): pass + class PositiveIntRange(IntRange): pass + + self.assertTrue(Range(10, 20)==IntRange(10, 20)) + self.assertTrue(PositiveIntRange(10, 20)==IntRange(10, 20)) + def test_not_ordered(self): from psycopg2.extras import Range self.assertRaises(TypeError, lambda: Range(empty=True) < Range(0,4)) From d50ea3d82baa0b0a9d3e76836ecec81f71362422 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Tue, 18 Jun 2013 14:10:49 +0100 Subject: [PATCH 4/5] Uniform Range eq tests style --- tests/test_types_extras.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_types_extras.py b/tests/test_types_extras.py index eded26a1..96ffcd3c 100755 --- a/tests/test_types_extras.py +++ b/tests/test_types_extras.py @@ -1214,16 +1214,16 @@ class RangeTestCase(unittest.TestCase): def test_eq_wrong_type(self): from psycopg2.extras import Range - self.assertFalse(Range(10, 20)==()) + self.assertNotEqual(Range(10, 20), ()) def test_eq_subclass(self): from psycopg2.extras import Range, NumericRange - + class IntRange(NumericRange): pass class PositiveIntRange(IntRange): pass - - self.assertTrue(Range(10, 20)==IntRange(10, 20)) - self.assertTrue(PositiveIntRange(10, 20)==IntRange(10, 20)) + + self.assertEqual(Range(10, 20), IntRange(10, 20)) + self.assertEqual(PositiveIntRange(10, 20), IntRange(10, 20)) def test_not_ordered(self): from psycopg2.extras import Range From 1361189b991e8905767cc1660dc2a4affa1d75fd Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Tue, 18 Jun 2013 14:13:00 +0100 Subject: [PATCH 5/5] Mention the Range eq fix in the NEWS file --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index a2b94ce0..e2f6b7fe 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ What's new in psycopg 2.5.1 - Fixed build on Solaris 10 and 11 where the round() function is already declared (:ticket:`#146`). +- Fixed comparison of `Range` with non-range objects (:ticket:`#164`). + Thanks to Chris Withers for the patch. What's new in psycopg 2.5