From: abebus Date: Mon, 20 Oct 2025 20:45:44 +0000 (+0300) Subject: done X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d5d193c1c09aada28679d0eea6dc453ab80c65e;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git done --- diff --git a/lib/sqlalchemy/engine/_row_cy.py b/lib/sqlalchemy/engine/_row_cy.py index cb9dfa9a28..1db2be4916 100644 --- a/lib/sqlalchemy/engine/_row_cy.py +++ b/lib/sqlalchemy/engine/_row_cy.py @@ -4,7 +4,9 @@ # # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php -# mypy: disable-error-code="misc" +# mypy: disable-error-code="misc,no-redef,valid-type,no-untyped-call" +# mypy: disable-error-code="index,no-any-return,arg-type,assignment" +# cython: wraparound=False, boundscheck=False from __future__ import annotations from typing import Any @@ -43,17 +45,6 @@ def _is_compiled() -> bool: if not cython.compiled: - if TYPE_CHECKING: - - def PyTuple_New(n): # type: ignore - # Actually produces list if not compiled - return [None] * n - - def PyTuple_SET_ITEM(tup, idx, item): # type: ignore - tup[idx] = item - - PySequence_Fast_GET_SIZE = len - Py_INCREF = cython._no_op def _apply_processors( proc: _ProcessorsType, data: Sequence[Any] @@ -72,20 +63,20 @@ else: from cython.cimports.cpython import PyTuple_New from cython.cimports.cpython import Py_INCREF from cython.cimports.cpython import PyTuple_SET_ITEM - from cython.cimports.cpython import PySequence_Fast_GET_SIZE + + _SequenceLike = cython.fused_type(tuple, list, object) @cython.inline @cython.cfunc - @cython.wraparound(False) - @cython.boundscheck(False) - @cython.returns(tuple) @cython.locals( res=tuple, proc_size=cython.Py_ssize_t, p=object, value=object ) - def _apply_processors(proc: object, data: object) -> Tuple[Any, ...]: - proc_size = PySequence_Fast_GET_SIZE(proc) + def _apply_processors( + proc: _SequenceLike, data: _SequenceLike + ) -> Tuple[Any, ...]: + proc_size = len(proc) # TODO: would be nice to do this only on the fist row - assert PySequence_Fast_GET_SIZE(data) == proc_size + assert len(data) == proc_size res = PyTuple_New(proc_size) for i in range(proc_size): p = proc[i] @@ -109,6 +100,22 @@ class BaseRow: ) _data: Tuple[Any, ...] = cython.declare(tuple, visibility="readonly") + def __getattribute__(self, name: _KeyType) -> object: + self = cython.cast(BaseRow, self) + if isinstance(name, str): + if name == "_data": + return self._data + if name == "_key_to_index": + return self._key_to_index + if name == "_parent": + return self._parent + if name[0] != "_" and name[-1] != "_": + try: + return self._get_by_key_impl(name, False) + except KeyError: + pass + return object.__getattribute__(self, name) + def __init__( self, parent: ResultMetaData, @@ -139,65 +146,24 @@ class BaseRow: self._key_to_index = key_to_index self._data = data - if cython.compiled: - - @cython.ccall - @cython.returns(dict) - def __getstate__(self) -> Dict[str, Any]: - self = cython.cast(BaseRow, self) - return {"_parent": self._parent, "_data": self._data} - - @cython.ccall - @cython.returns(tuple) - def __reduce__(self) -> Tuple[Any, Any]: - self = cython.cast(BaseRow, self) - return ( - rowproxy_reconstructor, - ( - self.__class__, - {"_parent": self._parent, "_data": self._data}, - ), - ) + def __getstate__(self) -> Dict[str, Any]: + return {"_parent": self._parent, "_data": self._data} - def __getattribute__(self, name: _KeyType) -> object: - self = cython.cast(BaseRow, self) - if isinstance(name, str): - if name == "_data": - return self._data - if name == "_key_to_index": - return self._key_to_index - if name == "_parent": - return self._parent - if name[0] != "_" and name[-1] != "_": - try: - return self._get_by_key_impl(name, False) - except KeyError: - pass - return object.__getattribute__(self, name) - - else: - - def __getstate__(self) -> Dict[str, Any]: - return {"_parent": self._parent, "_data": self._data} - - def __reduce__(self) -> Tuple[Any, Any]: - return ( - rowproxy_reconstructor, - ( - self.__class__, - {"_parent": self._parent, "_data": self._data}, - ), - ) + def __reduce__(self) -> Tuple[Any, Any]: + return ( + rowproxy_reconstructor, + ( + self.__class__, + {"_parent": self._parent, "_data": self._data}, + ), + ) def __setstate__(self, state: Dict[str, Any]) -> None: - self = cython.cast(BaseRow, self) - parent = state["_parent"] + parent: ResultMetaData = state["_parent"] self._set_attrs(parent, parent._key_to_index, state["_data"]) - @cython.wraparound(False) - @cython.boundscheck(False) def _values_impl(self) -> List[Any]: - return list(cython.cast(BaseRow, self)._data) + return list(self._data) def __iter__(self) -> Iterator[Any]: return iter(self._data) @@ -218,12 +184,9 @@ class BaseRow: @cython.cfunc @cython.inline - @cython.wraparound(False) - @cython.boundscheck(False) - @cython.locals(index=cython.Py_ssize_t) def _get_by_key_impl(self, key: _KeyType, attr_err: cython.bint) -> object: self = cython.cast(BaseRow, self) - index = self._key_to_index.get(key, -1) + index: cython.Py_ssize_t = self._key_to_index.get(key, -1) if index != -1: return self._data[index] self._parent._key_not_found(key, attr_err) @@ -231,7 +194,7 @@ class BaseRow: def __getattr__(self, name: _KeyType) -> Any: return self._get_by_key_impl(name, True) - def __setattr__(self, name: str, value: Any): + def __setattr__(self, name: str, value: Any) -> None: if name not in {"_parent", "_data", "_key_to_index"}: raise AttributeError("can't set attribute") object.__setattr__(self, name, value) @@ -240,9 +203,9 @@ class BaseRow: raise AttributeError("can't delete attribute") def _to_tuple_instance(self) -> Tuple[Any, ...]: - return cython.cast(BaseRow, self)._data + return self._data - def __contains__(self, key: _KeyType) -> cython.bint: + def __contains__(self, key: Any) -> cython.bint: return key in self._data diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index fb40c6f10a..19381de87e 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -3408,7 +3408,7 @@ class Mapper( mapping: RowMapping if hasattr(row, "_mapping"): - mapping = row._mapping + mapping = row._mapping # type: ignore[assignment] else: mapping = row # type: ignore[assignment] diff --git a/lib/sqlalchemy/util/cython.py b/lib/sqlalchemy/util/cython.py index 56ba0bf7b1..3e74d8199d 100644 --- a/lib/sqlalchemy/util/cython.py +++ b/lib/sqlalchemy/util/cython.py @@ -68,6 +68,3 @@ def returns(_: type) -> _NO_OP[_T]: def locals(**kwargs: Any) -> _NO_OP[_T]: # noqa: A001 return _no_op - - -boundscheck = wraparound = annotation_typing diff --git a/test/aaa_profiling/test_resultset.py b/test/aaa_profiling/test_resultset.py index 049e4a45e5..5c6ef2b1dd 100644 --- a/test/aaa_profiling/test_resultset.py +++ b/test/aaa_profiling/test_resultset.py @@ -266,4 +266,7 @@ class RowTest(fixtures.TestBase): def __iter__(self): return iter(self.data) + def __len__(self): + return len(self.data) + self._test_getitem_value_refcounts_new(CustomSeq)