From: Daniele Varrazzo Date: Tue, 14 Oct 2025 00:35:48 +0000 (+0200) Subject: refactor: drop copy format code path with buffer creation X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4c46e27f0c11ebdf1456b156f747494797061ad0;p=thirdparty%2Fpsycopg.git refactor: drop copy format code path with buffer creation The path is unused and leads to more convoluted code. --- diff --git a/psycopg/psycopg/_copy_base.py b/psycopg/psycopg/_copy_base.py index 19d016d9a..bedc98a8b 100644 --- a/psycopg/psycopg/_copy_base.py +++ b/psycopg/psycopg/_copy_base.py @@ -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): diff --git a/psycopg_c/psycopg_c/_psycopg.pyi b/psycopg_c/psycopg_c/_psycopg.pyi index c17823467..4fbd390e0 100644 --- a/psycopg_c/psycopg_c/_psycopg.pyi +++ b/psycopg_c/psycopg_c/_psycopg.pyi @@ -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, ...]: ... diff --git a/psycopg_c/psycopg_c/_psycopg/copy.pyx b/psycopg_c/psycopg_c/_psycopg/copy.pyx index bd3ac10ac..b9b2119cd 100644 --- a/psycopg_c/psycopg_c/_psycopg/copy.pyx +++ b/psycopg_c/psycopg_c/_psycopg/copy.pyx @@ -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 = 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