]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Fix equality comparison between a PG Range and a different class instance
authorLele Gaifax <lele@metapensiero.it>
Thu, 15 Dec 2022 09:27:03 +0000 (04:27 -0500)
committersqla-tester <sqla-tester@sqlalchemy.org>
Thu, 15 Dec 2022 09:27:03 +0000 (04:27 -0500)
This fixes issue #8984, making the method `Range.__eq__` return `NotImplemented` when the argument is an instance of a different class.

Closes: #8985
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/8985
Pull-request-sha: b8f601f038a2203af02a99ab190ebbc1c489549a

Change-Id: Iaf0b651a22a9f346c8f18b3a53e3339bf61bb33f

doc/build/changelog/unreleased_20/8984.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/postgresql/ranges.py
test/dialect/postgresql/test_types.py

diff --git a/doc/build/changelog/unreleased_20/8984.rst b/doc/build/changelog/unreleased_20/8984.rst
new file mode 100644 (file)
index 0000000..b78abb2
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: bug, postgresql
+    :tickets: 8984
+
+    The :meth:`_postgresql.Range.__eq___` will now return ``NotImplemented``
+    when comparing with an instance of a different class, instead of raising
+    an :exc:`AttributeError` exception.
index 9b5834ccd80a2b017442cc871f3107a5d56b4afa..609af5eb6200084245d54125cdebbea2ee4798f0 100644 (file)
@@ -146,7 +146,7 @@ class Range(Generic[_T]):
         return AbstractRange()
 
     def _contains_value(self, value: _T) -> bool:
-        """return True if this range contains the given value."""
+        """Return True if this range contains the given value."""
 
         if self.empty:
             return False
@@ -289,6 +289,9 @@ class Range(Generic[_T]):
         bounds inclusivity, returning ``True`` if they are equal.
         """
 
+        if not isinstance(other, Range):
+            return NotImplemented
+
         if self.empty and other.empty:
             return True
         elif self.empty != other.empty:
@@ -681,7 +684,7 @@ class AbstractRange(sqltypes.TypeEngine[Range[_T]]):
         cls: Type[Union[TypeEngine[Any], TypeEngineMixin]],
         **kw: Any,
     ) -> TypeEngine[Any]:
-        """dynamically adapt a range type to an abstract impl.
+        """Dynamically adapt a range type to an abstract impl.
 
         For example ``INT4RANGE().adapt(_Psycopg2NumericRange)`` should
         produce a type that will have ``_Psycopg2NumericRange`` behaviors
@@ -808,7 +811,7 @@ class AbstractRange(sqltypes.TypeEngine[Range[_T]]):
 
 
 class AbstractRangeImpl(AbstractRange[Range[_T]]):
-    """marker for AbstractRange that will apply a subclass-specific
+    """Marker for AbstractRange that will apply a subclass-specific
     adaptation"""
 
 
@@ -821,7 +824,7 @@ class AbstractMultiRange(AbstractRange[Range[_T]]):
 class AbstractMultiRangeImpl(
     AbstractRangeImpl[Range[_T]], AbstractMultiRange[Range[_T]]
 ):
-    """marker for AbstractRange that will apply a subclass-specific
+    """Marker for AbstractRange that will apply a subclass-specific
     adaptation"""
 
 
index dcde497b46326292f269deea13802db91b3d2ec2..4832d81d9c441d1c3f73f0487629356795601884 100644 (file)
@@ -3996,6 +3996,10 @@ class _RangeComparisonFixtures(_RangeTests):
 
         is_false(range_.contains(values["rh"]))
 
+        is_true(range_ == range_)
+        is_false(range_ != range_)
+        is_false(range_ == None)
+
     def test_compatibility_accessors(self):
         range_ = self._data_obj()