]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
refactor: drop copy format code path with buffer creation 1150/head
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 14 Oct 2025 00:35:48 +0000 (02:35 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 14 Oct 2025 01:45:43 +0000 (03:45 +0200)
The path is unused and leads to more convoluted code.

psycopg/psycopg/_copy_base.py
psycopg_c/psycopg_c/_psycopg.pyi
psycopg_c/psycopg_c/_psycopg/copy.pyx

index 19d016d9a4e2776daa3d8a1ae8779035b5882b98..bedc98a8b155e2d36662e25b1d64a65341e776d7 100644 (file)
@@ -321,16 +321,11 @@ class BinaryFormatter(Formatter):
             return data
 
 
-def _format_row_text(
-    row: Sequence[Any], tx: Transformer, out: bytearray | None = None
-) -> bytearray:
+def _format_row_text(row: Sequence[Any], tx: Transformer, out: bytearray) -> None:
     """Convert a row of objects to the data to send for copy."""
-    if out is None:
-        out = bytearray()
-
     if not row:
         out += b"\n"
-        return out
+        return
 
     adapted = tx.dump_sequence(row, [PY_TEXT] * len(row))
     for b in adapted:
@@ -338,16 +333,10 @@ def _format_row_text(
         out += b"\t"
 
     out[-1:] = b"\n"
-    return out
 
 
-def _format_row_binary(
-    row: Sequence[Any], tx: Transformer, out: bytearray | None = None
-) -> bytearray:
+def _format_row_binary(row: Sequence[Any], tx: Transformer, out: bytearray) -> None:
     """Convert a row of objects to the data to send for binary copy."""
-    if out is None:
-        out = bytearray()
-
     adapted = tx.dump_sequence(row, [PY_BINARY] * len(row))
     out += _pack_int2(len(row))
     for b in adapted:
@@ -357,8 +346,6 @@ def _format_row_binary(
         else:
             out += _binary_null
 
-    return out
-
 
 def _parse_row_text(data: Buffer, tx: Transformer) -> tuple[Any, ...]:
     if not isinstance(data, bytes):
index c17823467194d3348312816bce4afa1c39ebaa2b..4fbd390e01c2693ce4a3152777e49e63a1322bc2 100644 (file)
@@ -68,11 +68,11 @@ def wait_c(
 
 # Copy support
 def format_row_text(
-    row: Sequence[Any], tx: abc.Transformer, out: bytearray | None = None
-) -> bytearray: ...
+    row: Sequence[Any], tx: abc.Transformer, out: bytearray
+) -> None: ...
 def format_row_binary(
-    row: Sequence[Any], tx: abc.Transformer, out: bytearray | None = None
-) -> bytearray: ...
+    row: Sequence[Any], tx: abc.Transformer, out: bytearray
+) -> None: ...
 def parse_row_text(data: abc.Buffer, tx: abc.Transformer) -> tuple[Any, ...]: ...
 def parse_row_binary(data: abc.Buffer, tx: abc.Transformer) -> tuple[Any, ...]: ...
 
index bd3ac10ac8e49bed14a1357f6aa37771ac32e5b1..b9b2119cd479d6867931ff8f8036ceb26327de2b 100644 (file)
@@ -21,9 +21,7 @@ from psycopg import errors as e
 cdef int32_t _binary_null = -1
 
 
-def _format_row_binary(
-    row: Sequence[Any], tx: Transformer, out: bytearray
-) -> bytearray:
+cdef object _format_row_binary(object row, Transformer tx, bytearray out):
     """Convert a row of adapted data to the data to send for binary copy"""
     cdef Py_ssize_t rowlen
     if type(row) is list:
@@ -95,27 +93,19 @@ def _format_row_binary(
 
     # Resize to the final size
     PyByteArray_Resize(out, pos)
-    return out
 
 
-def format_row_binary(
-    row: Sequence[Any], tx: Transformer, out: bytearray = None
-) -> bytearray:
-    cdef Py_ssize_t size
-    if out is None:
-        out = PyByteArray_FromStringAndSize("", 0)
-        size = 0
-    else:
-        size = PyByteArray_GET_SIZE(out)
+def format_row_binary(row: Sequence[Any], tx: Transformer, out: bytearray) -> None:
+    cdef Py_ssize_t size = PyByteArray_GET_SIZE(out)
 
     try:
         _format_row_binary(row, tx, out)
     except Exception as e:
+        # Restore the input bytearray to the size it was before entering here
+        # to avoid potentially passing junk to copy.
         PyByteArray_Resize(out, size)
         raise e
 
-    return out
-
 
 cdef int _append_binary_none(bytearray out, Py_ssize_t *pos) except -1:
     cdef char *target
@@ -125,9 +115,7 @@ cdef int _append_binary_none(bytearray out, Py_ssize_t *pos) except -1:
     return 0
 
 
-def _format_row_text(
-    row: Sequence[Any], tx: Transformer, out: bytearray
-) -> bytearray:
+cdef object _format_row_text(object row, Py_ssize_t rowlen, Transformer tx, bytearray out):
     # offset in 'out' where to write
     cdef Py_ssize_t pos = PyByteArray_GET_SIZE(out)
 
@@ -139,7 +127,6 @@ def _format_row_text(
     cdef int with_tab
     cdef PyObject *fmt = <PyObject *>PG_TEXT
     cdef PyObject *row_dumper
-    cdef Py_ssize_t rowlen = len(row)
 
     # try to get preloaded dumpers from set_types
     if not tx._row_dumpers:
@@ -215,34 +202,33 @@ def _format_row_text(
     # Resize to the final size, add the newline
     PyByteArray_Resize(out, pos + 1)
     out[pos] = b"\n"
-    return out
 
 
-def format_row_text(
-    row: Sequence[Any], tx: Transformer, out: bytearray = None
-) -> bytearray:
-    cdef Py_ssize_t size
-    if out is None:
-        out = PyByteArray_FromStringAndSize("", 0)
-        size = 0
-    else:
-        size = PyByteArray_GET_SIZE(out)
+def format_row_text(row: Sequence[Any], tx: Transformer, out: bytearray) -> None:
+    cdef Py_ssize_t size = PyByteArray_GET_SIZE(out)
 
     # exit early, if the row is empty
-    cdef Py_ssize_t rowlen = len(row)
+    cdef Py_ssize_t rowlen
+    if type(row) is list:
+        rowlen = PyList_GET_SIZE(row)
+    elif type(row) is tuple:
+        rowlen = PyTuple_GET_SIZE(row)
+    else:
+        rowlen = len(row)
+
     if rowlen == 0:
         PyByteArray_Resize(out, size + 1)
         out[size] = b"\n"
-        return out
+        return
 
     try:
-        _format_row_text(row, tx, out)
+        _format_row_text(row, rowlen, tx, out)
     except Exception as e:
+        # Restore the input bytearray to the size it was before entering here
+        # to avoid potentially passing junk to copy.
         PyByteArray_Resize(out, size)
         raise e
 
-    return out
-
 
 cdef int _append_text_none(bytearray out, Py_ssize_t *pos, int with_tab) except -1:
     cdef char *target