- Drop support for Python 3.6.
+Psycopg 3.0.14 (unreleased)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Fail dumping arrays of mixed numbers with DataError (:ticket:`#301`).
+
+
Current release
---------------
class _IntDumper(Dumper):
def dump(self, obj: Any) -> bytes:
- # Convert to int in order to dump IntEnum correctly
- return str(int(obj)).encode()
+ t = type(obj)
+ if t is not int:
+ # Convert to int in order to dump IntEnum correctly
+ if issubclass(t, int):
+ obj = int(obj)
+ else:
+ raise e.DataError(f"ingeger expected, got {type(obj).__name__!r}")
+
+ return str(obj).encode()
def quote(self, obj: Any) -> bytes:
value = self.dump(obj)
cdef char *src
cdef Py_ssize_t length
+ # Ensure an int or a subclass. The 'is' type check is fast.
+ # Passing a float must give an error, but passing an Enum should work.
+ if type(obj) is not int and not isinstance(obj, int):
+ raise e.DataError(f"ingeger expected, got {type(obj).__name__!r}")
+
val = PyLong_AsLongLongAndOverflow(obj, &overflow)
if not overflow:
buf = CDumper.ensure_size(rv, offset, MAXINT8LEN + 1)
+from enum import Enum
from decimal import Decimal
import pytest
assert type(i) is want_cls
+def test_mix_types(conn):
+ class MyEnum(int, Enum):
+ ONE = 2**30
+
+ cur = conn.execute("select %s", ([1, MyEnum.ONE],))
+ assert cur.fetchone() == ([1, 2**30],)
+ assert cur.description[0].type_code == cur.adapters.types["int4"].array_oid
+
+ cur = conn.execute("select %s", ([1, psycopg.types.numeric.Int8(2**60)],))
+ assert cur.fetchone() == ([1, 2**60],)
+ assert cur.description[0].type_code == cur.adapters.types["int8"].array_oid
+
+ with pytest.raises(psycopg.DataError):
+ conn.execute("select %s", ([1, 0.5],))
+
+ with pytest.raises(psycopg.DataError):
+ conn.execute("select %s", ([1, Decimal("0.5")],))
+
+
@pytest.mark.parametrize("fmt_in", PyFormat)
def test_empty_list_mix(conn, fmt_in):
objs = list(range(3))