SQLAlchemy 2.1.0rc1__cp315-cp315-win_amd64.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-win_amd64.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp315-win_amd64.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +711 -0
  80. sqlalchemy/engine/_row_cy.cp315-win_amd64.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp315-win_amd64.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-win_amd64.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-win_amd64.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-win_amd64.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-win_amd64.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,660 @@
1
+ # sql/default_comparator.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
+
8
+ """Default implementation of SQL comparison operations."""
9
+
10
+ from __future__ import annotations
11
+
12
+ import typing
13
+ from typing import Any
14
+ from typing import Callable
15
+ from typing import NoReturn
16
+ from typing import Optional
17
+ from typing import Tuple
18
+ from typing import Type
19
+ from typing import Union
20
+
21
+ from . import coercions
22
+ from . import functions
23
+ from . import operators
24
+ from . import roles
25
+ from . import type_api
26
+ from .elements import and_
27
+ from .elements import BinaryExpression
28
+ from .elements import ClauseElement
29
+ from .elements import CollationClause
30
+ from .elements import CollectionAggregate
31
+ from .elements import ExpressionClauseList
32
+ from .elements import False_
33
+ from .elements import Null
34
+ from .elements import OperatorExpression
35
+ from .elements import or_
36
+ from .elements import True_
37
+ from .elements import UnaryExpression
38
+ from .operators import OperatorType
39
+ from .. import exc
40
+ from .. import util
41
+
42
+ _T = typing.TypeVar("_T", bound=Any)
43
+
44
+ if typing.TYPE_CHECKING:
45
+ from .elements import ColumnElement
46
+ from .operators import custom_op
47
+ from .type_api import TypeEngine
48
+
49
+
50
+ def _boolean_compare(
51
+ expr: ColumnElement[Any],
52
+ op: OperatorType,
53
+ obj: Any,
54
+ *,
55
+ negate_op: Optional[OperatorType] = None,
56
+ reverse: bool = False,
57
+ _python_is_types: Tuple[Type[Any], ...] = (type(None), bool),
58
+ result_type: Optional[TypeEngine[bool]] = None,
59
+ **kwargs: Any,
60
+ ) -> OperatorExpression[bool]:
61
+ if result_type is None:
62
+ result_type = type_api.BOOLEANTYPE
63
+
64
+ if isinstance(obj, _python_is_types + (Null, True_, False_)):
65
+ # allow x ==/!= True/False to be treated as a literal.
66
+ # this comes out to "== / != true/false" or "1/0" if those
67
+ # constants aren't supported and works on all platforms
68
+ if op in (operators.eq, operators.ne) and isinstance(
69
+ obj, (bool, True_, False_)
70
+ ):
71
+ return OperatorExpression._construct_for_op(
72
+ expr,
73
+ coercions.expect(roles.ConstExprRole, obj),
74
+ op,
75
+ type_=result_type,
76
+ negate=negate_op,
77
+ modifiers=kwargs,
78
+ )
79
+ elif op in (
80
+ operators.is_distinct_from,
81
+ operators.is_not_distinct_from,
82
+ ):
83
+ return OperatorExpression._construct_for_op(
84
+ expr,
85
+ coercions.expect(roles.ConstExprRole, obj),
86
+ op,
87
+ type_=result_type,
88
+ negate=negate_op,
89
+ modifiers=kwargs,
90
+ )
91
+ elif expr._is_collection_aggregate:
92
+ obj = coercions.expect(
93
+ roles.ConstExprRole, element=obj, operator=op, expr=expr
94
+ )
95
+ else:
96
+ # all other None uses IS, IS NOT
97
+ if op in (operators.eq, operators.is_):
98
+ return OperatorExpression._construct_for_op(
99
+ expr,
100
+ coercions.expect(roles.ConstExprRole, obj),
101
+ operators.is_,
102
+ negate=operators.is_not,
103
+ type_=result_type,
104
+ )
105
+ elif op in (operators.ne, operators.is_not):
106
+ return OperatorExpression._construct_for_op(
107
+ expr,
108
+ coercions.expect(roles.ConstExprRole, obj),
109
+ operators.is_not,
110
+ negate=operators.is_,
111
+ type_=result_type,
112
+ )
113
+ else:
114
+ raise exc.ArgumentError(
115
+ "Only '=', '!=', 'is_()', 'is_not()', "
116
+ "'is_distinct_from()', 'is_not_distinct_from()' "
117
+ "operators can be used with None/True/False"
118
+ )
119
+ else:
120
+ obj = coercions.expect(
121
+ roles.BinaryElementRole, element=obj, operator=op, expr=expr
122
+ )
123
+
124
+ if reverse:
125
+ return OperatorExpression._construct_for_op(
126
+ obj,
127
+ expr,
128
+ op,
129
+ type_=result_type,
130
+ negate=negate_op,
131
+ modifiers=kwargs,
132
+ )
133
+ else:
134
+ return OperatorExpression._construct_for_op(
135
+ expr,
136
+ obj,
137
+ op,
138
+ type_=result_type,
139
+ negate=negate_op,
140
+ modifiers=kwargs,
141
+ )
142
+
143
+
144
+ def _custom_op_operate(
145
+ expr: ColumnElement[Any],
146
+ op: custom_op[Any],
147
+ obj: Any,
148
+ reverse: bool = False,
149
+ result_type: Optional[TypeEngine[Any]] = None,
150
+ **kw: Any,
151
+ ) -> ColumnElement[Any]:
152
+ if result_type is None:
153
+ if op.return_type:
154
+ result_type = op.return_type
155
+ elif op.is_comparison:
156
+ result_type = type_api.BOOLEANTYPE
157
+
158
+ return _binary_operate(
159
+ expr, op, obj, reverse=reverse, result_type=result_type, **kw
160
+ )
161
+
162
+
163
+ def _binary_operate(
164
+ expr: ColumnElement[Any],
165
+ op: OperatorType,
166
+ obj: roles.BinaryElementRole[Any],
167
+ *,
168
+ reverse: bool = False,
169
+ result_type: Optional[TypeEngine[_T]] = None,
170
+ **kw: Any,
171
+ ) -> OperatorExpression[_T]:
172
+ coerced_obj = coercions.expect(
173
+ roles.BinaryElementRole, obj, expr=expr, operator=op
174
+ )
175
+
176
+ if reverse:
177
+ left, right = coerced_obj, expr
178
+ else:
179
+ left, right = expr, coerced_obj
180
+
181
+ if result_type is None:
182
+ op, result_type = left.comparator._adapt_expression(
183
+ op, right.comparator
184
+ )
185
+
186
+ return OperatorExpression._construct_for_op(
187
+ left, right, op, type_=result_type, modifiers=kw
188
+ )
189
+
190
+
191
+ def _conjunction_operate(
192
+ expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
193
+ ) -> ColumnElement[Any]:
194
+ if op is operators.and_:
195
+ return and_(expr, other)
196
+ elif op is operators.or_:
197
+ return or_(expr, other)
198
+ else:
199
+ raise NotImplementedError()
200
+
201
+
202
+ def _scalar(
203
+ expr: ColumnElement[Any],
204
+ op: OperatorType,
205
+ fn: Callable[[ColumnElement[Any]], ColumnElement[Any]],
206
+ **kw: Any,
207
+ ) -> ColumnElement[Any]:
208
+ return fn(expr)
209
+
210
+
211
+ def _in_impl(
212
+ expr: ColumnElement[Any],
213
+ op: OperatorType,
214
+ seq_or_selectable: ClauseElement,
215
+ negate_op: OperatorType,
216
+ **kw: Any,
217
+ ) -> ColumnElement[Any]:
218
+ seq_or_selectable = coercions.expect(
219
+ roles.InElementRole, seq_or_selectable, expr=expr, operator=op
220
+ )
221
+ if "in_ops" in seq_or_selectable._annotations:
222
+ op, negate_op = seq_or_selectable._annotations["in_ops"]
223
+
224
+ return _boolean_compare(
225
+ expr, op, seq_or_selectable, negate_op=negate_op, **kw
226
+ )
227
+
228
+
229
+ def _getitem_impl(
230
+ expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
231
+ ) -> ColumnElement[Any]:
232
+ if (
233
+ isinstance(expr.type, type_api.INDEXABLE)
234
+ or isinstance(expr.type, type_api.TypeDecorator)
235
+ and isinstance(expr.type.impl_instance, type_api.INDEXABLE)
236
+ ):
237
+ other = coercions.expect(
238
+ roles.BinaryElementRole, other, expr=expr, operator=op
239
+ )
240
+ return _binary_operate(expr, op, other, **kw)
241
+ else:
242
+ _unsupported_impl(expr, op, other, **kw)
243
+
244
+
245
+ def _unsupported_impl(
246
+ expr: ColumnElement[Any], op: OperatorType, *arg: Any, **kw: Any
247
+ ) -> NoReturn:
248
+ raise NotImplementedError(
249
+ "Operator '%s' is not supported on this expression" % op.__name__
250
+ )
251
+
252
+
253
+ def _inv_impl(
254
+ expr: ColumnElement[Any], op: OperatorType, **kw: Any
255
+ ) -> ColumnElement[Any]:
256
+ """See :meth:`.ColumnOperators.__inv__`."""
257
+
258
+ # undocumented element currently used by the ORM for
259
+ # relationship.contains()
260
+ if hasattr(expr, "negation_clause"):
261
+ return expr.negation_clause
262
+ else:
263
+ return expr._negate()
264
+
265
+
266
+ def _neg_impl(
267
+ expr: ColumnElement[Any], op: OperatorType, **kw: Any
268
+ ) -> ColumnElement[Any]:
269
+ """See :meth:`.ColumnOperators.__neg__`."""
270
+ return UnaryExpression(expr, operator=operators.neg, type_=expr.type)
271
+
272
+
273
+ def _bitwise_not_impl(
274
+ expr: ColumnElement[Any], op: OperatorType, **kw: Any
275
+ ) -> ColumnElement[Any]:
276
+ """See :meth:`.ColumnOperators.bitwise_not`."""
277
+
278
+ return UnaryExpression(
279
+ expr, operator=operators.bitwise_not_op, type_=expr.type
280
+ )
281
+
282
+
283
+ def _match_impl(
284
+ expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
285
+ ) -> ColumnElement[Any]:
286
+ """See :meth:`.ColumnOperators.match`."""
287
+
288
+ return _boolean_compare(
289
+ expr,
290
+ operators.match_op,
291
+ coercions.expect(
292
+ roles.BinaryElementRole,
293
+ other,
294
+ expr=expr,
295
+ operator=operators.match_op,
296
+ ),
297
+ result_type=type_api.MATCHTYPE,
298
+ negate_op=(
299
+ operators.not_match_op
300
+ if op is operators.match_op
301
+ else operators.match_op
302
+ ),
303
+ **kw,
304
+ )
305
+
306
+
307
+ def _distinct_impl(
308
+ expr: ColumnElement[Any], op: OperatorType, **kw: Any
309
+ ) -> ColumnElement[Any]:
310
+ """See :meth:`.ColumnOperators.distinct`."""
311
+ return UnaryExpression(
312
+ expr, operator=operators.distinct_op, type_=expr.type
313
+ )
314
+
315
+
316
+ def _between_impl(
317
+ expr: ColumnElement[Any],
318
+ op: OperatorType,
319
+ cleft: Any,
320
+ cright: Any,
321
+ **kw: Any,
322
+ ) -> ColumnElement[Any]:
323
+ """See :meth:`.ColumnOperators.between`."""
324
+ return BinaryExpression(
325
+ expr,
326
+ ExpressionClauseList._construct_for_list(
327
+ operators.and_,
328
+ type_api.NULLTYPE,
329
+ coercions.expect(
330
+ roles.BinaryElementRole,
331
+ cleft,
332
+ expr=expr,
333
+ operator=operators.and_,
334
+ ),
335
+ coercions.expect(
336
+ roles.BinaryElementRole,
337
+ cright,
338
+ expr=expr,
339
+ operator=operators.and_,
340
+ ),
341
+ group=False,
342
+ ),
343
+ op,
344
+ negate=(
345
+ operators.not_between_op
346
+ if op is operators.between_op
347
+ else operators.between_op
348
+ ),
349
+ modifiers=kw,
350
+ )
351
+
352
+
353
+ def _pow_impl(
354
+ expr: ColumnElement[Any],
355
+ op: OperatorType,
356
+ other: Any,
357
+ reverse: bool = False,
358
+ **kw: Any,
359
+ ) -> ColumnElement[Any]:
360
+ if reverse:
361
+ return functions.pow(other, expr)
362
+ else:
363
+ return functions.pow(expr, other)
364
+
365
+
366
+ def _collate_impl(
367
+ expr: ColumnElement[str],
368
+ op: OperatorType,
369
+ collation: str,
370
+ collation_schema: Optional[str] = None,
371
+ **kw: Any,
372
+ ) -> ColumnElement[str]:
373
+ return CollationClause._create_collation_expression(
374
+ expr, collation, collation_schema
375
+ )
376
+
377
+
378
+ def _regexp_match_impl(
379
+ expr: ColumnElement[str],
380
+ op: OperatorType,
381
+ pattern: Any,
382
+ flags: Optional[str],
383
+ **kw: Any,
384
+ ) -> ColumnElement[Any]:
385
+ return BinaryExpression(
386
+ expr,
387
+ coercions.expect(
388
+ roles.BinaryElementRole,
389
+ pattern,
390
+ expr=expr,
391
+ operator=operators.comma_op,
392
+ ),
393
+ op,
394
+ negate=operators.not_regexp_match_op,
395
+ modifiers={"flags": flags},
396
+ )
397
+
398
+
399
+ def _regexp_replace_impl(
400
+ expr: ColumnElement[Any],
401
+ op: OperatorType,
402
+ pattern: Any,
403
+ replacement: Any,
404
+ flags: Optional[str],
405
+ **kw: Any,
406
+ ) -> ColumnElement[Any]:
407
+ return BinaryExpression(
408
+ expr,
409
+ ExpressionClauseList._construct_for_list(
410
+ operators.comma_op,
411
+ type_api.NULLTYPE,
412
+ coercions.expect(
413
+ roles.BinaryElementRole,
414
+ pattern,
415
+ expr=expr,
416
+ operator=operators.comma_op,
417
+ ),
418
+ coercions.expect(
419
+ roles.BinaryElementRole,
420
+ replacement,
421
+ expr=expr,
422
+ operator=operators.comma_op,
423
+ ),
424
+ group=False,
425
+ ),
426
+ op,
427
+ modifiers={"flags": flags},
428
+ )
429
+
430
+
431
+ operator_lookup: util.immutabledict[
432
+ str,
433
+ Tuple[
434
+ Callable[..., "ColumnElement[Any]"],
435
+ util.immutabledict[
436
+ str, Union["OperatorType", Callable[..., "ColumnElement[Any]"]]
437
+ ],
438
+ ],
439
+ ] = util.immutabledict(
440
+ {
441
+ "any_op": (
442
+ _scalar,
443
+ util.immutabledict({"fn": CollectionAggregate._create_any}),
444
+ ),
445
+ "all_op": (
446
+ _scalar,
447
+ util.immutabledict({"fn": CollectionAggregate._create_all}),
448
+ ),
449
+ "lt": (
450
+ _boolean_compare,
451
+ util.immutabledict({"negate_op": operators.ge}),
452
+ ),
453
+ "le": (
454
+ _boolean_compare,
455
+ util.immutabledict({"negate_op": operators.gt}),
456
+ ),
457
+ "ne": (
458
+ _boolean_compare,
459
+ util.immutabledict({"negate_op": operators.eq}),
460
+ ),
461
+ "gt": (
462
+ _boolean_compare,
463
+ util.immutabledict({"negate_op": operators.le}),
464
+ ),
465
+ "ge": (
466
+ _boolean_compare,
467
+ util.immutabledict({"negate_op": operators.lt}),
468
+ ),
469
+ "eq": (
470
+ _boolean_compare,
471
+ util.immutabledict({"negate_op": operators.ne}),
472
+ ),
473
+ "is_distinct_from": (
474
+ _boolean_compare,
475
+ util.immutabledict({"negate_op": operators.is_not_distinct_from}),
476
+ ),
477
+ "is_not_distinct_from": (
478
+ _boolean_compare,
479
+ util.immutabledict({"negate_op": operators.is_distinct_from}),
480
+ ),
481
+ "in_op": (
482
+ _in_impl,
483
+ util.immutabledict({"negate_op": operators.not_in_op}),
484
+ ),
485
+ "not_in_op": (
486
+ _in_impl,
487
+ util.immutabledict({"negate_op": operators.in_op}),
488
+ ),
489
+ "is_": (
490
+ _boolean_compare,
491
+ util.immutabledict({"negate_op": operators.is_}),
492
+ ),
493
+ "is_not": (
494
+ _boolean_compare,
495
+ util.immutabledict({"negate_op": operators.is_not}),
496
+ ),
497
+ "between_op": (
498
+ _between_impl,
499
+ util.EMPTY_DICT,
500
+ ),
501
+ "not_between_op": (
502
+ _between_impl,
503
+ util.EMPTY_DICT,
504
+ ),
505
+ "desc_op": (
506
+ _scalar,
507
+ util.immutabledict({"fn": UnaryExpression._create_desc}),
508
+ ),
509
+ "asc_op": (
510
+ _scalar,
511
+ util.immutabledict({"fn": UnaryExpression._create_asc}),
512
+ ),
513
+ "nulls_first_op": (
514
+ _scalar,
515
+ util.immutabledict({"fn": UnaryExpression._create_nulls_first}),
516
+ ),
517
+ "nulls_last_op": (
518
+ _scalar,
519
+ util.immutabledict({"fn": UnaryExpression._create_nulls_last}),
520
+ ),
521
+ "distinct_op": (
522
+ _distinct_impl,
523
+ util.EMPTY_DICT,
524
+ ),
525
+ "null_op": (_binary_operate, util.EMPTY_DICT),
526
+ "custom_op": (_custom_op_operate, util.EMPTY_DICT),
527
+ "and_": (
528
+ _conjunction_operate,
529
+ util.EMPTY_DICT,
530
+ ),
531
+ "or_": (
532
+ _conjunction_operate,
533
+ util.EMPTY_DICT,
534
+ ),
535
+ "inv": (
536
+ _inv_impl,
537
+ util.EMPTY_DICT,
538
+ ),
539
+ "add": (
540
+ _binary_operate,
541
+ util.EMPTY_DICT,
542
+ ),
543
+ "concat_op": (
544
+ _binary_operate,
545
+ util.EMPTY_DICT,
546
+ ),
547
+ "getitem": (_getitem_impl, util.EMPTY_DICT),
548
+ "contains_op": (
549
+ _boolean_compare,
550
+ util.immutabledict({"negate_op": operators.not_contains_op}),
551
+ ),
552
+ "icontains_op": (
553
+ _boolean_compare,
554
+ util.immutabledict({"negate_op": operators.not_icontains_op}),
555
+ ),
556
+ "contains": (
557
+ _unsupported_impl,
558
+ util.EMPTY_DICT,
559
+ ),
560
+ "like_op": (
561
+ _boolean_compare,
562
+ util.immutabledict({"negate_op": operators.not_like_op}),
563
+ ),
564
+ "ilike_op": (
565
+ _boolean_compare,
566
+ util.immutabledict({"negate_op": operators.not_ilike_op}),
567
+ ),
568
+ "not_like_op": (
569
+ _boolean_compare,
570
+ util.immutabledict({"negate_op": operators.like_op}),
571
+ ),
572
+ "not_ilike_op": (
573
+ _boolean_compare,
574
+ util.immutabledict({"negate_op": operators.ilike_op}),
575
+ ),
576
+ "startswith_op": (
577
+ _boolean_compare,
578
+ util.immutabledict({"negate_op": operators.not_startswith_op}),
579
+ ),
580
+ "istartswith_op": (
581
+ _boolean_compare,
582
+ util.immutabledict({"negate_op": operators.not_istartswith_op}),
583
+ ),
584
+ "endswith_op": (
585
+ _boolean_compare,
586
+ util.immutabledict({"negate_op": operators.not_endswith_op}),
587
+ ),
588
+ "iendswith_op": (
589
+ _boolean_compare,
590
+ util.immutabledict({"negate_op": operators.not_iendswith_op}),
591
+ ),
592
+ "collate": (
593
+ _collate_impl,
594
+ util.EMPTY_DICT,
595
+ ),
596
+ "match_op": (_match_impl, util.EMPTY_DICT),
597
+ "not_match_op": (
598
+ _match_impl,
599
+ util.EMPTY_DICT,
600
+ ),
601
+ "regexp_match_op": (
602
+ _regexp_match_impl,
603
+ util.EMPTY_DICT,
604
+ ),
605
+ "not_regexp_match_op": (
606
+ _regexp_match_impl,
607
+ util.EMPTY_DICT,
608
+ ),
609
+ "regexp_replace_op": (
610
+ _regexp_replace_impl,
611
+ util.EMPTY_DICT,
612
+ ),
613
+ "lshift": (_unsupported_impl, util.EMPTY_DICT),
614
+ "rshift": (_unsupported_impl, util.EMPTY_DICT),
615
+ "bitwise_xor_op": (
616
+ _binary_operate,
617
+ util.EMPTY_DICT,
618
+ ),
619
+ "bitwise_or_op": (
620
+ _binary_operate,
621
+ util.EMPTY_DICT,
622
+ ),
623
+ "bitwise_and_op": (
624
+ _binary_operate,
625
+ util.EMPTY_DICT,
626
+ ),
627
+ "bitwise_not_op": (
628
+ _bitwise_not_impl,
629
+ util.EMPTY_DICT,
630
+ ),
631
+ "bitwise_lshift_op": (
632
+ _binary_operate,
633
+ util.EMPTY_DICT,
634
+ ),
635
+ "bitwise_rshift_op": (
636
+ _binary_operate,
637
+ util.EMPTY_DICT,
638
+ ),
639
+ "matmul": (_unsupported_impl, util.EMPTY_DICT),
640
+ "pow": (_pow_impl, util.EMPTY_DICT),
641
+ "neg": (_neg_impl, util.EMPTY_DICT),
642
+ "mul": (_binary_operate, util.EMPTY_DICT),
643
+ "sub": (
644
+ _binary_operate,
645
+ util.EMPTY_DICT,
646
+ ),
647
+ "div": (_binary_operate, util.EMPTY_DICT),
648
+ "mod": (_binary_operate, util.EMPTY_DICT),
649
+ "truediv": (_binary_operate, util.EMPTY_DICT),
650
+ "floordiv": (_binary_operate, util.EMPTY_DICT),
651
+ "json_path_getitem_op": (
652
+ _binary_operate,
653
+ util.EMPTY_DICT,
654
+ ),
655
+ "json_getitem_op": (
656
+ _binary_operate,
657
+ util.EMPTY_DICT,
658
+ ),
659
+ }
660
+ )