SQLAlchemy 2.0.36__cp313-cp313-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 (273) hide show
  1. SQLAlchemy-2.0.36.dist-info/LICENSE +19 -0
  2. SQLAlchemy-2.0.36.dist-info/METADATA +243 -0
  3. SQLAlchemy-2.0.36.dist-info/RECORD +273 -0
  4. SQLAlchemy-2.0.36.dist-info/WHEEL +5 -0
  5. SQLAlchemy-2.0.36.dist-info/top_level.txt +1 -0
  6. sqlalchemy/__init__.py +294 -0
  7. sqlalchemy/connectors/__init__.py +18 -0
  8. sqlalchemy/connectors/aioodbc.py +174 -0
  9. sqlalchemy/connectors/asyncio.py +213 -0
  10. sqlalchemy/connectors/pyodbc.py +249 -0
  11. sqlalchemy/cyextension/__init__.py +6 -0
  12. sqlalchemy/cyextension/collections.cp313-win32.pyd +0 -0
  13. sqlalchemy/cyextension/collections.pyx +409 -0
  14. sqlalchemy/cyextension/immutabledict.cp313-win32.pyd +0 -0
  15. sqlalchemy/cyextension/immutabledict.pxd +8 -0
  16. sqlalchemy/cyextension/immutabledict.pyx +133 -0
  17. sqlalchemy/cyextension/processors.cp313-win32.pyd +0 -0
  18. sqlalchemy/cyextension/processors.pyx +68 -0
  19. sqlalchemy/cyextension/resultproxy.cp313-win32.pyd +0 -0
  20. sqlalchemy/cyextension/resultproxy.pyx +102 -0
  21. sqlalchemy/cyextension/util.cp313-win32.pyd +0 -0
  22. sqlalchemy/cyextension/util.pyx +91 -0
  23. sqlalchemy/dialects/__init__.py +61 -0
  24. sqlalchemy/dialects/_typing.py +25 -0
  25. sqlalchemy/dialects/mssql/__init__.py +88 -0
  26. sqlalchemy/dialects/mssql/aioodbc.py +64 -0
  27. sqlalchemy/dialects/mssql/base.py +4010 -0
  28. sqlalchemy/dialects/mssql/information_schema.py +254 -0
  29. sqlalchemy/dialects/mssql/json.py +133 -0
  30. sqlalchemy/dialects/mssql/provision.py +162 -0
  31. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  32. sqlalchemy/dialects/mssql/pyodbc.py +745 -0
  33. sqlalchemy/dialects/mysql/__init__.py +101 -0
  34. sqlalchemy/dialects/mysql/aiomysql.py +333 -0
  35. sqlalchemy/dialects/mysql/asyncmy.py +337 -0
  36. sqlalchemy/dialects/mysql/base.py +3494 -0
  37. sqlalchemy/dialects/mysql/cymysql.py +84 -0
  38. sqlalchemy/dialects/mysql/dml.py +219 -0
  39. sqlalchemy/dialects/mysql/enumerated.py +244 -0
  40. sqlalchemy/dialects/mysql/expression.py +141 -0
  41. sqlalchemy/dialects/mysql/json.py +81 -0
  42. sqlalchemy/dialects/mysql/mariadb.py +32 -0
  43. sqlalchemy/dialects/mysql/mariadbconnector.py +277 -0
  44. sqlalchemy/dialects/mysql/mysqlconnector.py +180 -0
  45. sqlalchemy/dialects/mysql/mysqldb.py +303 -0
  46. sqlalchemy/dialects/mysql/provision.py +110 -0
  47. sqlalchemy/dialects/mysql/pymysql.py +137 -0
  48. sqlalchemy/dialects/mysql/pyodbc.py +138 -0
  49. sqlalchemy/dialects/mysql/reflection.py +677 -0
  50. sqlalchemy/dialects/mysql/reserved_words.py +571 -0
  51. sqlalchemy/dialects/mysql/types.py +774 -0
  52. sqlalchemy/dialects/oracle/__init__.py +67 -0
  53. sqlalchemy/dialects/oracle/base.py +3271 -0
  54. sqlalchemy/dialects/oracle/cx_oracle.py +1483 -0
  55. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  56. sqlalchemy/dialects/oracle/oracledb.py +431 -0
  57. sqlalchemy/dialects/oracle/provision.py +220 -0
  58. sqlalchemy/dialects/oracle/types.py +287 -0
  59. sqlalchemy/dialects/postgresql/__init__.py +167 -0
  60. sqlalchemy/dialects/postgresql/_psycopg_common.py +187 -0
  61. sqlalchemy/dialects/postgresql/array.py +425 -0
  62. sqlalchemy/dialects/postgresql/asyncpg.py +1274 -0
  63. sqlalchemy/dialects/postgresql/base.py +5008 -0
  64. sqlalchemy/dialects/postgresql/dml.py +310 -0
  65. sqlalchemy/dialects/postgresql/ext.py +496 -0
  66. sqlalchemy/dialects/postgresql/hstore.py +397 -0
  67. sqlalchemy/dialects/postgresql/json.py +333 -0
  68. sqlalchemy/dialects/postgresql/named_types.py +509 -0
  69. sqlalchemy/dialects/postgresql/operators.py +129 -0
  70. sqlalchemy/dialects/postgresql/pg8000.py +662 -0
  71. sqlalchemy/dialects/postgresql/pg_catalog.py +300 -0
  72. sqlalchemy/dialects/postgresql/provision.py +175 -0
  73. sqlalchemy/dialects/postgresql/psycopg.py +772 -0
  74. sqlalchemy/dialects/postgresql/psycopg2.py +886 -0
  75. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  76. sqlalchemy/dialects/postgresql/ranges.py +1029 -0
  77. sqlalchemy/dialects/postgresql/types.py +303 -0
  78. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  79. sqlalchemy/dialects/sqlite/aiosqlite.py +396 -0
  80. sqlalchemy/dialects/sqlite/base.py +2805 -0
  81. sqlalchemy/dialects/sqlite/dml.py +240 -0
  82. sqlalchemy/dialects/sqlite/json.py +92 -0
  83. sqlalchemy/dialects/sqlite/provision.py +198 -0
  84. sqlalchemy/dialects/sqlite/pysqlcipher.py +155 -0
  85. sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
  86. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  87. sqlalchemy/engine/__init__.py +62 -0
  88. sqlalchemy/engine/_py_processors.py +136 -0
  89. sqlalchemy/engine/_py_row.py +128 -0
  90. sqlalchemy/engine/_py_util.py +74 -0
  91. sqlalchemy/engine/base.py +3375 -0
  92. sqlalchemy/engine/characteristics.py +155 -0
  93. sqlalchemy/engine/create.py +875 -0
  94. sqlalchemy/engine/cursor.py +2181 -0
  95. sqlalchemy/engine/default.py +2365 -0
  96. sqlalchemy/engine/events.py +951 -0
  97. sqlalchemy/engine/interfaces.py +3403 -0
  98. sqlalchemy/engine/mock.py +131 -0
  99. sqlalchemy/engine/processors.py +61 -0
  100. sqlalchemy/engine/reflection.py +2098 -0
  101. sqlalchemy/engine/result.py +2382 -0
  102. sqlalchemy/engine/row.py +401 -0
  103. sqlalchemy/engine/strategies.py +19 -0
  104. sqlalchemy/engine/url.py +910 -0
  105. sqlalchemy/engine/util.py +167 -0
  106. sqlalchemy/event/__init__.py +25 -0
  107. sqlalchemy/event/api.py +225 -0
  108. sqlalchemy/event/attr.py +655 -0
  109. sqlalchemy/event/base.py +470 -0
  110. sqlalchemy/event/legacy.py +246 -0
  111. sqlalchemy/event/registry.py +386 -0
  112. sqlalchemy/events.py +17 -0
  113. sqlalchemy/exc.py +830 -0
  114. sqlalchemy/ext/__init__.py +11 -0
  115. sqlalchemy/ext/associationproxy.py +2013 -0
  116. sqlalchemy/ext/asyncio/__init__.py +25 -0
  117. sqlalchemy/ext/asyncio/base.py +279 -0
  118. sqlalchemy/ext/asyncio/engine.py +1466 -0
  119. sqlalchemy/ext/asyncio/exc.py +21 -0
  120. sqlalchemy/ext/asyncio/result.py +961 -0
  121. sqlalchemy/ext/asyncio/scoping.py +1614 -0
  122. sqlalchemy/ext/asyncio/session.py +1936 -0
  123. sqlalchemy/ext/automap.py +1691 -0
  124. sqlalchemy/ext/baked.py +574 -0
  125. sqlalchemy/ext/compiler.py +570 -0
  126. sqlalchemy/ext/declarative/__init__.py +65 -0
  127. sqlalchemy/ext/declarative/extensions.py +548 -0
  128. sqlalchemy/ext/horizontal_shard.py +481 -0
  129. sqlalchemy/ext/hybrid.py +1514 -0
  130. sqlalchemy/ext/indexable.py +341 -0
  131. sqlalchemy/ext/instrumentation.py +450 -0
  132. sqlalchemy/ext/mutable.py +1073 -0
  133. sqlalchemy/ext/mypy/__init__.py +6 -0
  134. sqlalchemy/ext/mypy/apply.py +320 -0
  135. sqlalchemy/ext/mypy/decl_class.py +515 -0
  136. sqlalchemy/ext/mypy/infer.py +590 -0
  137. sqlalchemy/ext/mypy/names.py +335 -0
  138. sqlalchemy/ext/mypy/plugin.py +303 -0
  139. sqlalchemy/ext/mypy/util.py +357 -0
  140. sqlalchemy/ext/orderinglist.py +416 -0
  141. sqlalchemy/ext/serializer.py +181 -0
  142. sqlalchemy/future/__init__.py +16 -0
  143. sqlalchemy/future/engine.py +15 -0
  144. sqlalchemy/inspection.py +174 -0
  145. sqlalchemy/log.py +288 -0
  146. sqlalchemy/orm/__init__.py +170 -0
  147. sqlalchemy/orm/_orm_constructors.py +2571 -0
  148. sqlalchemy/orm/_typing.py +179 -0
  149. sqlalchemy/orm/attributes.py +2835 -0
  150. sqlalchemy/orm/base.py +973 -0
  151. sqlalchemy/orm/bulk_persistence.py +2123 -0
  152. sqlalchemy/orm/clsregistry.py +571 -0
  153. sqlalchemy/orm/collections.py +1620 -0
  154. sqlalchemy/orm/context.py +3268 -0
  155. sqlalchemy/orm/decl_api.py +1883 -0
  156. sqlalchemy/orm/decl_base.py +2190 -0
  157. sqlalchemy/orm/dependency.py +1304 -0
  158. sqlalchemy/orm/descriptor_props.py +1076 -0
  159. sqlalchemy/orm/dynamic.py +300 -0
  160. sqlalchemy/orm/evaluator.py +379 -0
  161. sqlalchemy/orm/events.py +3261 -0
  162. sqlalchemy/orm/exc.py +228 -0
  163. sqlalchemy/orm/identity.py +302 -0
  164. sqlalchemy/orm/instrumentation.py +754 -0
  165. sqlalchemy/orm/interfaces.py +1474 -0
  166. sqlalchemy/orm/loading.py +1682 -0
  167. sqlalchemy/orm/mapped_collection.py +557 -0
  168. sqlalchemy/orm/mapper.py +4432 -0
  169. sqlalchemy/orm/path_registry.py +811 -0
  170. sqlalchemy/orm/persistence.py +1782 -0
  171. sqlalchemy/orm/properties.py +886 -0
  172. sqlalchemy/orm/query.py +3396 -0
  173. sqlalchemy/orm/relationships.py +3500 -0
  174. sqlalchemy/orm/scoping.py +2165 -0
  175. sqlalchemy/orm/session.py +5301 -0
  176. sqlalchemy/orm/state.py +1143 -0
  177. sqlalchemy/orm/state_changes.py +198 -0
  178. sqlalchemy/orm/strategies.py +3473 -0
  179. sqlalchemy/orm/strategy_options.py +2569 -0
  180. sqlalchemy/orm/sync.py +164 -0
  181. sqlalchemy/orm/unitofwork.py +796 -0
  182. sqlalchemy/orm/util.py +2424 -0
  183. sqlalchemy/orm/writeonly.py +678 -0
  184. sqlalchemy/pool/__init__.py +44 -0
  185. sqlalchemy/pool/base.py +1515 -0
  186. sqlalchemy/pool/events.py +370 -0
  187. sqlalchemy/pool/impl.py +581 -0
  188. sqlalchemy/py.typed +0 -0
  189. sqlalchemy/schema.py +70 -0
  190. sqlalchemy/sql/__init__.py +145 -0
  191. sqlalchemy/sql/_dml_constructors.py +140 -0
  192. sqlalchemy/sql/_elements_constructors.py +1850 -0
  193. sqlalchemy/sql/_orm_types.py +20 -0
  194. sqlalchemy/sql/_py_util.py +75 -0
  195. sqlalchemy/sql/_selectable_constructors.py +635 -0
  196. sqlalchemy/sql/_typing.py +460 -0
  197. sqlalchemy/sql/annotation.py +585 -0
  198. sqlalchemy/sql/base.py +2185 -0
  199. sqlalchemy/sql/cache_key.py +1057 -0
  200. sqlalchemy/sql/coercions.py +1405 -0
  201. sqlalchemy/sql/compiler.py +7818 -0
  202. sqlalchemy/sql/crud.py +1669 -0
  203. sqlalchemy/sql/ddl.py +1378 -0
  204. sqlalchemy/sql/default_comparator.py +552 -0
  205. sqlalchemy/sql/dml.py +1817 -0
  206. sqlalchemy/sql/elements.py +5499 -0
  207. sqlalchemy/sql/events.py +455 -0
  208. sqlalchemy/sql/expression.py +162 -0
  209. sqlalchemy/sql/functions.py +2055 -0
  210. sqlalchemy/sql/lambdas.py +1449 -0
  211. sqlalchemy/sql/naming.py +212 -0
  212. sqlalchemy/sql/operators.py +2579 -0
  213. sqlalchemy/sql/roles.py +323 -0
  214. sqlalchemy/sql/schema.py +6158 -0
  215. sqlalchemy/sql/selectable.py +7004 -0
  216. sqlalchemy/sql/sqltypes.py +3827 -0
  217. sqlalchemy/sql/traversals.py +1024 -0
  218. sqlalchemy/sql/type_api.py +2339 -0
  219. sqlalchemy/sql/util.py +1486 -0
  220. sqlalchemy/sql/visitors.py +1165 -0
  221. sqlalchemy/testing/__init__.py +96 -0
  222. sqlalchemy/testing/assertions.py +989 -0
  223. sqlalchemy/testing/assertsql.py +516 -0
  224. sqlalchemy/testing/asyncio.py +135 -0
  225. sqlalchemy/testing/config.py +427 -0
  226. sqlalchemy/testing/engines.py +472 -0
  227. sqlalchemy/testing/entities.py +117 -0
  228. sqlalchemy/testing/exclusions.py +435 -0
  229. sqlalchemy/testing/fixtures/__init__.py +28 -0
  230. sqlalchemy/testing/fixtures/base.py +366 -0
  231. sqlalchemy/testing/fixtures/mypy.py +312 -0
  232. sqlalchemy/testing/fixtures/orm.py +227 -0
  233. sqlalchemy/testing/fixtures/sql.py +503 -0
  234. sqlalchemy/testing/pickleable.py +155 -0
  235. sqlalchemy/testing/plugin/__init__.py +6 -0
  236. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  237. sqlalchemy/testing/plugin/plugin_base.py +779 -0
  238. sqlalchemy/testing/plugin/pytestplugin.py +868 -0
  239. sqlalchemy/testing/profiling.py +324 -0
  240. sqlalchemy/testing/provision.py +496 -0
  241. sqlalchemy/testing/requirements.py +1818 -0
  242. sqlalchemy/testing/schema.py +224 -0
  243. sqlalchemy/testing/suite/__init__.py +19 -0
  244. sqlalchemy/testing/suite/test_cte.py +211 -0
  245. sqlalchemy/testing/suite/test_ddl.py +389 -0
  246. sqlalchemy/testing/suite/test_deprecations.py +153 -0
  247. sqlalchemy/testing/suite/test_dialect.py +740 -0
  248. sqlalchemy/testing/suite/test_insert.py +630 -0
  249. sqlalchemy/testing/suite/test_reflection.py +3225 -0
  250. sqlalchemy/testing/suite/test_results.py +502 -0
  251. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  252. sqlalchemy/testing/suite/test_select.py +1999 -0
  253. sqlalchemy/testing/suite/test_sequence.py +317 -0
  254. sqlalchemy/testing/suite/test_types.py +2141 -0
  255. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  256. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  257. sqlalchemy/testing/util.py +537 -0
  258. sqlalchemy/testing/warnings.py +52 -0
  259. sqlalchemy/types.py +76 -0
  260. sqlalchemy/util/__init__.py +160 -0
  261. sqlalchemy/util/_collections.py +715 -0
  262. sqlalchemy/util/_concurrency_py3k.py +288 -0
  263. sqlalchemy/util/_has_cy.py +40 -0
  264. sqlalchemy/util/_py_collections.py +541 -0
  265. sqlalchemy/util/compat.py +301 -0
  266. sqlalchemy/util/concurrency.py +108 -0
  267. sqlalchemy/util/deprecations.py +401 -0
  268. sqlalchemy/util/langhelpers.py +2218 -0
  269. sqlalchemy/util/preloaded.py +150 -0
  270. sqlalchemy/util/queue.py +322 -0
  271. sqlalchemy/util/tool_support.py +201 -0
  272. sqlalchemy/util/topological.py +120 -0
  273. sqlalchemy/util/typing.py +629 -0
@@ -0,0 +1,1405 @@
1
+ # sql/coercions.py
2
+ # Copyright (C) 2005-2024 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: allow-untyped-defs, allow-untyped-calls
8
+
9
+ from __future__ import annotations
10
+
11
+ import collections.abc as collections_abc
12
+ import numbers
13
+ import re
14
+ import typing
15
+ from typing import Any
16
+ from typing import Callable
17
+ from typing import cast
18
+ from typing import Dict
19
+ from typing import Iterable
20
+ from typing import Iterator
21
+ from typing import List
22
+ from typing import NoReturn
23
+ from typing import Optional
24
+ from typing import overload
25
+ from typing import Sequence
26
+ from typing import Tuple
27
+ from typing import Type
28
+ from typing import TYPE_CHECKING
29
+ from typing import TypeVar
30
+ from typing import Union
31
+
32
+ from . import roles
33
+ from . import visitors
34
+ from ._typing import is_from_clause
35
+ from .base import ExecutableOption
36
+ from .base import Options
37
+ from .cache_key import HasCacheKey
38
+ from .visitors import Visitable
39
+ from .. import exc
40
+ from .. import inspection
41
+ from .. import util
42
+ from ..util.typing import Literal
43
+
44
+ if typing.TYPE_CHECKING:
45
+ # elements lambdas schema selectable are set by __init__
46
+ from . import elements
47
+ from . import lambdas
48
+ from . import schema
49
+ from . import selectable
50
+ from ._typing import _ColumnExpressionArgument
51
+ from ._typing import _ColumnsClauseArgument
52
+ from ._typing import _DDLColumnArgument
53
+ from ._typing import _DMLTableArgument
54
+ from ._typing import _FromClauseArgument
55
+ from .dml import _DMLTableElement
56
+ from .elements import BindParameter
57
+ from .elements import ClauseElement
58
+ from .elements import ColumnClause
59
+ from .elements import ColumnElement
60
+ from .elements import DQLDMLClauseElement
61
+ from .elements import NamedColumn
62
+ from .elements import SQLCoreOperations
63
+ from .schema import Column
64
+ from .selectable import _ColumnsClauseElement
65
+ from .selectable import _JoinTargetProtocol
66
+ from .selectable import FromClause
67
+ from .selectable import HasCTE
68
+ from .selectable import SelectBase
69
+ from .selectable import Subquery
70
+ from .visitors import _TraverseCallableType
71
+
72
+ _SR = TypeVar("_SR", bound=roles.SQLRole)
73
+ _F = TypeVar("_F", bound=Callable[..., Any])
74
+ _StringOnlyR = TypeVar("_StringOnlyR", bound=roles.StringRole)
75
+ _T = TypeVar("_T", bound=Any)
76
+
77
+
78
+ def _is_literal(element):
79
+ """Return whether or not the element is a "literal" in the context
80
+ of a SQL expression construct.
81
+
82
+ """
83
+
84
+ return not isinstance(
85
+ element,
86
+ (Visitable, schema.SchemaEventTarget),
87
+ ) and not hasattr(element, "__clause_element__")
88
+
89
+
90
+ def _deep_is_literal(element):
91
+ """Return whether or not the element is a "literal" in the context
92
+ of a SQL expression construct.
93
+
94
+ does a deeper more esoteric check than _is_literal. is used
95
+ for lambda elements that have to distinguish values that would
96
+ be bound vs. not without any context.
97
+
98
+ """
99
+
100
+ if isinstance(element, collections_abc.Sequence) and not isinstance(
101
+ element, str
102
+ ):
103
+ for elem in element:
104
+ if not _deep_is_literal(elem):
105
+ return False
106
+ else:
107
+ return True
108
+
109
+ return (
110
+ not isinstance(
111
+ element,
112
+ (
113
+ Visitable,
114
+ schema.SchemaEventTarget,
115
+ HasCacheKey,
116
+ Options,
117
+ util.langhelpers.symbol,
118
+ ),
119
+ )
120
+ and not hasattr(element, "__clause_element__")
121
+ and (
122
+ not isinstance(element, type)
123
+ or not issubclass(element, HasCacheKey)
124
+ )
125
+ )
126
+
127
+
128
+ def _document_text_coercion(
129
+ paramname: str, meth_rst: str, param_rst: str
130
+ ) -> Callable[[_F], _F]:
131
+ return util.add_parameter_text(
132
+ paramname,
133
+ (
134
+ ".. warning:: "
135
+ "The %s argument to %s can be passed as a Python string argument, "
136
+ "which will be treated "
137
+ "as **trusted SQL text** and rendered as given. **DO NOT PASS "
138
+ "UNTRUSTED INPUT TO THIS PARAMETER**."
139
+ )
140
+ % (param_rst, meth_rst),
141
+ )
142
+
143
+
144
+ def _expression_collection_was_a_list(
145
+ attrname: str,
146
+ fnname: str,
147
+ args: Union[Sequence[_T], Sequence[Sequence[_T]]],
148
+ ) -> Sequence[_T]:
149
+ if args and isinstance(args[0], (list, set, dict)) and len(args) == 1:
150
+ if isinstance(args[0], list):
151
+ raise exc.ArgumentError(
152
+ f'The "{attrname}" argument to {fnname}(), when '
153
+ "referring to a sequence "
154
+ "of items, is now passed as a series of positional "
155
+ "elements, rather than as a list. "
156
+ )
157
+ return cast("Sequence[_T]", args[0])
158
+
159
+ return cast("Sequence[_T]", args)
160
+
161
+
162
+ @overload
163
+ def expect(
164
+ role: Type[roles.TruncatedLabelRole],
165
+ element: Any,
166
+ **kw: Any,
167
+ ) -> str: ...
168
+
169
+
170
+ @overload
171
+ def expect(
172
+ role: Type[roles.DMLColumnRole],
173
+ element: Any,
174
+ *,
175
+ as_key: Literal[True] = ...,
176
+ **kw: Any,
177
+ ) -> str: ...
178
+
179
+
180
+ @overload
181
+ def expect(
182
+ role: Type[roles.LiteralValueRole],
183
+ element: Any,
184
+ **kw: Any,
185
+ ) -> BindParameter[Any]: ...
186
+
187
+
188
+ @overload
189
+ def expect(
190
+ role: Type[roles.DDLReferredColumnRole],
191
+ element: Any,
192
+ **kw: Any,
193
+ ) -> Column[Any]: ...
194
+
195
+
196
+ @overload
197
+ def expect(
198
+ role: Type[roles.DDLConstraintColumnRole],
199
+ element: Any,
200
+ **kw: Any,
201
+ ) -> Union[Column[Any], str]: ...
202
+
203
+
204
+ @overload
205
+ def expect(
206
+ role: Type[roles.StatementOptionRole],
207
+ element: Any,
208
+ **kw: Any,
209
+ ) -> DQLDMLClauseElement: ...
210
+
211
+
212
+ @overload
213
+ def expect(
214
+ role: Type[roles.LabeledColumnExprRole[Any]],
215
+ element: _ColumnExpressionArgument[_T],
216
+ **kw: Any,
217
+ ) -> NamedColumn[_T]: ...
218
+
219
+
220
+ @overload
221
+ def expect(
222
+ role: Union[
223
+ Type[roles.ExpressionElementRole[Any]],
224
+ Type[roles.LimitOffsetRole],
225
+ Type[roles.WhereHavingRole],
226
+ ],
227
+ element: _ColumnExpressionArgument[_T],
228
+ **kw: Any,
229
+ ) -> ColumnElement[_T]: ...
230
+
231
+
232
+ @overload
233
+ def expect(
234
+ role: Union[
235
+ Type[roles.ExpressionElementRole[Any]],
236
+ Type[roles.LimitOffsetRole],
237
+ Type[roles.WhereHavingRole],
238
+ Type[roles.OnClauseRole],
239
+ Type[roles.ColumnArgumentRole],
240
+ ],
241
+ element: Any,
242
+ **kw: Any,
243
+ ) -> ColumnElement[Any]: ...
244
+
245
+
246
+ @overload
247
+ def expect(
248
+ role: Type[roles.DMLTableRole],
249
+ element: _DMLTableArgument,
250
+ **kw: Any,
251
+ ) -> _DMLTableElement: ...
252
+
253
+
254
+ @overload
255
+ def expect(
256
+ role: Type[roles.HasCTERole],
257
+ element: HasCTE,
258
+ **kw: Any,
259
+ ) -> HasCTE: ...
260
+
261
+
262
+ @overload
263
+ def expect(
264
+ role: Type[roles.SelectStatementRole],
265
+ element: SelectBase,
266
+ **kw: Any,
267
+ ) -> SelectBase: ...
268
+
269
+
270
+ @overload
271
+ def expect(
272
+ role: Type[roles.FromClauseRole],
273
+ element: _FromClauseArgument,
274
+ **kw: Any,
275
+ ) -> FromClause: ...
276
+
277
+
278
+ @overload
279
+ def expect(
280
+ role: Type[roles.FromClauseRole],
281
+ element: SelectBase,
282
+ *,
283
+ explicit_subquery: Literal[True] = ...,
284
+ **kw: Any,
285
+ ) -> Subquery: ...
286
+
287
+
288
+ @overload
289
+ def expect(
290
+ role: Type[roles.ColumnsClauseRole],
291
+ element: _ColumnsClauseArgument[Any],
292
+ **kw: Any,
293
+ ) -> _ColumnsClauseElement: ...
294
+
295
+
296
+ @overload
297
+ def expect(
298
+ role: Type[roles.JoinTargetRole],
299
+ element: _JoinTargetProtocol,
300
+ **kw: Any,
301
+ ) -> _JoinTargetProtocol: ...
302
+
303
+
304
+ # catchall for not-yet-implemented overloads
305
+ @overload
306
+ def expect(
307
+ role: Type[_SR],
308
+ element: Any,
309
+ **kw: Any,
310
+ ) -> Any: ...
311
+
312
+
313
+ def expect(
314
+ role: Type[_SR],
315
+ element: Any,
316
+ *,
317
+ apply_propagate_attrs: Optional[ClauseElement] = None,
318
+ argname: Optional[str] = None,
319
+ post_inspect: bool = False,
320
+ disable_inspection: bool = False,
321
+ **kw: Any,
322
+ ) -> Any:
323
+ if (
324
+ role.allows_lambda
325
+ # note callable() will not invoke a __getattr__() method, whereas
326
+ # hasattr(obj, "__call__") will. by keeping the callable() check here
327
+ # we prevent most needless calls to hasattr() and therefore
328
+ # __getattr__(), which is present on ColumnElement.
329
+ and callable(element)
330
+ and hasattr(element, "__code__")
331
+ ):
332
+ return lambdas.LambdaElement(
333
+ element,
334
+ role,
335
+ lambdas.LambdaOptions(**kw),
336
+ apply_propagate_attrs=apply_propagate_attrs,
337
+ )
338
+
339
+ # major case is that we are given a ClauseElement already, skip more
340
+ # elaborate logic up front if possible
341
+ impl = _impl_lookup[role]
342
+
343
+ original_element = element
344
+
345
+ if not isinstance(
346
+ element,
347
+ (
348
+ elements.CompilerElement,
349
+ schema.SchemaItem,
350
+ schema.FetchedValue,
351
+ lambdas.PyWrapper,
352
+ ),
353
+ ):
354
+ resolved = None
355
+
356
+ if impl._resolve_literal_only:
357
+ resolved = impl._literal_coercion(element, **kw)
358
+ else:
359
+ original_element = element
360
+
361
+ is_clause_element = False
362
+
363
+ # this is a special performance optimization for ORM
364
+ # joins used by JoinTargetImpl that we don't go through the
365
+ # work of creating __clause_element__() when we only need the
366
+ # original QueryableAttribute, as the former will do clause
367
+ # adaption and all that which is just thrown away here.
368
+ if (
369
+ impl._skip_clauseelement_for_target_match
370
+ and isinstance(element, role)
371
+ and hasattr(element, "__clause_element__")
372
+ ):
373
+ is_clause_element = True
374
+ else:
375
+ while hasattr(element, "__clause_element__"):
376
+ is_clause_element = True
377
+
378
+ if not getattr(element, "is_clause_element", False):
379
+ element = element.__clause_element__()
380
+ else:
381
+ break
382
+
383
+ if not is_clause_element:
384
+ if impl._use_inspection and not disable_inspection:
385
+ insp = inspection.inspect(element, raiseerr=False)
386
+ if insp is not None:
387
+ if post_inspect:
388
+ insp._post_inspect
389
+ try:
390
+ resolved = insp.__clause_element__()
391
+ except AttributeError:
392
+ impl._raise_for_expected(original_element, argname)
393
+
394
+ if resolved is None:
395
+ resolved = impl._literal_coercion(
396
+ element, argname=argname, **kw
397
+ )
398
+ else:
399
+ resolved = element
400
+ elif isinstance(element, lambdas.PyWrapper):
401
+ resolved = element._sa__py_wrapper_literal(**kw)
402
+ else:
403
+ resolved = element
404
+
405
+ if apply_propagate_attrs is not None:
406
+ if typing.TYPE_CHECKING:
407
+ assert isinstance(resolved, (SQLCoreOperations, ClauseElement))
408
+
409
+ if not apply_propagate_attrs._propagate_attrs and getattr(
410
+ resolved, "_propagate_attrs", None
411
+ ):
412
+ apply_propagate_attrs._propagate_attrs = resolved._propagate_attrs
413
+
414
+ if impl._role_class in resolved.__class__.__mro__:
415
+ if impl._post_coercion:
416
+ resolved = impl._post_coercion(
417
+ resolved,
418
+ argname=argname,
419
+ original_element=original_element,
420
+ **kw,
421
+ )
422
+ return resolved
423
+ else:
424
+ return impl._implicit_coercions(
425
+ original_element, resolved, argname=argname, **kw
426
+ )
427
+
428
+
429
+ def expect_as_key(
430
+ role: Type[roles.DMLColumnRole], element: Any, **kw: Any
431
+ ) -> str:
432
+ kw.pop("as_key", None)
433
+ return expect(role, element, as_key=True, **kw)
434
+
435
+
436
+ def expect_col_expression_collection(
437
+ role: Type[roles.DDLConstraintColumnRole],
438
+ expressions: Iterable[_DDLColumnArgument],
439
+ ) -> Iterator[
440
+ Tuple[
441
+ Union[str, Column[Any]],
442
+ Optional[ColumnClause[Any]],
443
+ Optional[str],
444
+ Optional[Union[Column[Any], str]],
445
+ ]
446
+ ]:
447
+ for expr in expressions:
448
+ strname = None
449
+ column = None
450
+
451
+ resolved: Union[Column[Any], str] = expect(role, expr)
452
+ if isinstance(resolved, str):
453
+ assert isinstance(expr, str)
454
+ strname = resolved = expr
455
+ else:
456
+ cols: List[Column[Any]] = []
457
+ col_append: _TraverseCallableType[Column[Any]] = cols.append
458
+ visitors.traverse(resolved, {}, {"column": col_append})
459
+ if cols:
460
+ column = cols[0]
461
+ add_element = column if column is not None else strname
462
+
463
+ yield resolved, column, strname, add_element
464
+
465
+
466
+ class RoleImpl:
467
+ __slots__ = ("_role_class", "name", "_use_inspection")
468
+
469
+ def _literal_coercion(self, element, **kw):
470
+ raise NotImplementedError()
471
+
472
+ _post_coercion: Any = None
473
+ _resolve_literal_only = False
474
+ _skip_clauseelement_for_target_match = False
475
+
476
+ def __init__(self, role_class):
477
+ self._role_class = role_class
478
+ self.name = role_class._role_name
479
+ self._use_inspection = issubclass(role_class, roles.UsesInspection)
480
+
481
+ def _implicit_coercions(
482
+ self,
483
+ element: Any,
484
+ resolved: Any,
485
+ argname: Optional[str] = None,
486
+ **kw: Any,
487
+ ) -> Any:
488
+ self._raise_for_expected(element, argname, resolved)
489
+
490
+ def _raise_for_expected(
491
+ self,
492
+ element: Any,
493
+ argname: Optional[str] = None,
494
+ resolved: Optional[Any] = None,
495
+ *,
496
+ advice: Optional[str] = None,
497
+ code: Optional[str] = None,
498
+ err: Optional[Exception] = None,
499
+ **kw: Any,
500
+ ) -> NoReturn:
501
+ if resolved is not None and resolved is not element:
502
+ got = "%r object resolved from %r object" % (resolved, element)
503
+ else:
504
+ got = repr(element)
505
+
506
+ if argname:
507
+ msg = "%s expected for argument %r; got %s." % (
508
+ self.name,
509
+ argname,
510
+ got,
511
+ )
512
+ else:
513
+ msg = "%s expected, got %s." % (self.name, got)
514
+
515
+ if advice:
516
+ msg += " " + advice
517
+
518
+ raise exc.ArgumentError(msg, code=code) from err
519
+
520
+
521
+ class _Deannotate:
522
+ __slots__ = ()
523
+
524
+ def _post_coercion(self, resolved, **kw):
525
+ from .util import _deep_deannotate
526
+
527
+ return _deep_deannotate(resolved)
528
+
529
+
530
+ class _StringOnly:
531
+ __slots__ = ()
532
+
533
+ _resolve_literal_only = True
534
+
535
+
536
+ class _ReturnsStringKey(RoleImpl):
537
+ __slots__ = ()
538
+
539
+ def _implicit_coercions(self, element, resolved, argname=None, **kw):
540
+ if isinstance(element, str):
541
+ return element
542
+ else:
543
+ self._raise_for_expected(element, argname, resolved)
544
+
545
+ def _literal_coercion(self, element, **kw):
546
+ return element
547
+
548
+
549
+ class _ColumnCoercions(RoleImpl):
550
+ __slots__ = ()
551
+
552
+ def _warn_for_scalar_subquery_coercion(self):
553
+ util.warn(
554
+ "implicitly coercing SELECT object to scalar subquery; "
555
+ "please use the .scalar_subquery() method to produce a scalar "
556
+ "subquery.",
557
+ )
558
+
559
+ def _implicit_coercions(self, element, resolved, argname=None, **kw):
560
+ original_element = element
561
+ if not getattr(resolved, "is_clause_element", False):
562
+ self._raise_for_expected(original_element, argname, resolved)
563
+ elif resolved._is_select_base:
564
+ self._warn_for_scalar_subquery_coercion()
565
+ return resolved.scalar_subquery()
566
+ elif resolved._is_from_clause and isinstance(
567
+ resolved, selectable.Subquery
568
+ ):
569
+ self._warn_for_scalar_subquery_coercion()
570
+ return resolved.element.scalar_subquery()
571
+ elif self._role_class.allows_lambda and resolved._is_lambda_element:
572
+ return resolved
573
+ else:
574
+ self._raise_for_expected(original_element, argname, resolved)
575
+
576
+
577
+ def _no_text_coercion(
578
+ element: Any,
579
+ argname: Optional[str] = None,
580
+ exc_cls: Type[exc.SQLAlchemyError] = exc.ArgumentError,
581
+ extra: Optional[str] = None,
582
+ err: Optional[Exception] = None,
583
+ ) -> NoReturn:
584
+ raise exc_cls(
585
+ "%(extra)sTextual SQL expression %(expr)r %(argname)sshould be "
586
+ "explicitly declared as text(%(expr)r)"
587
+ % {
588
+ "expr": util.ellipses_string(element),
589
+ "argname": "for argument %s" % (argname,) if argname else "",
590
+ "extra": "%s " % extra if extra else "",
591
+ }
592
+ ) from err
593
+
594
+
595
+ class _NoTextCoercion(RoleImpl):
596
+ __slots__ = ()
597
+
598
+ def _literal_coercion(self, element, *, argname=None, **kw):
599
+ if isinstance(element, str) and issubclass(
600
+ elements.TextClause, self._role_class
601
+ ):
602
+ _no_text_coercion(element, argname)
603
+ else:
604
+ self._raise_for_expected(element, argname)
605
+
606
+
607
+ class _CoerceLiterals(RoleImpl):
608
+ __slots__ = ()
609
+ _coerce_consts = False
610
+ _coerce_star = False
611
+ _coerce_numerics = False
612
+
613
+ def _text_coercion(self, element, argname=None):
614
+ return _no_text_coercion(element, argname)
615
+
616
+ def _literal_coercion(self, element, *, argname=None, **kw):
617
+ if isinstance(element, str):
618
+ if self._coerce_star and element == "*":
619
+ return elements.ColumnClause("*", is_literal=True)
620
+ else:
621
+ return self._text_coercion(element, argname, **kw)
622
+
623
+ if self._coerce_consts:
624
+ if element is None:
625
+ return elements.Null()
626
+ elif element is False:
627
+ return elements.False_()
628
+ elif element is True:
629
+ return elements.True_()
630
+
631
+ if self._coerce_numerics and isinstance(element, (numbers.Number)):
632
+ return elements.ColumnClause(str(element), is_literal=True)
633
+
634
+ self._raise_for_expected(element, argname)
635
+
636
+
637
+ class LiteralValueImpl(RoleImpl):
638
+ _resolve_literal_only = True
639
+
640
+ def _implicit_coercions(
641
+ self,
642
+ element,
643
+ resolved,
644
+ argname=None,
645
+ *,
646
+ type_=None,
647
+ literal_execute=False,
648
+ **kw,
649
+ ):
650
+ if not _is_literal(resolved):
651
+ self._raise_for_expected(
652
+ element, resolved=resolved, argname=argname, **kw
653
+ )
654
+
655
+ return elements.BindParameter(
656
+ None,
657
+ element,
658
+ type_=type_,
659
+ unique=True,
660
+ literal_execute=literal_execute,
661
+ )
662
+
663
+ def _literal_coercion(self, element, **kw):
664
+ return element
665
+
666
+
667
+ class _SelectIsNotFrom(RoleImpl):
668
+ __slots__ = ()
669
+
670
+ def _raise_for_expected(
671
+ self,
672
+ element: Any,
673
+ argname: Optional[str] = None,
674
+ resolved: Optional[Any] = None,
675
+ *,
676
+ advice: Optional[str] = None,
677
+ code: Optional[str] = None,
678
+ err: Optional[Exception] = None,
679
+ **kw: Any,
680
+ ) -> NoReturn:
681
+ if (
682
+ not advice
683
+ and isinstance(element, roles.SelectStatementRole)
684
+ or isinstance(resolved, roles.SelectStatementRole)
685
+ ):
686
+ advice = (
687
+ "To create a "
688
+ "FROM clause from a %s object, use the .subquery() method."
689
+ % (resolved.__class__ if resolved is not None else element,)
690
+ )
691
+ code = "89ve"
692
+ else:
693
+ code = None
694
+
695
+ super()._raise_for_expected(
696
+ element,
697
+ argname=argname,
698
+ resolved=resolved,
699
+ advice=advice,
700
+ code=code,
701
+ err=err,
702
+ **kw,
703
+ )
704
+ # never reached
705
+ assert False
706
+
707
+
708
+ class HasCacheKeyImpl(RoleImpl):
709
+ __slots__ = ()
710
+
711
+ def _implicit_coercions(
712
+ self,
713
+ element: Any,
714
+ resolved: Any,
715
+ argname: Optional[str] = None,
716
+ **kw: Any,
717
+ ) -> Any:
718
+ if isinstance(element, HasCacheKey):
719
+ return element
720
+ else:
721
+ self._raise_for_expected(element, argname, resolved)
722
+
723
+ def _literal_coercion(self, element, **kw):
724
+ return element
725
+
726
+
727
+ class ExecutableOptionImpl(RoleImpl):
728
+ __slots__ = ()
729
+
730
+ def _implicit_coercions(
731
+ self,
732
+ element: Any,
733
+ resolved: Any,
734
+ argname: Optional[str] = None,
735
+ **kw: Any,
736
+ ) -> Any:
737
+ if isinstance(element, ExecutableOption):
738
+ return element
739
+ else:
740
+ self._raise_for_expected(element, argname, resolved)
741
+
742
+ def _literal_coercion(self, element, **kw):
743
+ return element
744
+
745
+
746
+ class ExpressionElementImpl(_ColumnCoercions, RoleImpl):
747
+ __slots__ = ()
748
+
749
+ def _literal_coercion(
750
+ self, element, *, name=None, type_=None, is_crud=False, **kw
751
+ ):
752
+ if (
753
+ element is None
754
+ and not is_crud
755
+ and (type_ is None or not type_.should_evaluate_none)
756
+ ):
757
+ # TODO: there's no test coverage now for the
758
+ # "should_evaluate_none" part of this, as outside of "crud" this
759
+ # codepath is not normally used except in some special cases
760
+ return elements.Null()
761
+ else:
762
+ try:
763
+ return elements.BindParameter(
764
+ name, element, type_, unique=True, _is_crud=is_crud
765
+ )
766
+ except exc.ArgumentError as err:
767
+ self._raise_for_expected(element, err=err)
768
+
769
+ def _raise_for_expected(self, element, argname=None, resolved=None, **kw):
770
+ # select uses implicit coercion with warning instead of raising
771
+ if isinstance(element, selectable.Values):
772
+ advice = (
773
+ "To create a column expression from a VALUES clause, "
774
+ "use the .scalar_values() method."
775
+ )
776
+ elif isinstance(element, roles.AnonymizedFromClauseRole):
777
+ advice = (
778
+ "To create a column expression from a FROM clause row "
779
+ "as a whole, use the .table_valued() method."
780
+ )
781
+ else:
782
+ advice = None
783
+
784
+ return super()._raise_for_expected(
785
+ element, argname=argname, resolved=resolved, advice=advice, **kw
786
+ )
787
+
788
+
789
+ class BinaryElementImpl(ExpressionElementImpl, RoleImpl):
790
+ __slots__ = ()
791
+
792
+ def _literal_coercion( # type: ignore[override]
793
+ self,
794
+ element,
795
+ *,
796
+ expr,
797
+ operator,
798
+ bindparam_type=None,
799
+ argname=None,
800
+ **kw,
801
+ ):
802
+ try:
803
+ return expr._bind_param(operator, element, type_=bindparam_type)
804
+ except exc.ArgumentError as err:
805
+ self._raise_for_expected(element, err=err)
806
+
807
+ def _post_coercion(self, resolved, *, expr, bindparam_type=None, **kw):
808
+ if resolved.type._isnull and not expr.type._isnull:
809
+ resolved = resolved._with_binary_element_type(
810
+ bindparam_type if bindparam_type is not None else expr.type
811
+ )
812
+ return resolved
813
+
814
+
815
+ class InElementImpl(RoleImpl):
816
+ __slots__ = ()
817
+
818
+ def _implicit_coercions(
819
+ self,
820
+ element: Any,
821
+ resolved: Any,
822
+ argname: Optional[str] = None,
823
+ **kw: Any,
824
+ ) -> Any:
825
+ if resolved._is_from_clause:
826
+ if (
827
+ isinstance(resolved, selectable.Alias)
828
+ and resolved.element._is_select_base
829
+ ):
830
+ self._warn_for_implicit_coercion(resolved)
831
+ return self._post_coercion(resolved.element, **kw)
832
+ else:
833
+ self._warn_for_implicit_coercion(resolved)
834
+ return self._post_coercion(resolved.select(), **kw)
835
+ else:
836
+ self._raise_for_expected(element, argname, resolved)
837
+
838
+ def _warn_for_implicit_coercion(self, elem):
839
+ util.warn(
840
+ "Coercing %s object into a select() for use in IN(); "
841
+ "please pass a select() construct explicitly"
842
+ % (elem.__class__.__name__)
843
+ )
844
+
845
+ @util.preload_module("sqlalchemy.sql.elements")
846
+ def _literal_coercion(self, element, *, expr, operator, **kw):
847
+ if util.is_non_string_iterable(element):
848
+ non_literal_expressions: Dict[
849
+ Optional[ColumnElement[Any]],
850
+ ColumnElement[Any],
851
+ ] = {}
852
+ element = list(element)
853
+ for o in element:
854
+ if not _is_literal(o):
855
+ if not isinstance(
856
+ o, util.preloaded.sql_elements.ColumnElement
857
+ ):
858
+ self._raise_for_expected(element, **kw)
859
+
860
+ else:
861
+ non_literal_expressions[o] = o
862
+ elif o is None:
863
+ non_literal_expressions[o] = elements.Null()
864
+
865
+ if non_literal_expressions:
866
+ return elements.ClauseList(
867
+ *[
868
+ (
869
+ non_literal_expressions[o]
870
+ if o in non_literal_expressions
871
+ else expr._bind_param(operator, o)
872
+ )
873
+ for o in element
874
+ ]
875
+ )
876
+ else:
877
+ return expr._bind_param(operator, element, expanding=True)
878
+
879
+ else:
880
+ self._raise_for_expected(element, **kw)
881
+
882
+ def _post_coercion(self, element, *, expr, operator, **kw):
883
+ if element._is_select_base:
884
+ # for IN, we are doing scalar_subquery() coercion without
885
+ # a warning
886
+ return element.scalar_subquery()
887
+ elif isinstance(element, elements.ClauseList):
888
+ assert not len(element.clauses) == 0
889
+ return element.self_group(against=operator)
890
+
891
+ elif isinstance(element, elements.BindParameter):
892
+ element = element._clone(maintain_key=True)
893
+ element.expanding = True
894
+ element.expand_op = operator
895
+
896
+ return element
897
+ elif isinstance(element, selectable.Values):
898
+ return element.scalar_values()
899
+ else:
900
+ return element
901
+
902
+
903
+ class OnClauseImpl(_ColumnCoercions, RoleImpl):
904
+ __slots__ = ()
905
+
906
+ _coerce_consts = True
907
+
908
+ def _literal_coercion(self, element, **kw):
909
+ self._raise_for_expected(element)
910
+
911
+ def _post_coercion(self, resolved, *, original_element=None, **kw):
912
+ # this is a hack right now as we want to use coercion on an
913
+ # ORM InstrumentedAttribute, but we want to return the object
914
+ # itself if it is one, not its clause element.
915
+ # ORM context _join and _legacy_join() would need to be improved
916
+ # to look for annotations in a clause element form.
917
+ if isinstance(original_element, roles.JoinTargetRole):
918
+ return original_element
919
+ return resolved
920
+
921
+
922
+ class WhereHavingImpl(_CoerceLiterals, _ColumnCoercions, RoleImpl):
923
+ __slots__ = ()
924
+
925
+ _coerce_consts = True
926
+
927
+ def _text_coercion(self, element, argname=None):
928
+ return _no_text_coercion(element, argname)
929
+
930
+
931
+ class StatementOptionImpl(_CoerceLiterals, RoleImpl):
932
+ __slots__ = ()
933
+
934
+ _coerce_consts = True
935
+
936
+ def _text_coercion(self, element, argname=None):
937
+ return elements.TextClause(element)
938
+
939
+
940
+ class ColumnArgumentImpl(_NoTextCoercion, RoleImpl):
941
+ __slots__ = ()
942
+
943
+
944
+ class ColumnArgumentOrKeyImpl(_ReturnsStringKey, RoleImpl):
945
+ __slots__ = ()
946
+
947
+
948
+ class StrAsPlainColumnImpl(_CoerceLiterals, RoleImpl):
949
+ __slots__ = ()
950
+
951
+ def _text_coercion(self, element, argname=None):
952
+ return elements.ColumnClause(element)
953
+
954
+
955
+ class ByOfImpl(_CoerceLiterals, _ColumnCoercions, RoleImpl, roles.ByOfRole):
956
+ __slots__ = ()
957
+
958
+ _coerce_consts = True
959
+
960
+ def _text_coercion(self, element, argname=None):
961
+ return elements._textual_label_reference(element)
962
+
963
+
964
+ class OrderByImpl(ByOfImpl, RoleImpl):
965
+ __slots__ = ()
966
+
967
+ def _post_coercion(self, resolved, **kw):
968
+ if (
969
+ isinstance(resolved, self._role_class)
970
+ and resolved._order_by_label_element is not None
971
+ ):
972
+ return elements._label_reference(resolved)
973
+ else:
974
+ return resolved
975
+
976
+
977
+ class GroupByImpl(ByOfImpl, RoleImpl):
978
+ __slots__ = ()
979
+
980
+ def _implicit_coercions(
981
+ self,
982
+ element: Any,
983
+ resolved: Any,
984
+ argname: Optional[str] = None,
985
+ **kw: Any,
986
+ ) -> Any:
987
+ if is_from_clause(resolved):
988
+ return elements.ClauseList(*resolved.c)
989
+ else:
990
+ return resolved
991
+
992
+
993
+ class DMLColumnImpl(_ReturnsStringKey, RoleImpl):
994
+ __slots__ = ()
995
+
996
+ def _post_coercion(self, element, *, as_key=False, **kw):
997
+ if as_key:
998
+ return element.key
999
+ else:
1000
+ return element
1001
+
1002
+
1003
+ class ConstExprImpl(RoleImpl):
1004
+ __slots__ = ()
1005
+
1006
+ def _literal_coercion(self, element, *, argname=None, **kw):
1007
+ if element is None:
1008
+ return elements.Null()
1009
+ elif element is False:
1010
+ return elements.False_()
1011
+ elif element is True:
1012
+ return elements.True_()
1013
+ else:
1014
+ self._raise_for_expected(element, argname)
1015
+
1016
+
1017
+ class TruncatedLabelImpl(_StringOnly, RoleImpl):
1018
+ __slots__ = ()
1019
+
1020
+ def _implicit_coercions(
1021
+ self,
1022
+ element: Any,
1023
+ resolved: Any,
1024
+ argname: Optional[str] = None,
1025
+ **kw: Any,
1026
+ ) -> Any:
1027
+ if isinstance(element, str):
1028
+ return resolved
1029
+ else:
1030
+ self._raise_for_expected(element, argname, resolved)
1031
+
1032
+ def _literal_coercion(self, element, **kw):
1033
+ """coerce the given value to :class:`._truncated_label`.
1034
+
1035
+ Existing :class:`._truncated_label` and
1036
+ :class:`._anonymous_label` objects are passed
1037
+ unchanged.
1038
+ """
1039
+
1040
+ if isinstance(element, elements._truncated_label):
1041
+ return element
1042
+ else:
1043
+ return elements._truncated_label(element)
1044
+
1045
+
1046
+ class DDLExpressionImpl(_Deannotate, _CoerceLiterals, RoleImpl):
1047
+ __slots__ = ()
1048
+
1049
+ _coerce_consts = True
1050
+
1051
+ def _text_coercion(self, element, argname=None):
1052
+ # see #5754 for why we can't easily deprecate this coercion.
1053
+ # essentially expressions like postgresql_where would have to be
1054
+ # text() as they come back from reflection and we don't want to
1055
+ # have text() elements wired into the inspection dictionaries.
1056
+ return elements.TextClause(element)
1057
+
1058
+
1059
+ class DDLConstraintColumnImpl(_Deannotate, _ReturnsStringKey, RoleImpl):
1060
+ __slots__ = ()
1061
+
1062
+
1063
+ class DDLReferredColumnImpl(DDLConstraintColumnImpl):
1064
+ __slots__ = ()
1065
+
1066
+
1067
+ class LimitOffsetImpl(RoleImpl):
1068
+ __slots__ = ()
1069
+
1070
+ def _implicit_coercions(
1071
+ self,
1072
+ element: Any,
1073
+ resolved: Any,
1074
+ argname: Optional[str] = None,
1075
+ **kw: Any,
1076
+ ) -> Any:
1077
+ if resolved is None:
1078
+ return None
1079
+ else:
1080
+ self._raise_for_expected(element, argname, resolved)
1081
+
1082
+ def _literal_coercion( # type: ignore[override]
1083
+ self, element, *, name, type_, **kw
1084
+ ):
1085
+ if element is None:
1086
+ return None
1087
+ else:
1088
+ value = util.asint(element)
1089
+ return selectable._OffsetLimitParam(
1090
+ name, value, type_=type_, unique=True
1091
+ )
1092
+
1093
+
1094
+ class LabeledColumnExprImpl(ExpressionElementImpl):
1095
+ __slots__ = ()
1096
+
1097
+ def _implicit_coercions(
1098
+ self,
1099
+ element: Any,
1100
+ resolved: Any,
1101
+ argname: Optional[str] = None,
1102
+ **kw: Any,
1103
+ ) -> Any:
1104
+ if isinstance(resolved, roles.ExpressionElementRole):
1105
+ return resolved.label(None)
1106
+ else:
1107
+ new = super()._implicit_coercions(
1108
+ element, resolved, argname=argname, **kw
1109
+ )
1110
+ if isinstance(new, roles.ExpressionElementRole):
1111
+ return new.label(None)
1112
+ else:
1113
+ self._raise_for_expected(element, argname, resolved)
1114
+
1115
+
1116
+ class ColumnsClauseImpl(_SelectIsNotFrom, _CoerceLiterals, RoleImpl):
1117
+ __slots__ = ()
1118
+
1119
+ _coerce_consts = True
1120
+ _coerce_numerics = True
1121
+ _coerce_star = True
1122
+
1123
+ _guess_straight_column = re.compile(r"^\w\S*$", re.I)
1124
+
1125
+ def _raise_for_expected(
1126
+ self, element, argname=None, resolved=None, *, advice=None, **kw
1127
+ ):
1128
+ if not advice and isinstance(element, list):
1129
+ advice = (
1130
+ f"Did you mean to say select("
1131
+ f"{', '.join(repr(e) for e in element)})?"
1132
+ )
1133
+
1134
+ return super()._raise_for_expected(
1135
+ element, argname=argname, resolved=resolved, advice=advice, **kw
1136
+ )
1137
+
1138
+ def _text_coercion(self, element, argname=None):
1139
+ element = str(element)
1140
+
1141
+ guess_is_literal = not self._guess_straight_column.match(element)
1142
+ raise exc.ArgumentError(
1143
+ "Textual column expression %(column)r %(argname)sshould be "
1144
+ "explicitly declared with text(%(column)r), "
1145
+ "or use %(literal_column)s(%(column)r) "
1146
+ "for more specificity"
1147
+ % {
1148
+ "column": util.ellipses_string(element),
1149
+ "argname": "for argument %s" % (argname,) if argname else "",
1150
+ "literal_column": (
1151
+ "literal_column" if guess_is_literal else "column"
1152
+ ),
1153
+ }
1154
+ )
1155
+
1156
+
1157
+ class ReturnsRowsImpl(RoleImpl):
1158
+ __slots__ = ()
1159
+
1160
+
1161
+ class StatementImpl(_CoerceLiterals, RoleImpl):
1162
+ __slots__ = ()
1163
+
1164
+ def _post_coercion(
1165
+ self, resolved, *, original_element, argname=None, **kw
1166
+ ):
1167
+ if resolved is not original_element and not isinstance(
1168
+ original_element, str
1169
+ ):
1170
+ # use same method as Connection uses; this will later raise
1171
+ # ObjectNotExecutableError
1172
+ try:
1173
+ original_element._execute_on_connection
1174
+ except AttributeError:
1175
+ util.warn_deprecated(
1176
+ "Object %r should not be used directly in a SQL statement "
1177
+ "context, such as passing to methods such as "
1178
+ "session.execute(). This usage will be disallowed in a "
1179
+ "future release. "
1180
+ "Please use Core select() / update() / delete() etc. "
1181
+ "with Session.execute() and other statement execution "
1182
+ "methods." % original_element,
1183
+ "1.4",
1184
+ )
1185
+
1186
+ return resolved
1187
+
1188
+ def _implicit_coercions(
1189
+ self,
1190
+ element: Any,
1191
+ resolved: Any,
1192
+ argname: Optional[str] = None,
1193
+ **kw: Any,
1194
+ ) -> Any:
1195
+ if resolved._is_lambda_element:
1196
+ return resolved
1197
+ else:
1198
+ return super()._implicit_coercions(
1199
+ element, resolved, argname=argname, **kw
1200
+ )
1201
+
1202
+
1203
+ class SelectStatementImpl(_NoTextCoercion, RoleImpl):
1204
+ __slots__ = ()
1205
+
1206
+ def _implicit_coercions(
1207
+ self,
1208
+ element: Any,
1209
+ resolved: Any,
1210
+ argname: Optional[str] = None,
1211
+ **kw: Any,
1212
+ ) -> Any:
1213
+ if resolved._is_text_clause:
1214
+ return resolved.columns()
1215
+ else:
1216
+ self._raise_for_expected(element, argname, resolved)
1217
+
1218
+
1219
+ class HasCTEImpl(ReturnsRowsImpl):
1220
+ __slots__ = ()
1221
+
1222
+
1223
+ class IsCTEImpl(RoleImpl):
1224
+ __slots__ = ()
1225
+
1226
+
1227
+ class JoinTargetImpl(RoleImpl):
1228
+ __slots__ = ()
1229
+
1230
+ _skip_clauseelement_for_target_match = True
1231
+
1232
+ def _literal_coercion(self, element, *, argname=None, **kw):
1233
+ self._raise_for_expected(element, argname)
1234
+
1235
+ def _implicit_coercions(
1236
+ self,
1237
+ element: Any,
1238
+ resolved: Any,
1239
+ argname: Optional[str] = None,
1240
+ *,
1241
+ legacy: bool = False,
1242
+ **kw: Any,
1243
+ ) -> Any:
1244
+ if isinstance(element, roles.JoinTargetRole):
1245
+ # note that this codepath no longer occurs as of
1246
+ # #6550, unless JoinTargetImpl._skip_clauseelement_for_target_match
1247
+ # were set to False.
1248
+ return element
1249
+ elif legacy and resolved._is_select_base:
1250
+ util.warn_deprecated(
1251
+ "Implicit coercion of SELECT and textual SELECT "
1252
+ "constructs into FROM clauses is deprecated; please call "
1253
+ ".subquery() on any Core select or ORM Query object in "
1254
+ "order to produce a subquery object.",
1255
+ version="1.4",
1256
+ )
1257
+ # TODO: doing _implicit_subquery here causes tests to fail,
1258
+ # how was this working before? probably that ORM
1259
+ # join logic treated it as a select and subquery would happen
1260
+ # in _ORMJoin->Join
1261
+ return resolved
1262
+ else:
1263
+ self._raise_for_expected(element, argname, resolved)
1264
+
1265
+
1266
+ class FromClauseImpl(_SelectIsNotFrom, _NoTextCoercion, RoleImpl):
1267
+ __slots__ = ()
1268
+
1269
+ def _implicit_coercions(
1270
+ self,
1271
+ element: Any,
1272
+ resolved: Any,
1273
+ argname: Optional[str] = None,
1274
+ *,
1275
+ explicit_subquery: bool = False,
1276
+ allow_select: bool = True,
1277
+ **kw: Any,
1278
+ ) -> Any:
1279
+ if resolved._is_select_base:
1280
+ if explicit_subquery:
1281
+ return resolved.subquery()
1282
+ elif allow_select:
1283
+ util.warn_deprecated(
1284
+ "Implicit coercion of SELECT and textual SELECT "
1285
+ "constructs into FROM clauses is deprecated; please call "
1286
+ ".subquery() on any Core select or ORM Query object in "
1287
+ "order to produce a subquery object.",
1288
+ version="1.4",
1289
+ )
1290
+ return resolved._implicit_subquery
1291
+ elif resolved._is_text_clause:
1292
+ return resolved
1293
+ else:
1294
+ self._raise_for_expected(element, argname, resolved)
1295
+
1296
+ def _post_coercion(self, element, *, deannotate=False, **kw):
1297
+ if deannotate:
1298
+ return element._deannotate()
1299
+ else:
1300
+ return element
1301
+
1302
+
1303
+ class StrictFromClauseImpl(FromClauseImpl):
1304
+ __slots__ = ()
1305
+
1306
+ def _implicit_coercions(
1307
+ self,
1308
+ element: Any,
1309
+ resolved: Any,
1310
+ argname: Optional[str] = None,
1311
+ *,
1312
+ allow_select: bool = False,
1313
+ **kw: Any,
1314
+ ) -> Any:
1315
+ if resolved._is_select_base and allow_select:
1316
+ util.warn_deprecated(
1317
+ "Implicit coercion of SELECT and textual SELECT constructs "
1318
+ "into FROM clauses is deprecated; please call .subquery() "
1319
+ "on any Core select or ORM Query object in order to produce a "
1320
+ "subquery object.",
1321
+ version="1.4",
1322
+ )
1323
+ return resolved._implicit_subquery
1324
+ else:
1325
+ self._raise_for_expected(element, argname, resolved)
1326
+
1327
+
1328
+ class AnonymizedFromClauseImpl(StrictFromClauseImpl):
1329
+ __slots__ = ()
1330
+
1331
+ def _post_coercion(self, element, *, flat=False, name=None, **kw):
1332
+ assert name is None
1333
+
1334
+ return element._anonymous_fromclause(flat=flat)
1335
+
1336
+
1337
+ class DMLTableImpl(_SelectIsNotFrom, _NoTextCoercion, RoleImpl):
1338
+ __slots__ = ()
1339
+
1340
+ def _post_coercion(self, element, **kw):
1341
+ if "dml_table" in element._annotations:
1342
+ return element._annotations["dml_table"]
1343
+ else:
1344
+ return element
1345
+
1346
+
1347
+ class DMLSelectImpl(_NoTextCoercion, RoleImpl):
1348
+ __slots__ = ()
1349
+
1350
+ def _implicit_coercions(
1351
+ self,
1352
+ element: Any,
1353
+ resolved: Any,
1354
+ argname: Optional[str] = None,
1355
+ **kw: Any,
1356
+ ) -> Any:
1357
+ if resolved._is_from_clause:
1358
+ if (
1359
+ isinstance(resolved, selectable.Alias)
1360
+ and resolved.element._is_select_base
1361
+ ):
1362
+ return resolved.element
1363
+ else:
1364
+ return resolved.select()
1365
+ else:
1366
+ self._raise_for_expected(element, argname, resolved)
1367
+
1368
+
1369
+ class CompoundElementImpl(_NoTextCoercion, RoleImpl):
1370
+ __slots__ = ()
1371
+
1372
+ def _raise_for_expected(self, element, argname=None, resolved=None, **kw):
1373
+ if isinstance(element, roles.FromClauseRole):
1374
+ if element._is_subquery:
1375
+ advice = (
1376
+ "Use the plain select() object without "
1377
+ "calling .subquery() or .alias()."
1378
+ )
1379
+ else:
1380
+ advice = (
1381
+ "To SELECT from any FROM clause, use the .select() method."
1382
+ )
1383
+ else:
1384
+ advice = None
1385
+ return super()._raise_for_expected(
1386
+ element, argname=argname, resolved=resolved, advice=advice, **kw
1387
+ )
1388
+
1389
+
1390
+ _impl_lookup = {}
1391
+
1392
+
1393
+ for name in dir(roles):
1394
+ cls = getattr(roles, name)
1395
+ if name.endswith("Role"):
1396
+ name = name.replace("Role", "Impl")
1397
+ if name in globals():
1398
+ impl = globals()[name](cls)
1399
+ _impl_lookup[cls] = impl
1400
+
1401
+ if not TYPE_CHECKING:
1402
+ ee_impl = _impl_lookup[roles.ExpressionElementRole]
1403
+
1404
+ for py_type in (int, bool, str, float):
1405
+ _impl_lookup[roles.ExpressionElementRole[py_type]] = ee_impl