]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Raise a TypeError when slice-setting a Multirange with a non-iterable value
authorDenis Laxalde <denis.laxalde@dalibo.com>
Thu, 28 Oct 2021 08:13:39 +0000 (10:13 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 28 Oct 2021 14:26:48 +0000 (15:26 +0100)
The type declaration is:

    def __setitem__(index: slice, value: Iterable[Range[T]]) -> None:
        ...

so passing a non-iterable value should not be allowed. However, the
method implementation makes a special-case for non-iterable values with
a slice.

In accordance with MutableSequence behavior, e.g.:

  >>> x = [1, 2, 3]
  >>> x[1:3] = 0
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  TypeError: can only assign an iterable

it seems more correct to raise a TypeError.

docs/news.rst
psycopg/psycopg/types/multirange.py
tests/types/test_multirange.py

index 28348aae410ac52f158f57f793ce97fa58be08cb..832a1523aa420f01c1c83dc745d1ae83be9d591c 100644 (file)
@@ -15,6 +15,8 @@ Psycopg 3.0.2
 
 - Fix type hint for `sql.SQL.join()` (:ticket:`#127`).
 - Fix type hint for `Connection.notifies()` (:ticket:`#128`).
+- Fix call to `MultiRange.__setitem__()` with a non-iterable value and a
+  slice, now raising a `TypeError` (:ticket:`#129`).
 
 
 Psycopg 3.0.1
index 7824e230efd9a01b5261709b04bd618f20aacbfb..9d6763c6faa5903b676bad2239cef37cff578346 100644 (file)
@@ -79,11 +79,10 @@ class Multirange(MutableSequence[Range[T]]):
         if isinstance(index, int):
             self._check_type(value)
             self._ranges[index] = self._check_type(value)
+        elif not isinstance(value, Iterable):
+            raise TypeError("can only assign an iterable")
         else:
-            if isinstance(value, Iterable):
-                value = map(self._check_type, value)
-            else:
-                value = [self._check_type(value)]
+            value = map(self._check_type, value)
             self._ranges[index] = value
 
     def __delitem__(self, index: Union[int, slice]) -> None:
index 7721f63a81376704453536babd2d17b4b6d5999c..e8f05dfc6a8f2fb62ec3bee166d0deddce2d6c9e 100644 (file)
@@ -67,7 +67,10 @@ class TestMultirangeObject:
         assert mr == Multirange([Range(10, 20), Range(31, 41), Range(51, 61)])
 
         mr = Multirange([Range(10, 20), Range(30, 40), Range(50, 60)])
-        mr[1:3] = Range(31, 41)
+        with pytest.raises(TypeError, match="can only assign an iterable"):
+            mr[1:3] = Range(31, 41)  # type: ignore[call-overload]
+
+        mr[1:3] = [Range(31, 41)]
         assert mr == Multirange([Range(10, 20), Range(31, 41)])
 
     def test_delitem(self):