SQLAlchemy 2.1.0rc1__cp315-cp315-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. sqlalchemy/__init__.py +299 -0
  2. sqlalchemy/connectors/__init__.py +18 -0
  3. sqlalchemy/connectors/aioodbc.py +171 -0
  4. sqlalchemy/connectors/asyncio.py +476 -0
  5. sqlalchemy/connectors/pyodbc.py +248 -0
  6. sqlalchemy/dialects/__init__.py +62 -0
  7. sqlalchemy/dialects/_typing.py +29 -0
  8. sqlalchemy/dialects/mssql/__init__.py +88 -0
  9. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  10. sqlalchemy/dialects/mssql/base.py +4833 -0
  11. sqlalchemy/dialects/mssql/information_schema.py +345 -0
  12. sqlalchemy/dialects/mssql/json.py +140 -0
  13. sqlalchemy/dialects/mssql/mssqlpython.py +242 -0
  14. sqlalchemy/dialects/mssql/provision.py +196 -0
  15. sqlalchemy/dialects/mssql/pymssql.py +130 -0
  16. sqlalchemy/dialects/mssql/pyodbc.py +697 -0
  17. sqlalchemy/dialects/mysql/__init__.py +106 -0
  18. sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
  19. sqlalchemy/dialects/mysql/aiomysql.py +260 -0
  20. sqlalchemy/dialects/mysql/asyncmy.py +241 -0
  21. sqlalchemy/dialects/mysql/base.py +3896 -0
  22. sqlalchemy/dialects/mysql/cymysql.py +107 -0
  23. sqlalchemy/dialects/mysql/dml.py +279 -0
  24. sqlalchemy/dialects/mysql/enumerated.py +277 -0
  25. sqlalchemy/dialects/mysql/expression.py +146 -0
  26. sqlalchemy/dialects/mysql/json.py +92 -0
  27. sqlalchemy/dialects/mysql/mariadb.py +67 -0
  28. sqlalchemy/dialects/mysql/mariadbconnector.py +314 -0
  29. sqlalchemy/dialects/mysql/mysqlconnector.py +291 -0
  30. sqlalchemy/dialects/mysql/mysqldb.py +318 -0
  31. sqlalchemy/dialects/mysql/provision.py +153 -0
  32. sqlalchemy/dialects/mysql/pymysql.py +188 -0
  33. sqlalchemy/dialects/mysql/pyodbc.py +157 -0
  34. sqlalchemy/dialects/mysql/reflection.py +724 -0
  35. sqlalchemy/dialects/mysql/reserved_words.py +570 -0
  36. sqlalchemy/dialects/mysql/types.py +845 -0
  37. sqlalchemy/dialects/oracle/__init__.py +85 -0
  38. sqlalchemy/dialects/oracle/base.py +3847 -0
  39. sqlalchemy/dialects/oracle/cx_oracle.py +1736 -0
  40. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  41. sqlalchemy/dialects/oracle/json.py +157 -0
  42. sqlalchemy/dialects/oracle/oracledb.py +898 -0
  43. sqlalchemy/dialects/oracle/provision.py +288 -0
  44. sqlalchemy/dialects/oracle/types.py +367 -0
  45. sqlalchemy/dialects/oracle/vector.py +366 -0
  46. sqlalchemy/dialects/postgresql/__init__.py +170 -0
  47. sqlalchemy/dialects/postgresql/_psycopg_common.py +232 -0
  48. sqlalchemy/dialects/postgresql/array.py +534 -0
  49. sqlalchemy/dialects/postgresql/asyncpg.py +1318 -0
  50. sqlalchemy/dialects/postgresql/base.py +5935 -0
  51. sqlalchemy/dialects/postgresql/bitstring.py +327 -0
  52. sqlalchemy/dialects/postgresql/dml.py +360 -0
  53. sqlalchemy/dialects/postgresql/ext.py +599 -0
  54. sqlalchemy/dialects/postgresql/hstore.py +422 -0
  55. sqlalchemy/dialects/postgresql/json.py +411 -0
  56. sqlalchemy/dialects/postgresql/named_types.py +535 -0
  57. sqlalchemy/dialects/postgresql/operators.py +129 -0
  58. sqlalchemy/dialects/postgresql/pg8000.py +655 -0
  59. sqlalchemy/dialects/postgresql/pg_catalog.py +345 -0
  60. sqlalchemy/dialects/postgresql/provision.py +202 -0
  61. sqlalchemy/dialects/postgresql/psycopg.py +800 -0
  62. sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
  63. sqlalchemy/dialects/postgresql/psycopg2cffi.py +62 -0
  64. sqlalchemy/dialects/postgresql/ranges.py +1002 -0
  65. sqlalchemy/dialects/postgresql/types.py +388 -0
  66. sqlalchemy/dialects/sqlite/__init__.py +59 -0
  67. sqlalchemy/dialects/sqlite/aiosqlite.py +375 -0
  68. sqlalchemy/dialects/sqlite/base.py +3103 -0
  69. sqlalchemy/dialects/sqlite/dml.py +314 -0
  70. sqlalchemy/dialects/sqlite/json.py +134 -0
  71. sqlalchemy/dialects/sqlite/provision.py +237 -0
  72. sqlalchemy/dialects/sqlite/pysqlcipher.py +166 -0
  73. sqlalchemy/dialects/sqlite/pysqlite.py +959 -0
  74. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  75. sqlalchemy/engine/__init__.py +62 -0
  76. sqlalchemy/engine/_processors_cy.cp315-win32.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp315-win32.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +711 -0
  80. sqlalchemy/engine/_row_cy.cp315-win32.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp315-win32.pyd +0 -0
  83. sqlalchemy/engine/_util_cy.py +136 -0
  84. sqlalchemy/engine/base.py +3357 -0
  85. sqlalchemy/engine/characteristics.py +155 -0
  86. sqlalchemy/engine/create.py +877 -0
  87. sqlalchemy/engine/cursor.py +2425 -0
  88. sqlalchemy/engine/default.py +2627 -0
  89. sqlalchemy/engine/events.py +965 -0
  90. sqlalchemy/engine/interfaces.py +3636 -0
  91. sqlalchemy/engine/mock.py +133 -0
  92. sqlalchemy/engine/processors.py +83 -0
  93. sqlalchemy/engine/reflection.py +2141 -0
  94. sqlalchemy/engine/result.py +2012 -0
  95. sqlalchemy/engine/row.py +397 -0
  96. sqlalchemy/engine/strategies.py +16 -0
  97. sqlalchemy/engine/url.py +922 -0
  98. sqlalchemy/engine/util.py +164 -0
  99. sqlalchemy/event/__init__.py +26 -0
  100. sqlalchemy/event/api.py +220 -0
  101. sqlalchemy/event/attr.py +675 -0
  102. sqlalchemy/event/base.py +473 -0
  103. sqlalchemy/event/legacy.py +259 -0
  104. sqlalchemy/event/registry.py +391 -0
  105. sqlalchemy/events.py +17 -0
  106. sqlalchemy/exc.py +939 -0
  107. sqlalchemy/ext/__init__.py +10 -0
  108. sqlalchemy/ext/associationproxy.py +2073 -0
  109. sqlalchemy/ext/asyncio/__init__.py +29 -0
  110. sqlalchemy/ext/asyncio/base.py +281 -0
  111. sqlalchemy/ext/asyncio/engine.py +1487 -0
  112. sqlalchemy/ext/asyncio/exc.py +21 -0
  113. sqlalchemy/ext/asyncio/result.py +994 -0
  114. sqlalchemy/ext/asyncio/scoping.py +1679 -0
  115. sqlalchemy/ext/asyncio/session.py +2006 -0
  116. sqlalchemy/ext/automap.py +1702 -0
  117. sqlalchemy/ext/baked.py +558 -0
  118. sqlalchemy/ext/compiler.py +601 -0
  119. sqlalchemy/ext/declarative/__init__.py +65 -0
  120. sqlalchemy/ext/declarative/extensions.py +561 -0
  121. sqlalchemy/ext/horizontal_shard.py +481 -0
  122. sqlalchemy/ext/hybrid.py +1877 -0
  123. sqlalchemy/ext/indexable.py +364 -0
  124. sqlalchemy/ext/instrumentation.py +450 -0
  125. sqlalchemy/ext/mutable.py +1081 -0
  126. sqlalchemy/ext/orderinglist.py +440 -0
  127. sqlalchemy/ext/serializer.py +184 -0
  128. sqlalchemy/future/__init__.py +17 -0
  129. sqlalchemy/future/engine.py +15 -0
  130. sqlalchemy/inspection.py +188 -0
  131. sqlalchemy/log.py +279 -0
  132. sqlalchemy/orm/__init__.py +176 -0
  133. sqlalchemy/orm/_orm_constructors.py +2694 -0
  134. sqlalchemy/orm/_typing.py +180 -0
  135. sqlalchemy/orm/attributes.py +2868 -0
  136. sqlalchemy/orm/base.py +991 -0
  137. sqlalchemy/orm/bulk_persistence.py +2168 -0
  138. sqlalchemy/orm/clsregistry.py +630 -0
  139. sqlalchemy/orm/collections.py +1569 -0
  140. sqlalchemy/orm/context.py +3475 -0
  141. sqlalchemy/orm/decl_api.py +2283 -0
  142. sqlalchemy/orm/decl_base.py +2320 -0
  143. sqlalchemy/orm/dependency.py +1306 -0
  144. sqlalchemy/orm/descriptor_props.py +1183 -0
  145. sqlalchemy/orm/dynamic.py +306 -0
  146. sqlalchemy/orm/evaluator.py +378 -0
  147. sqlalchemy/orm/events.py +3387 -0
  148. sqlalchemy/orm/exc.py +237 -0
  149. sqlalchemy/orm/identity.py +302 -0
  150. sqlalchemy/orm/instrumentation.py +749 -0
  151. sqlalchemy/orm/interfaces.py +1595 -0
  152. sqlalchemy/orm/loading.py +1712 -0
  153. sqlalchemy/orm/mapped_collection.py +557 -0
  154. sqlalchemy/orm/mapper.py +4465 -0
  155. sqlalchemy/orm/path_registry.py +907 -0
  156. sqlalchemy/orm/persistence.py +1790 -0
  157. sqlalchemy/orm/properties.py +972 -0
  158. sqlalchemy/orm/query.py +3528 -0
  159. sqlalchemy/orm/relationships.py +3608 -0
  160. sqlalchemy/orm/scoping.py +2233 -0
  161. sqlalchemy/orm/session.py +5468 -0
  162. sqlalchemy/orm/state.py +1175 -0
  163. sqlalchemy/orm/state_changes.py +196 -0
  164. sqlalchemy/orm/strategies.py +3552 -0
  165. sqlalchemy/orm/strategy_options.py +2648 -0
  166. sqlalchemy/orm/sync.py +164 -0
  167. sqlalchemy/orm/unitofwork.py +797 -0
  168. sqlalchemy/orm/util.py +2461 -0
  169. sqlalchemy/orm/writeonly.py +701 -0
  170. sqlalchemy/pool/__init__.py +41 -0
  171. sqlalchemy/pool/base.py +1540 -0
  172. sqlalchemy/pool/events.py +375 -0
  173. sqlalchemy/pool/impl.py +583 -0
  174. sqlalchemy/py.typed +0 -0
  175. sqlalchemy/schema.py +75 -0
  176. sqlalchemy/sql/__init__.py +156 -0
  177. sqlalchemy/sql/_annotated_cols.py +402 -0
  178. sqlalchemy/sql/_cache_key_cy.cp315-win32.pyd +0 -0
  179. sqlalchemy/sql/_cache_key_cy.py +363 -0
  180. sqlalchemy/sql/_dml_constructors.py +132 -0
  181. sqlalchemy/sql/_elements_constructors.py +2190 -0
  182. sqlalchemy/sql/_orm_types.py +19 -0
  183. sqlalchemy/sql/_selectable_constructors.py +840 -0
  184. sqlalchemy/sql/_typing.py +500 -0
  185. sqlalchemy/sql/_util_cy.cp315-win32.pyd +0 -0
  186. sqlalchemy/sql/_util_cy.pxd +11 -0
  187. sqlalchemy/sql/_util_cy.py +127 -0
  188. sqlalchemy/sql/annotation.py +590 -0
  189. sqlalchemy/sql/base.py +2702 -0
  190. sqlalchemy/sql/cache_key.py +915 -0
  191. sqlalchemy/sql/coercions.py +1373 -0
  192. sqlalchemy/sql/compiler.py +8453 -0
  193. sqlalchemy/sql/crud.py +1816 -0
  194. sqlalchemy/sql/ddl.py +1962 -0
  195. sqlalchemy/sql/default_comparator.py +660 -0
  196. sqlalchemy/sql/dml.py +2018 -0
  197. sqlalchemy/sql/elements.py +6057 -0
  198. sqlalchemy/sql/events.py +458 -0
  199. sqlalchemy/sql/expression.py +171 -0
  200. sqlalchemy/sql/functions.py +2380 -0
  201. sqlalchemy/sql/lambdas.py +1442 -0
  202. sqlalchemy/sql/naming.py +204 -0
  203. sqlalchemy/sql/operators.py +2909 -0
  204. sqlalchemy/sql/roles.py +332 -0
  205. sqlalchemy/sql/schema.py +7075 -0
  206. sqlalchemy/sql/selectable.py +7634 -0
  207. sqlalchemy/sql/sqltypes.py +4130 -0
  208. sqlalchemy/sql/traversals.py +1041 -0
  209. sqlalchemy/sql/type_api.py +2450 -0
  210. sqlalchemy/sql/util.py +1496 -0
  211. sqlalchemy/sql/visitors.py +1153 -0
  212. sqlalchemy/testing/__init__.py +97 -0
  213. sqlalchemy/testing/assertions.py +1007 -0
  214. sqlalchemy/testing/assertsql.py +519 -0
  215. sqlalchemy/testing/asyncio.py +128 -0
  216. sqlalchemy/testing/cancellation.py +237 -0
  217. sqlalchemy/testing/config.py +440 -0
  218. sqlalchemy/testing/engines.py +482 -0
  219. sqlalchemy/testing/entities.py +117 -0
  220. sqlalchemy/testing/exclusions.py +501 -0
  221. sqlalchemy/testing/fixtures/__init__.py +30 -0
  222. sqlalchemy/testing/fixtures/base.py +426 -0
  223. sqlalchemy/testing/fixtures/mypy.py +247 -0
  224. sqlalchemy/testing/fixtures/orm.py +227 -0
  225. sqlalchemy/testing/fixtures/sql.py +538 -0
  226. sqlalchemy/testing/pickleable.py +155 -0
  227. sqlalchemy/testing/plugin/__init__.py +6 -0
  228. sqlalchemy/testing/plugin/bootstrap.py +50 -0
  229. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  230. sqlalchemy/testing/plugin/pytestplugin.py +896 -0
  231. sqlalchemy/testing/profiles_file.py +350 -0
  232. sqlalchemy/testing/profiling.py +294 -0
  233. sqlalchemy/testing/provision.py +633 -0
  234. sqlalchemy/testing/requirements.py +1971 -0
  235. sqlalchemy/testing/schema.py +198 -0
  236. sqlalchemy/testing/suite/__init__.py +19 -0
  237. sqlalchemy/testing/suite/test_cte.py +237 -0
  238. sqlalchemy/testing/suite/test_ddl.py +420 -0
  239. sqlalchemy/testing/suite/test_dialect.py +776 -0
  240. sqlalchemy/testing/suite/test_insert.py +630 -0
  241. sqlalchemy/testing/suite/test_reflection.py +3815 -0
  242. sqlalchemy/testing/suite/test_results.py +660 -0
  243. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  244. sqlalchemy/testing/suite/test_select.py +2112 -0
  245. sqlalchemy/testing/suite/test_sequence.py +317 -0
  246. sqlalchemy/testing/suite/test_table_via_select.py +686 -0
  247. sqlalchemy/testing/suite/test_types.py +2271 -0
  248. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  249. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  250. sqlalchemy/testing/util.py +575 -0
  251. sqlalchemy/testing/warnings.py +52 -0
  252. sqlalchemy/types.py +75 -0
  253. sqlalchemy/util/__init__.py +165 -0
  254. sqlalchemy/util/_collections.py +688 -0
  255. sqlalchemy/util/_collections_cy.cp315-win32.pyd +0 -0
  256. sqlalchemy/util/_collections_cy.pxd +8 -0
  257. sqlalchemy/util/_collections_cy.py +516 -0
  258. sqlalchemy/util/_has_cython.py +48 -0
  259. sqlalchemy/util/_immutabledict_cy.cp315-win32.pyd +0 -0
  260. sqlalchemy/util/_immutabledict_cy.py +240 -0
  261. sqlalchemy/util/compat.py +298 -0
  262. sqlalchemy/util/concurrency.py +272 -0
  263. sqlalchemy/util/cython.py +95 -0
  264. sqlalchemy/util/deprecations.py +401 -0
  265. sqlalchemy/util/langhelpers.py +2797 -0
  266. sqlalchemy/util/preloaded.py +153 -0
  267. sqlalchemy/util/queue.py +304 -0
  268. sqlalchemy/util/tool_support.py +202 -0
  269. sqlalchemy/util/topological.py +120 -0
  270. sqlalchemy/util/typing.py +709 -0
  271. sqlalchemy-2.1.0rc1.dist-info/METADATA +270 -0
  272. sqlalchemy-2.1.0rc1.dist-info/RECORD +276 -0
  273. sqlalchemy-2.1.0rc1.dist-info/WHEEL +5 -0
  274. sqlalchemy-2.1.0rc1.dist-info/licenses/AUTHORS +30 -0
  275. sqlalchemy-2.1.0rc1.dist-info/licenses/LICENSE +19 -0
  276. sqlalchemy-2.1.0rc1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,711 @@
1
+ # engine/_result_cy.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+ # mypy: disable-error-code="misc,no-redef,type-arg,untyped-decorator"
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Callable
11
+ from collections.abc import Iterator
12
+ from collections.abc import Sequence
13
+ from enum import Enum
14
+ import operator
15
+ from typing import Any
16
+ from typing import cast
17
+ from typing import Generic
18
+ from typing import Literal
19
+ from typing import overload
20
+ from typing import TYPE_CHECKING
21
+ from typing import TypeVar
22
+ from typing import Union
23
+
24
+ from .row import Row
25
+ from .row import RowMapping
26
+ from .. import exc
27
+ from ..util import HasMemoized_ro_memoized_attribute
28
+ from ..util.typing import Self
29
+ from ..util.typing import TupleAny
30
+ from ..util.typing import Unpack
31
+
32
+ if TYPE_CHECKING:
33
+ from .result import _ProcessorsType
34
+ from .result import Result
35
+ from .result import ResultMetaData
36
+
37
+ # START GENERATED CYTHON IMPORT
38
+ # This section is automatically generated by the script tools/cython_imports.py
39
+ try:
40
+ # NOTE: the cython compiler needs this "import cython" in the file, it
41
+ # can't be only "from sqlalchemy.util import cython" with the fallback
42
+ # in that module
43
+ import cython
44
+ except ModuleNotFoundError:
45
+ from sqlalchemy.util import cython
46
+
47
+
48
+ def _is_compiled() -> bool:
49
+ """Utility function to indicate if this module is compiled or not."""
50
+ return cython.compiled # type: ignore[no-any-return,unused-ignore]
51
+
52
+
53
+ # END GENERATED CYTHON IMPORT
54
+
55
+ if cython.compiled:
56
+ from cython.cimports.cpython import Py_INCREF
57
+ from cython.cimports.cpython import PyList_New
58
+ from cython.cimports.cpython import PyList_SET_ITEM
59
+ from cython.cimports.cpython import PyTuple_New
60
+ from cython.cimports.cpython import PyTuple_SET_ITEM
61
+
62
+
63
+ _RowData = Row[Unpack[TupleAny]] | RowMapping | Any
64
+ """A generic form of "row" that accommodates for the different kinds of
65
+ "rows" that different result objects return, including row, row mapping, and
66
+ scalar values"""
67
+ _R = TypeVar("_R", bound=_RowData)
68
+ _T = TypeVar("_T", bound=Any)
69
+
70
+ _InterimRowType = Union[_R, TupleAny]
71
+ """a catchall "anything" kind of return type that can be applied
72
+ across all the result types
73
+
74
+ """
75
+
76
+ _UniqueFilterType = Callable[[Any], Any]
77
+ _UniqueFilterStateType = tuple[set[Any], _UniqueFilterType | None]
78
+
79
+ _FLAG_SIMPLE = cython.declare(cython.const[cython.char], 0)
80
+ _FLAG_SCALAR_TO_TUPLE = cython.declare(cython.const[cython.char], 1)
81
+ _FLAG_TUPLE_FILTER = cython.declare(cython.const[cython.char], 2)
82
+
83
+
84
+ # a symbol that indicates to internal Result methods that
85
+ # "no row is returned". We can't use None for those cases where a scalar
86
+ # filter is applied to rows.
87
+ class _NoRow(Enum):
88
+ _NO_ROW = 0
89
+
90
+
91
+ _NO_ROW = _NoRow._NO_ROW
92
+
93
+
94
+ class BaseResultInternal(Generic[_R]):
95
+ __slots__ = ()
96
+
97
+ _real_result: Result[Unpack[TupleAny]] | None = None
98
+ _generate_rows: bool = True
99
+ _row_logging_fn: Callable[[Any], Any] | None
100
+
101
+ _unique_filter_state: _UniqueFilterStateType | None = None
102
+ _post_creational_filter: Callable[[Any], Any] | None = None
103
+
104
+ _metadata: ResultMetaData
105
+
106
+ _source_supports_scalars: bool
107
+ _yield_per: int | None
108
+
109
+ def _fetchiter_impl(
110
+ self,
111
+ ) -> Iterator[_InterimRowType[Row[Unpack[TupleAny]]]]:
112
+ raise NotImplementedError()
113
+
114
+ def _fetchone_impl(
115
+ self, hard_close: bool = False
116
+ ) -> _InterimRowType[Row[Unpack[TupleAny]]] | None:
117
+ raise NotImplementedError()
118
+
119
+ def _fetchmany_impl(
120
+ self, size: int | None = None
121
+ ) -> list[_InterimRowType[Row[Unpack[TupleAny]]]]:
122
+ raise NotImplementedError()
123
+
124
+ def _fetchall_impl(
125
+ self,
126
+ ) -> list[_InterimRowType[Row[Unpack[TupleAny]]]]:
127
+ raise NotImplementedError()
128
+
129
+ def _soft_close(self, hard: bool = False) -> None:
130
+ raise NotImplementedError()
131
+
132
+ @HasMemoized_ro_memoized_attribute
133
+ def _row_getter(
134
+ self,
135
+ ) -> tuple[
136
+ Callable[..., _R] | None,
137
+ Callable[..., Sequence[_R]] | None,
138
+ Callable[..., Sequence[Any]] | None,
139
+ ]:
140
+ """Return a three-tuple of callables
141
+ ``(single_row, many_rows, interim_rows)``.
142
+
143
+ ``single_row`` and ``many_rows`` produce :class:`.Row` objects for
144
+ one input row or a sequence of them. ``interim_rows`` produces
145
+ rows in "interim" form for a sequence of input rows: plain tuples
146
+ with result processors and tuple filters applied but no
147
+ :class:`.Row` construction, falling back to ``many_rows`` when
148
+ Row objects are required (row logging, scalar sources).
149
+
150
+ """
151
+ real_result = self if self._real_result is None else self._real_result
152
+
153
+ metadata = self._metadata
154
+ tuple_filters = metadata._tuplefilter
155
+ flag: cython.char = _FLAG_SIMPLE
156
+
157
+ if real_result._source_supports_scalars:
158
+ if not self._generate_rows:
159
+ return None, None, None
160
+ else:
161
+ flag = _FLAG_SCALAR_TO_TUPLE
162
+ elif tuple_filters is not None:
163
+ flag = _FLAG_TUPLE_FILTER
164
+
165
+ processors: tuple
166
+ proc_valid: tuple
167
+
168
+ if metadata._effective_processors is not None:
169
+ ep = metadata._effective_processors
170
+ if flag == _FLAG_TUPLE_FILTER:
171
+ ep = tuple_filters(ep)
172
+
173
+ processors = tuple(ep)
174
+ proc_valid = tuple(
175
+ [i for i, p in enumerate(processors) if p is not None]
176
+ )
177
+ else:
178
+ processors = ()
179
+ proc_valid = ()
180
+
181
+ proc_size: cython.Py_ssize_t = len(processors)
182
+ log_row = real_result._row_logging_fn
183
+ has_log_row: cython.bint = log_row is not None
184
+
185
+ key_to_index = metadata._key_to_index
186
+ _Row = Row
187
+
188
+ if flag == _FLAG_SIMPLE and proc_size == 0 and not has_log_row:
189
+ # just build the rows
190
+
191
+ def single_row_simple(input_row: Sequence[Any], /) -> Row:
192
+ return _Row(metadata, None, key_to_index, input_row)
193
+
194
+ if cython.compiled:
195
+
196
+ def many_rows_simple(rows: Sequence[Any], /) -> list[Any]:
197
+ size: cython.Py_hash_t = len(rows)
198
+ i: cython.Py_ssize_t
199
+ result: list = PyList_New(size)
200
+ for i in range(size):
201
+ row: object = _Row(
202
+ metadata, None, key_to_index, rows[i]
203
+ )
204
+ Py_INCREF(row)
205
+ PyList_SET_ITEM(result, i, row)
206
+ return result
207
+
208
+ else:
209
+
210
+ def many_rows_simple(rows: Sequence[Any], /) -> list[Any]:
211
+ return [
212
+ _Row(metadata, None, key_to_index, row) for row in rows
213
+ ]
214
+
215
+ def interim_rows_simple(rows: Sequence[Any], /) -> Sequence[Any]:
216
+ # interim rows must be tuples so that position-based
217
+ # getters and slices apply; most DBAPIs return tuples
218
+ # already
219
+ if rows and type(rows[0]) is not tuple:
220
+ return [tuple(row) for row in rows]
221
+ return rows
222
+
223
+ return single_row_simple, many_rows_simple, interim_rows_simple # type: ignore[return-value] # noqa: E501
224
+
225
+ first_row: cython.bint = True
226
+
227
+ def single_row(input_row: Sequence[Any], /) -> Row:
228
+ nonlocal first_row
229
+
230
+ if flag == _FLAG_SCALAR_TO_TUPLE:
231
+ input_row = (input_row,)
232
+ elif flag == _FLAG_TUPLE_FILTER:
233
+ input_row = tuple_filters(input_row)
234
+
235
+ if proc_size != 0:
236
+ if first_row:
237
+ first_row = False
238
+ assert len(input_row) == proc_size
239
+ input_row = _apply_processors(
240
+ processors, proc_size, proc_valid, input_row
241
+ )
242
+
243
+ row: Row = _Row(metadata, None, key_to_index, input_row)
244
+ if has_log_row:
245
+ row = log_row(row)
246
+ return row
247
+
248
+ if cython.compiled:
249
+
250
+ def many_rows(rows: Sequence[Any], /) -> list[Any]:
251
+ size: cython.Py_hash_t = len(rows)
252
+ i: cython.Py_ssize_t
253
+ result: list = PyList_New(size)
254
+ for i in range(size):
255
+ row: object = single_row(rows[i])
256
+ Py_INCREF(row)
257
+ PyList_SET_ITEM(result, i, row)
258
+ return result
259
+
260
+ else:
261
+
262
+ def many_rows(rows: Sequence[Any], /) -> list[Any]:
263
+ return [single_row(row) for row in rows]
264
+
265
+ if flag == _FLAG_SCALAR_TO_TUPLE or has_log_row:
266
+ # scalar-source rows have no tuple form; row logging requires
267
+ # the Row objects themselves
268
+ interim_rows = many_rows
269
+ else:
270
+
271
+ def single_interim_row(input_row: Sequence[Any], /) -> Any:
272
+ if flag == _FLAG_TUPLE_FILTER:
273
+ input_row = tuple_filters(input_row)
274
+ if proc_size != 0:
275
+ input_row = _apply_processors(
276
+ processors, proc_size, proc_valid, input_row
277
+ )
278
+ elif type(input_row) is not tuple:
279
+ input_row = tuple(input_row)
280
+ return input_row
281
+
282
+ if cython.compiled:
283
+
284
+ def interim_rows(rows: Sequence[Any], /) -> Sequence[Any]:
285
+ size: cython.Py_hash_t = len(rows)
286
+ i: cython.Py_ssize_t
287
+ result: list = PyList_New(size)
288
+ for i in range(size):
289
+ row: object = single_interim_row(rows[i])
290
+ Py_INCREF(row)
291
+ PyList_SET_ITEM(result, i, row)
292
+ return result
293
+
294
+ else:
295
+
296
+ def interim_rows(rows: Sequence[Any], /) -> Sequence[Any]:
297
+ return [single_interim_row(row) for row in rows]
298
+
299
+ return single_row, many_rows, interim_rows # type: ignore[return-value] # noqa: E501
300
+
301
+ @HasMemoized_ro_memoized_attribute
302
+ def _iterator_getter(self) -> Callable[[], Iterator[_R]]:
303
+ make_row = self._row_getter[0]
304
+
305
+ post_creational_filter = self._post_creational_filter
306
+
307
+ if self._unique_filter_state is not None:
308
+ uniques: set
309
+ uniques, strategy = self._unique_strategy
310
+
311
+ def iterrows() -> Iterator[_R]:
312
+ for raw_row in self._fetchiter_impl():
313
+ row = (
314
+ make_row(raw_row) if make_row is not None else raw_row
315
+ )
316
+ hashed = strategy(row) if strategy is not None else row
317
+ if hashed in uniques:
318
+ continue
319
+ uniques.add(hashed)
320
+ if post_creational_filter is not None:
321
+ row = post_creational_filter(row)
322
+ yield row
323
+
324
+ else:
325
+
326
+ def iterrows() -> Iterator[_R]:
327
+ for raw_row in self._fetchiter_impl():
328
+ row = (
329
+ make_row(raw_row) if make_row is not None else raw_row
330
+ )
331
+ if post_creational_filter is not None:
332
+ row = post_creational_filter(row)
333
+ yield row
334
+
335
+ return iterrows
336
+
337
+ def _raw_all_tuples(self) -> Sequence[tuple[Any, ...]]:
338
+ """Return all remaining rows as plain processed tuples, as produced
339
+ by the ``interim_rows`` element of :attr:`._row_getter`;
340
+ :class:`.Row` objects are produced instead where required (row
341
+ logging, scalar sources).
342
+
343
+ Used by ORM loading, whose row getters are position-based and
344
+ accept any tuple-like row.
345
+
346
+ Uniquing and post-creational filters are not applied here, so
347
+ may not be present on the :class:`.Result` when this method is
348
+ used.
349
+
350
+ """
351
+ assert self._unique_filter_state is None
352
+ assert self._post_creational_filter is None
353
+ interim_rows = self._row_getter[2]
354
+ assert interim_rows is not None
355
+ rows = self._fetchall_impl()
356
+ return interim_rows(rows)
357
+
358
+ def _allrows(self) -> Sequence[_R]:
359
+ post_creational_filter = self._post_creational_filter
360
+
361
+ make_rows = self._row_getter[1]
362
+
363
+ rows = self._fetchall_impl()
364
+ made_rows: Sequence[_InterimRowType[_R]]
365
+ if make_rows is not None:
366
+ made_rows = make_rows(rows)
367
+ else:
368
+ made_rows = rows
369
+
370
+ interim_rows: Sequence[_R]
371
+
372
+ if self._unique_filter_state is not None:
373
+ uniques: set
374
+ uniques, strategy = self._unique_strategy
375
+ interim_rows = _apply_unique_strategy(
376
+ made_rows, [], uniques, strategy
377
+ )
378
+ else:
379
+ interim_rows = made_rows # type: ignore[assignment]
380
+
381
+ if post_creational_filter is not None:
382
+ interim_rows = [
383
+ post_creational_filter(row) for row in interim_rows
384
+ ]
385
+ return interim_rows
386
+
387
+ @HasMemoized_ro_memoized_attribute
388
+ def _onerow_getter(
389
+ self,
390
+ ) -> Callable[[Self], Literal[_NoRow._NO_ROW] | _R]:
391
+ make_row = self._row_getter[0]
392
+
393
+ post_creational_filter = self._post_creational_filter
394
+
395
+ if self._unique_filter_state is not None:
396
+ uniques: set
397
+ uniques, strategy = self._unique_strategy
398
+
399
+ def onerow(self: Self) -> Literal[_NoRow._NO_ROW] | _R:
400
+ while True:
401
+ row = self._fetchone_impl()
402
+ if row is None:
403
+ return _NO_ROW
404
+ else:
405
+ obj: _InterimRowType[Any] = (
406
+ make_row(row) if make_row is not None else row
407
+ )
408
+ hashed = strategy(obj) if strategy is not None else obj
409
+ if hashed in uniques:
410
+ continue
411
+ uniques.add(hashed)
412
+ if post_creational_filter is not None:
413
+ obj = post_creational_filter(obj)
414
+ return obj # type: ignore[return-value]
415
+
416
+ else:
417
+
418
+ def onerow(self: Self) -> Literal[_NoRow._NO_ROW] | _R:
419
+ row = self._fetchone_impl()
420
+ if row is None:
421
+ return _NO_ROW
422
+ else:
423
+ interim_row: _InterimRowType[Any] = (
424
+ make_row(row) if make_row is not None else row
425
+ )
426
+ if post_creational_filter is not None:
427
+ interim_row = post_creational_filter(interim_row)
428
+ return interim_row # type: ignore[return-value]
429
+
430
+ return onerow
431
+
432
+ @HasMemoized_ro_memoized_attribute
433
+ def _manyrow_getter(self) -> Callable[[Self, int | None], Sequence[_R]]:
434
+ make_rows = self._row_getter[1]
435
+ real_result = self if self._real_result is None else self._real_result
436
+ yield_per = real_result._yield_per
437
+
438
+ post_creational_filter = self._post_creational_filter
439
+
440
+ if self._unique_filter_state:
441
+ uniques: set
442
+ uniques, strategy = self._unique_strategy
443
+
444
+ def manyrows(self: Self, num: int | None, /) -> Sequence[_R]:
445
+ made_rows: Sequence[Any]
446
+ collect: list[_R] = []
447
+
448
+ _manyrows = self._fetchmany_impl
449
+
450
+ if num is None:
451
+ # if None is passed, we don't know the default
452
+ # manyrows number, DBAPI has this as cursor.arraysize
453
+ # different DBAPIs / fetch strategies may be different.
454
+ # do a fetch to find what the number is. if there are
455
+ # only fewer rows left, then it doesn't matter.
456
+ if yield_per:
457
+ num_required = num = yield_per
458
+ else:
459
+ rows = _manyrows()
460
+ num = len(rows)
461
+ made_rows = (
462
+ rows if make_rows is None else make_rows(rows)
463
+ )
464
+ _apply_unique_strategy(
465
+ made_rows, collect, uniques, strategy
466
+ )
467
+ num_required = num - len(collect)
468
+ else:
469
+ num_required = num
470
+
471
+ assert num is not None
472
+
473
+ while num_required:
474
+ rows = _manyrows(num_required)
475
+ if not rows:
476
+ break
477
+
478
+ made_rows = rows if make_rows is None else make_rows(rows)
479
+ _apply_unique_strategy(
480
+ made_rows, collect, uniques, strategy
481
+ )
482
+ num_required = num - len(collect)
483
+
484
+ if post_creational_filter is not None:
485
+ collect = [post_creational_filter(row) for row in collect]
486
+ return collect
487
+
488
+ else:
489
+
490
+ def manyrows(self: Self, num: int | None, /) -> Sequence[_R]:
491
+ if num is None:
492
+ num = yield_per
493
+
494
+ rows: Sequence = self._fetchmany_impl(num)
495
+ if make_rows is not None:
496
+ rows = make_rows(rows)
497
+ if post_creational_filter is not None:
498
+ rows = [post_creational_filter(row) for row in rows]
499
+ return rows
500
+
501
+ return manyrows
502
+
503
+ @overload
504
+ def _only_one_row(
505
+ self: BaseResultInternal[Row[_T, Unpack[TupleAny]]],
506
+ raise_for_second_row: bool,
507
+ raise_for_none: bool,
508
+ scalar: Literal[True],
509
+ ) -> _T: ...
510
+
511
+ @overload
512
+ def _only_one_row(
513
+ self,
514
+ raise_for_second_row: bool,
515
+ raise_for_none: Literal[True],
516
+ scalar: bool,
517
+ ) -> _R: ...
518
+
519
+ @overload
520
+ def _only_one_row(
521
+ self,
522
+ raise_for_second_row: bool,
523
+ raise_for_none: bool,
524
+ scalar: bool,
525
+ ) -> _R | None: ...
526
+
527
+ def _only_one_row(
528
+ self,
529
+ raise_for_second_row: bool,
530
+ raise_for_none: bool,
531
+ scalar: bool,
532
+ ) -> _R | None:
533
+ onerow = self._fetchone_impl
534
+
535
+ row = onerow(hard_close=True)
536
+ if row is None:
537
+ if raise_for_none:
538
+ raise exc.NoResultFound(
539
+ "No row was found when one was required"
540
+ )
541
+ else:
542
+ return None
543
+
544
+ if scalar and self._source_supports_scalars:
545
+ self._generate_rows = False
546
+ make_row = None
547
+ else:
548
+ make_row = self._row_getter[0]
549
+
550
+ try:
551
+ row = make_row(row) if make_row is not None else row # type: ignore[assignment] # noqa: E501
552
+ except:
553
+ self._soft_close(hard=True)
554
+ raise
555
+
556
+ if raise_for_second_row:
557
+ if self._unique_filter_state:
558
+ # for no second row but uniqueness, need to essentially
559
+ # consume the entire result :(
560
+ strategy = self._unique_strategy[1]
561
+
562
+ existing_row_hash = (
563
+ strategy(row) if strategy is not None else row
564
+ )
565
+
566
+ while True:
567
+ next_row: Any = onerow(hard_close=True)
568
+ if next_row is None:
569
+ next_row = _NO_ROW
570
+ break
571
+
572
+ try:
573
+ next_row = (
574
+ make_row(next_row)
575
+ if make_row is not None
576
+ else next_row
577
+ )
578
+
579
+ if strategy is not None:
580
+ # assert next_row is not _NO_ROW
581
+ if existing_row_hash == strategy(next_row):
582
+ continue
583
+ elif row == next_row:
584
+ continue
585
+ # here, we have a row and it's different
586
+ break
587
+ except:
588
+ self._soft_close(hard=True)
589
+ raise
590
+ else:
591
+ next_row = onerow(hard_close=True)
592
+ if next_row is None:
593
+ next_row = _NO_ROW
594
+
595
+ if next_row is not _NO_ROW:
596
+ self._soft_close(hard=True)
597
+ raise exc.MultipleResultsFound(
598
+ "Multiple rows were found when exactly one was required"
599
+ if raise_for_none
600
+ else "Multiple rows were found when one or none "
601
+ "was required"
602
+ )
603
+ else:
604
+ next_row = _NO_ROW
605
+ # if we checked for second row then that would have
606
+ # closed us :)
607
+ self._soft_close(hard=True)
608
+
609
+ if not scalar:
610
+ post_creational_filter = self._post_creational_filter
611
+ if post_creational_filter is not None:
612
+ row = post_creational_filter(row)
613
+
614
+ if scalar and make_row is not None:
615
+ return row[0] # type: ignore[no-any-return]
616
+ else:
617
+ return row # type: ignore[return-value]
618
+
619
+ def _iter_impl(self) -> Iterator[_R]:
620
+ return self._iterator_getter()
621
+
622
+ def _next_impl(self) -> _R:
623
+ row = self._onerow_getter(self)
624
+ if row is _NO_ROW:
625
+ raise StopIteration()
626
+ else:
627
+ return row
628
+
629
+ @HasMemoized_ro_memoized_attribute
630
+ def _unique_strategy(self) -> _UniqueFilterStateType:
631
+ assert self._unique_filter_state is not None
632
+ uniques, strategy = self._unique_filter_state
633
+
634
+ if (
635
+ strategy is None
636
+ and self._metadata._create_unique_filters is not None
637
+ ):
638
+ real_result = cast(
639
+ "Result[Any]",
640
+ self if self._real_result is None else self._real_result,
641
+ )
642
+ filters = self._metadata._create_unique_filters(real_result)
643
+ if (
644
+ real_result._source_supports_scalars
645
+ and not self._generate_rows
646
+ ):
647
+ strategy = filters[0]
648
+ else:
649
+ if self._metadata._tuplefilter is not None:
650
+ filters = self._metadata._tuplefilter(filters)
651
+
652
+ strategy = operator.methodcaller("_filter_on_values", filters)
653
+ return uniques, strategy
654
+
655
+
656
+ if cython.compiled:
657
+
658
+ @cython.inline
659
+ @cython.cfunc
660
+ @cython.wraparound(False)
661
+ @cython.boundscheck(False)
662
+ def _apply_processors(
663
+ proc: tuple,
664
+ proc_size: cython.Py_ssize_t,
665
+ proc_valid: object, # used only by python impl
666
+ data: Sequence,
667
+ ) -> tuple[Any, ...]:
668
+ res: tuple = PyTuple_New(proc_size)
669
+ i: cython.Py_ssize_t
670
+ for i in range(proc_size):
671
+ p = proc[i]
672
+ if p is not None:
673
+ value = p(data[i])
674
+ else:
675
+ value = data[i]
676
+ Py_INCREF(value)
677
+ PyTuple_SET_ITEM(res, i, value)
678
+ return res
679
+
680
+ else:
681
+
682
+ def _apply_processors(
683
+ proc: _ProcessorsType,
684
+ proc_size: int, # used only by cython impl
685
+ proc_valid: tuple[int, ...],
686
+ data: Sequence[Any],
687
+ ) -> tuple[Any, ...]:
688
+ res = list(data)
689
+ for i in proc_valid:
690
+ res[i] = proc[i](res[i])
691
+ return tuple(res)
692
+
693
+
694
+ @cython.inline
695
+ @cython.cfunc
696
+ def _apply_unique_strategy(
697
+ rows: Sequence[Any],
698
+ destination: list[Any],
699
+ uniques: set[Any],
700
+ strategy: Callable[[Any], Any] | None,
701
+ ) -> list[Any]:
702
+ i: cython.Py_ssize_t
703
+ has_strategy: cython.bint = strategy is not None
704
+ for i in range(len(rows)):
705
+ row = rows[i]
706
+ hashed = strategy(row) if has_strategy else row
707
+ if hashed in uniques:
708
+ continue
709
+ uniques.add(hashed)
710
+ destination.append(row)
711
+ return destination