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,1818 @@
1
+ # testing/requirements.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: ignore-errors
8
+
9
+
10
+ """Global database feature support policy.
11
+
12
+ Provides decorators to mark tests requiring specific feature support from the
13
+ target database.
14
+
15
+ External dialect test suites should subclass SuiteRequirements
16
+ to provide specific inclusion/exclusions.
17
+
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import platform
23
+
24
+ from . import asyncio as _test_asyncio
25
+ from . import exclusions
26
+ from .exclusions import only_on
27
+ from .. import create_engine
28
+ from .. import util
29
+ from ..pool import QueuePool
30
+
31
+
32
+ class Requirements:
33
+ pass
34
+
35
+
36
+ class SuiteRequirements(Requirements):
37
+ @property
38
+ def create_table(self):
39
+ """target platform can emit basic CreateTable DDL."""
40
+
41
+ return exclusions.open()
42
+
43
+ @property
44
+ def drop_table(self):
45
+ """target platform can emit basic DropTable DDL."""
46
+
47
+ return exclusions.open()
48
+
49
+ @property
50
+ def table_ddl_if_exists(self):
51
+ """target platform supports IF NOT EXISTS / IF EXISTS for tables."""
52
+
53
+ return exclusions.closed()
54
+
55
+ @property
56
+ def index_ddl_if_exists(self):
57
+ """target platform supports IF NOT EXISTS / IF EXISTS for indexes."""
58
+
59
+ return exclusions.closed()
60
+
61
+ @property
62
+ def uuid_data_type(self):
63
+ """Return databases that support the UUID datatype."""
64
+
65
+ return exclusions.closed()
66
+
67
+ @property
68
+ def foreign_keys(self):
69
+ """Target database must support foreign keys."""
70
+
71
+ return exclusions.open()
72
+
73
+ @property
74
+ def foreign_keys_reflect_as_index(self):
75
+ """Target database creates an index that's reflected for
76
+ foreign keys."""
77
+
78
+ return exclusions.closed()
79
+
80
+ @property
81
+ def unique_index_reflect_as_unique_constraints(self):
82
+ """Target database reflects unique indexes as unique constrains."""
83
+
84
+ return exclusions.closed()
85
+
86
+ @property
87
+ def unique_constraints_reflect_as_index(self):
88
+ """Target database reflects unique constraints as indexes."""
89
+
90
+ return exclusions.closed()
91
+
92
+ @property
93
+ def table_value_constructor(self):
94
+ """Database / dialect supports a query like::
95
+
96
+ SELECT * FROM VALUES ( (c1, c2), (c1, c2), ...)
97
+ AS some_table(col1, col2)
98
+
99
+ SQLAlchemy generates this with the :func:`_sql.values` function.
100
+
101
+ """
102
+ return exclusions.closed()
103
+
104
+ @property
105
+ def standard_cursor_sql(self):
106
+ """Target database passes SQL-92 style statements to cursor.execute()
107
+ when a statement like select() or insert() is run.
108
+
109
+ A very small portion of dialect-level tests will ensure that certain
110
+ conditions are present in SQL strings, and these tests use very basic
111
+ SQL that will work on any SQL-like platform in order to assert results.
112
+
113
+ It's normally a given for any pep-249 DBAPI that a statement like
114
+ "SELECT id, name FROM table WHERE some_table.id=5" will work.
115
+ However, there are dialects that don't actually produce SQL Strings
116
+ and instead may work with symbolic objects instead, or dialects that
117
+ aren't working with SQL, so for those this requirement can be marked
118
+ as excluded.
119
+
120
+ """
121
+
122
+ return exclusions.open()
123
+
124
+ @property
125
+ def on_update_cascade(self):
126
+ """target database must support ON UPDATE..CASCADE behavior in
127
+ foreign keys."""
128
+
129
+ return exclusions.open()
130
+
131
+ @property
132
+ def non_updating_cascade(self):
133
+ """target database must *not* support ON UPDATE..CASCADE behavior in
134
+ foreign keys."""
135
+ return exclusions.closed()
136
+
137
+ @property
138
+ def deferrable_fks(self):
139
+ return exclusions.closed()
140
+
141
+ @property
142
+ def on_update_or_deferrable_fks(self):
143
+ # TODO: exclusions should be composable,
144
+ # somehow only_if([x, y]) isn't working here, negation/conjunctions
145
+ # getting confused.
146
+ return exclusions.only_if(
147
+ lambda: self.on_update_cascade.enabled
148
+ or self.deferrable_fks.enabled
149
+ )
150
+
151
+ @property
152
+ def queue_pool(self):
153
+ """target database is using QueuePool"""
154
+
155
+ def go(config):
156
+ return isinstance(config.db.pool, QueuePool)
157
+
158
+ return exclusions.only_if(go)
159
+
160
+ @property
161
+ def self_referential_foreign_keys(self):
162
+ """Target database must support self-referential foreign keys."""
163
+
164
+ return exclusions.open()
165
+
166
+ @property
167
+ def foreign_key_ddl(self):
168
+ """Target database must support the DDL phrases for FOREIGN KEY."""
169
+
170
+ return exclusions.open()
171
+
172
+ @property
173
+ def named_constraints(self):
174
+ """target database must support names for constraints."""
175
+
176
+ return exclusions.open()
177
+
178
+ @property
179
+ def implicitly_named_constraints(self):
180
+ """target database must apply names to unnamed constraints."""
181
+
182
+ return exclusions.open()
183
+
184
+ @property
185
+ def unusual_column_name_characters(self):
186
+ """target database allows column names that have unusual characters
187
+ in them, such as dots, spaces, slashes, or percent signs.
188
+
189
+ The column names are as always in such a case quoted, however the
190
+ DB still needs to support those characters in the name somehow.
191
+
192
+ """
193
+ return exclusions.open()
194
+
195
+ @property
196
+ def subqueries(self):
197
+ """Target database must support subqueries."""
198
+
199
+ return exclusions.open()
200
+
201
+ @property
202
+ def offset(self):
203
+ """target database can render OFFSET, or an equivalent, in a
204
+ SELECT.
205
+ """
206
+
207
+ return exclusions.open()
208
+
209
+ @property
210
+ def bound_limit_offset(self):
211
+ """target database can render LIMIT and/or OFFSET using a bound
212
+ parameter
213
+ """
214
+
215
+ return exclusions.open()
216
+
217
+ @property
218
+ def sql_expression_limit_offset(self):
219
+ """target database can render LIMIT and/or OFFSET with a complete
220
+ SQL expression, such as one that uses the addition operator.
221
+ parameter
222
+ """
223
+
224
+ return exclusions.open()
225
+
226
+ @property
227
+ def parens_in_union_contained_select_w_limit_offset(self):
228
+ """Target database must support parenthesized SELECT in UNION
229
+ when LIMIT/OFFSET is specifically present.
230
+
231
+ E.g. (SELECT ...) UNION (SELECT ..)
232
+
233
+ This is known to fail on SQLite.
234
+
235
+ """
236
+ return exclusions.open()
237
+
238
+ @property
239
+ def parens_in_union_contained_select_wo_limit_offset(self):
240
+ """Target database must support parenthesized SELECT in UNION
241
+ when OFFSET/LIMIT is specifically not present.
242
+
243
+ E.g. (SELECT ... LIMIT ..) UNION (SELECT .. OFFSET ..)
244
+
245
+ This is known to fail on SQLite. It also fails on Oracle
246
+ because without LIMIT/OFFSET, there is currently no step that
247
+ creates an additional subquery.
248
+
249
+ """
250
+ return exclusions.open()
251
+
252
+ @property
253
+ def boolean_col_expressions(self):
254
+ """Target database must support boolean expressions as columns"""
255
+
256
+ return exclusions.closed()
257
+
258
+ @property
259
+ def nullable_booleans(self):
260
+ """Target database allows boolean columns to store NULL."""
261
+
262
+ return exclusions.open()
263
+
264
+ @property
265
+ def nullsordering(self):
266
+ """Target backends that support nulls ordering."""
267
+
268
+ return exclusions.closed()
269
+
270
+ @property
271
+ def standalone_binds(self):
272
+ """target database/driver supports bound parameters as column
273
+ expressions without being in the context of a typed column.
274
+ """
275
+ return exclusions.open()
276
+
277
+ @property
278
+ def standalone_null_binds_whereclause(self):
279
+ """target database/driver supports bound parameters with NULL in the
280
+ WHERE clause, in situations where it has to be typed.
281
+
282
+ """
283
+ return exclusions.open()
284
+
285
+ @property
286
+ def intersect(self):
287
+ """Target database must support INTERSECT or equivalent."""
288
+ return exclusions.closed()
289
+
290
+ @property
291
+ def except_(self):
292
+ """Target database must support EXCEPT or equivalent (i.e. MINUS)."""
293
+ return exclusions.closed()
294
+
295
+ @property
296
+ def window_functions(self):
297
+ """Target database must support window functions."""
298
+ return exclusions.closed()
299
+
300
+ @property
301
+ def ctes(self):
302
+ """Target database supports CTEs"""
303
+
304
+ return exclusions.closed()
305
+
306
+ @property
307
+ def ctes_with_update_delete(self):
308
+ """target database supports CTES that ride on top of a normal UPDATE
309
+ or DELETE statement which refers to the CTE in a correlated subquery.
310
+
311
+ """
312
+
313
+ return exclusions.closed()
314
+
315
+ @property
316
+ def ctes_on_dml(self):
317
+ """target database supports CTES which consist of INSERT, UPDATE
318
+ or DELETE *within* the CTE, e.g. WITH x AS (UPDATE....)"""
319
+
320
+ return exclusions.closed()
321
+
322
+ @property
323
+ def autoincrement_insert(self):
324
+ """target platform generates new surrogate integer primary key values
325
+ when insert() is executed, excluding the pk column."""
326
+
327
+ return exclusions.open()
328
+
329
+ @property
330
+ def fetch_rows_post_commit(self):
331
+ """target platform will allow cursor.fetchone() to proceed after a
332
+ COMMIT.
333
+
334
+ Typically this refers to an INSERT statement with RETURNING which
335
+ is invoked within "autocommit". If the row can be returned
336
+ after the autocommit, then this rule can be open.
337
+
338
+ """
339
+
340
+ return exclusions.open()
341
+
342
+ @property
343
+ def group_by_complex_expression(self):
344
+ """target platform supports SQL expressions in GROUP BY
345
+
346
+ e.g.
347
+
348
+ SELECT x + y AS somelabel FROM table GROUP BY x + y
349
+
350
+ """
351
+
352
+ return exclusions.open()
353
+
354
+ @property
355
+ def sane_rowcount(self):
356
+ return exclusions.skip_if(
357
+ lambda config: not config.db.dialect.supports_sane_rowcount,
358
+ "driver doesn't support 'sane' rowcount",
359
+ )
360
+
361
+ @property
362
+ def sane_multi_rowcount(self):
363
+ return exclusions.fails_if(
364
+ lambda config: not config.db.dialect.supports_sane_multi_rowcount,
365
+ "driver %(driver)s %(doesnt_support)s 'sane' multi row count",
366
+ )
367
+
368
+ @property
369
+ def sane_rowcount_w_returning(self):
370
+ return exclusions.fails_if(
371
+ lambda config: not (
372
+ config.db.dialect.supports_sane_rowcount_returning
373
+ ),
374
+ "driver doesn't support 'sane' rowcount when returning is on",
375
+ )
376
+
377
+ @property
378
+ def empty_inserts(self):
379
+ """target platform supports INSERT with no values, i.e.
380
+ INSERT DEFAULT VALUES or equivalent."""
381
+
382
+ return exclusions.only_if(
383
+ lambda config: config.db.dialect.supports_empty_insert
384
+ or config.db.dialect.supports_default_values
385
+ or config.db.dialect.supports_default_metavalue,
386
+ "empty inserts not supported",
387
+ )
388
+
389
+ @property
390
+ def empty_inserts_executemany(self):
391
+ """target platform supports INSERT with no values, i.e.
392
+ INSERT DEFAULT VALUES or equivalent, within executemany()"""
393
+
394
+ return self.empty_inserts
395
+
396
+ @property
397
+ def insert_from_select(self):
398
+ """target platform supports INSERT from a SELECT."""
399
+
400
+ return exclusions.open()
401
+
402
+ @property
403
+ def delete_returning(self):
404
+ """target platform supports DELETE ... RETURNING."""
405
+
406
+ return exclusions.only_if(
407
+ lambda config: config.db.dialect.delete_returning,
408
+ "%(database)s %(does_support)s 'DELETE ... RETURNING'",
409
+ )
410
+
411
+ @property
412
+ def insert_returning(self):
413
+ """target platform supports INSERT ... RETURNING."""
414
+
415
+ return exclusions.only_if(
416
+ lambda config: config.db.dialect.insert_returning,
417
+ "%(database)s %(does_support)s 'INSERT ... RETURNING'",
418
+ )
419
+
420
+ @property
421
+ def update_returning(self):
422
+ """target platform supports UPDATE ... RETURNING."""
423
+
424
+ return exclusions.only_if(
425
+ lambda config: config.db.dialect.update_returning,
426
+ "%(database)s %(does_support)s 'UPDATE ... RETURNING'",
427
+ )
428
+
429
+ @property
430
+ def insert_executemany_returning(self):
431
+ """target platform supports RETURNING when INSERT is used with
432
+ executemany(), e.g. multiple parameter sets, indicating
433
+ as many rows come back as do parameter sets were passed.
434
+
435
+ """
436
+
437
+ return exclusions.only_if(
438
+ lambda config: config.db.dialect.insert_executemany_returning,
439
+ "%(database)s %(does_support)s 'RETURNING of "
440
+ "multiple rows with INSERT executemany'",
441
+ )
442
+
443
+ @property
444
+ def insertmanyvalues(self):
445
+ return exclusions.only_if(
446
+ lambda config: config.db.dialect.supports_multivalues_insert
447
+ and config.db.dialect.insert_returning
448
+ and config.db.dialect.use_insertmanyvalues,
449
+ "%(database)s %(does_support)s 'insertmanyvalues functionality",
450
+ )
451
+
452
+ @property
453
+ def tuple_in(self):
454
+ """Target platform supports the syntax
455
+ "(x, y) IN ((x1, y1), (x2, y2), ...)"
456
+ """
457
+
458
+ return exclusions.closed()
459
+
460
+ @property
461
+ def tuple_in_w_empty(self):
462
+ """Target platform tuple IN w/ empty set"""
463
+ return self.tuple_in
464
+
465
+ @property
466
+ def duplicate_names_in_cursor_description(self):
467
+ """target platform supports a SELECT statement that has
468
+ the same name repeated more than once in the columns list."""
469
+
470
+ return exclusions.open()
471
+
472
+ @property
473
+ def denormalized_names(self):
474
+ """Target database must have 'denormalized', i.e.
475
+ UPPERCASE as case insensitive names."""
476
+
477
+ return exclusions.skip_if(
478
+ lambda config: not config.db.dialect.requires_name_normalize,
479
+ "Backend does not require denormalized names.",
480
+ )
481
+
482
+ @property
483
+ def multivalues_inserts(self):
484
+ """target database must support multiple VALUES clauses in an
485
+ INSERT statement."""
486
+
487
+ return exclusions.skip_if(
488
+ lambda config: not config.db.dialect.supports_multivalues_insert,
489
+ "Backend does not support multirow inserts.",
490
+ )
491
+
492
+ @property
493
+ def implements_get_lastrowid(self):
494
+ """target dialect implements the executioncontext.get_lastrowid()
495
+ method without reliance on RETURNING.
496
+
497
+ """
498
+ return exclusions.open()
499
+
500
+ @property
501
+ def arraysize(self):
502
+ """dialect includes the required pep-249 attribute
503
+ ``cursor.arraysize``"""
504
+
505
+ return exclusions.open()
506
+
507
+ @property
508
+ def emulated_lastrowid(self):
509
+ """target dialect retrieves cursor.lastrowid, or fetches
510
+ from a database-side function after an insert() construct executes,
511
+ within the get_lastrowid() method.
512
+
513
+ Only dialects that "pre-execute", or need RETURNING to get last
514
+ inserted id, would return closed/fail/skip for this.
515
+
516
+ """
517
+ return exclusions.closed()
518
+
519
+ @property
520
+ def emulated_lastrowid_even_with_sequences(self):
521
+ """target dialect retrieves cursor.lastrowid or an equivalent
522
+ after an insert() construct executes, even if the table has a
523
+ Sequence on it.
524
+
525
+ """
526
+ return exclusions.closed()
527
+
528
+ @property
529
+ def dbapi_lastrowid(self):
530
+ """target platform includes a 'lastrowid' accessor on the DBAPI
531
+ cursor object.
532
+
533
+ """
534
+ return exclusions.closed()
535
+
536
+ @property
537
+ def views(self):
538
+ """Target database must support VIEWs."""
539
+
540
+ return exclusions.closed()
541
+
542
+ @property
543
+ def schemas(self):
544
+ """Target database must support external schemas, and have one
545
+ named 'test_schema'."""
546
+
547
+ return only_on(lambda config: config.db.dialect.supports_schemas)
548
+
549
+ @property
550
+ def cross_schema_fk_reflection(self):
551
+ """target system must support reflection of inter-schema
552
+ foreign keys"""
553
+ return exclusions.closed()
554
+
555
+ @property
556
+ def foreign_key_constraint_name_reflection(self):
557
+ """Target supports reflection of FOREIGN KEY constraints and
558
+ will return the name of the constraint that was used in the
559
+ "CONSTRAINT <name> FOREIGN KEY" DDL.
560
+
561
+ MySQL prior to version 8 and MariaDB prior to version 10.5
562
+ don't support this.
563
+
564
+ """
565
+ return exclusions.closed()
566
+
567
+ @property
568
+ def implicit_default_schema(self):
569
+ """target system has a strong concept of 'default' schema that can
570
+ be referred to implicitly.
571
+
572
+ basically, PostgreSQL.
573
+
574
+ """
575
+ return exclusions.closed()
576
+
577
+ @property
578
+ def default_schema_name_switch(self):
579
+ """target dialect implements provisioning module including
580
+ set_default_schema_on_connection"""
581
+
582
+ return exclusions.closed()
583
+
584
+ @property
585
+ def server_side_cursors(self):
586
+ """Target dialect must support server side cursors."""
587
+
588
+ return exclusions.only_if(
589
+ [lambda config: config.db.dialect.supports_server_side_cursors],
590
+ "no server side cursors support",
591
+ )
592
+
593
+ @property
594
+ def sequences(self):
595
+ """Target database must support SEQUENCEs."""
596
+
597
+ return exclusions.only_if(
598
+ [lambda config: config.db.dialect.supports_sequences],
599
+ "no sequence support",
600
+ )
601
+
602
+ @property
603
+ def no_sequences(self):
604
+ """the opposite of "sequences", DB does not support sequences at
605
+ all."""
606
+
607
+ return exclusions.NotPredicate(self.sequences)
608
+
609
+ @property
610
+ def sequences_optional(self):
611
+ """Target database supports sequences, but also optionally
612
+ as a means of generating new PK values."""
613
+
614
+ return exclusions.only_if(
615
+ [
616
+ lambda config: config.db.dialect.supports_sequences
617
+ and config.db.dialect.sequences_optional
618
+ ],
619
+ "no sequence support, or sequences not optional",
620
+ )
621
+
622
+ @property
623
+ def supports_lastrowid(self):
624
+ """target database / driver supports cursor.lastrowid as a means
625
+ of retrieving the last inserted primary key value.
626
+
627
+ note that if the target DB supports sequences also, this is still
628
+ assumed to work. This is a new use case brought on by MariaDB 10.3.
629
+
630
+ """
631
+ return exclusions.only_if(
632
+ [lambda config: config.db.dialect.postfetch_lastrowid]
633
+ )
634
+
635
+ @property
636
+ def no_lastrowid_support(self):
637
+ """the opposite of supports_lastrowid"""
638
+ return exclusions.only_if(
639
+ [lambda config: not config.db.dialect.postfetch_lastrowid]
640
+ )
641
+
642
+ @property
643
+ def reflects_pk_names(self):
644
+ return exclusions.closed()
645
+
646
+ @property
647
+ def table_reflection(self):
648
+ """target database has general support for table reflection"""
649
+ return exclusions.open()
650
+
651
+ @property
652
+ def reflect_tables_no_columns(self):
653
+ """target database supports creation and reflection of tables with no
654
+ columns, or at least tables that seem to have no columns."""
655
+
656
+ return exclusions.closed()
657
+
658
+ @property
659
+ def comment_reflection(self):
660
+ """Indicates if the database support table comment reflection"""
661
+ return exclusions.closed()
662
+
663
+ @property
664
+ def comment_reflection_full_unicode(self):
665
+ """Indicates if the database support table comment reflection in the
666
+ full unicode range, including emoji etc.
667
+ """
668
+ return exclusions.closed()
669
+
670
+ @property
671
+ def constraint_comment_reflection(self):
672
+ """indicates if the database support comments on constraints
673
+ and their reflection"""
674
+ return exclusions.closed()
675
+
676
+ @property
677
+ def view_column_reflection(self):
678
+ """target database must support retrieval of the columns in a view,
679
+ similarly to how a table is inspected.
680
+
681
+ This does not include the full CREATE VIEW definition.
682
+
683
+ """
684
+ return self.views
685
+
686
+ @property
687
+ def view_reflection(self):
688
+ """target database must support inspection of the full CREATE VIEW
689
+ definition."""
690
+ return self.views
691
+
692
+ @property
693
+ def schema_reflection(self):
694
+ return self.schemas
695
+
696
+ @property
697
+ def schema_create_delete(self):
698
+ """target database supports schema create and dropped with
699
+ 'CREATE SCHEMA' and 'DROP SCHEMA'"""
700
+ return exclusions.closed()
701
+
702
+ @property
703
+ def primary_key_constraint_reflection(self):
704
+ return exclusions.open()
705
+
706
+ @property
707
+ def foreign_key_constraint_reflection(self):
708
+ return exclusions.open()
709
+
710
+ @property
711
+ def foreign_key_constraint_option_reflection_ondelete(self):
712
+ return exclusions.closed()
713
+
714
+ @property
715
+ def fk_constraint_option_reflection_ondelete_restrict(self):
716
+ return exclusions.closed()
717
+
718
+ @property
719
+ def fk_constraint_option_reflection_ondelete_noaction(self):
720
+ return exclusions.closed()
721
+
722
+ @property
723
+ def foreign_key_constraint_option_reflection_onupdate(self):
724
+ return exclusions.closed()
725
+
726
+ @property
727
+ def fk_constraint_option_reflection_onupdate_restrict(self):
728
+ return exclusions.closed()
729
+
730
+ @property
731
+ def temp_table_reflection(self):
732
+ return exclusions.open()
733
+
734
+ @property
735
+ def temp_table_reflect_indexes(self):
736
+ return self.temp_table_reflection
737
+
738
+ @property
739
+ def temp_table_names(self):
740
+ """target dialect supports listing of temporary table names"""
741
+ return exclusions.closed()
742
+
743
+ @property
744
+ def has_temp_table(self):
745
+ """target dialect supports checking a single temp table name"""
746
+ return exclusions.closed()
747
+
748
+ @property
749
+ def temporary_tables(self):
750
+ """target database supports temporary tables"""
751
+ return exclusions.open()
752
+
753
+ @property
754
+ def temporary_views(self):
755
+ """target database supports temporary views"""
756
+ return exclusions.closed()
757
+
758
+ @property
759
+ def index_reflection(self):
760
+ return exclusions.open()
761
+
762
+ @property
763
+ def index_reflects_included_columns(self):
764
+ return exclusions.closed()
765
+
766
+ @property
767
+ def indexes_with_ascdesc(self):
768
+ """target database supports CREATE INDEX with per-column ASC/DESC."""
769
+ return exclusions.open()
770
+
771
+ @property
772
+ def reflect_indexes_with_ascdesc(self):
773
+ """target database supports reflecting INDEX with per-column
774
+ ASC/DESC."""
775
+ return exclusions.open()
776
+
777
+ @property
778
+ def reflect_indexes_with_ascdesc_as_expression(self):
779
+ """target database supports reflecting INDEX with per-column
780
+ ASC/DESC but reflects them as expressions (like oracle)."""
781
+ return exclusions.closed()
782
+
783
+ @property
784
+ def indexes_with_expressions(self):
785
+ """target database supports CREATE INDEX against SQL expressions."""
786
+ return exclusions.closed()
787
+
788
+ @property
789
+ def reflect_indexes_with_expressions(self):
790
+ """target database supports reflection of indexes with
791
+ SQL expressions."""
792
+ return exclusions.closed()
793
+
794
+ @property
795
+ def unique_constraint_reflection(self):
796
+ """target dialect supports reflection of unique constraints"""
797
+ return exclusions.open()
798
+
799
+ @property
800
+ def inline_check_constraint_reflection(self):
801
+ """target dialect supports reflection of inline check constraints"""
802
+ return exclusions.closed()
803
+
804
+ @property
805
+ def check_constraint_reflection(self):
806
+ """target dialect supports reflection of check constraints"""
807
+ return exclusions.closed()
808
+
809
+ @property
810
+ def duplicate_key_raises_integrity_error(self):
811
+ """target dialect raises IntegrityError when reporting an INSERT
812
+ with a primary key violation. (hint: it should)
813
+
814
+ """
815
+ return exclusions.open()
816
+
817
+ @property
818
+ def unbounded_varchar(self):
819
+ """Target database must support VARCHAR with no length"""
820
+
821
+ return exclusions.open()
822
+
823
+ @property
824
+ def unicode_data_no_special_types(self):
825
+ """Target database/dialect can receive / deliver / compare data with
826
+ non-ASCII characters in plain VARCHAR, TEXT columns, without the need
827
+ for special "national" datatypes like NVARCHAR or similar.
828
+
829
+ """
830
+ return exclusions.open()
831
+
832
+ @property
833
+ def unicode_data(self):
834
+ """Target database/dialect must support Python unicode objects with
835
+ non-ASCII characters represented, delivered as bound parameters
836
+ as well as in result rows.
837
+
838
+ """
839
+ return exclusions.open()
840
+
841
+ @property
842
+ def unicode_ddl(self):
843
+ """Target driver must support some degree of non-ascii symbol
844
+ names.
845
+ """
846
+ return exclusions.closed()
847
+
848
+ @property
849
+ def symbol_names_w_double_quote(self):
850
+ """Target driver can create tables with a name like 'some " table'"""
851
+ return exclusions.open()
852
+
853
+ @property
854
+ def datetime_interval(self):
855
+ """target dialect supports rendering of a datetime.timedelta as a
856
+ literal string, e.g. via the TypeEngine.literal_processor() method.
857
+
858
+ """
859
+ return exclusions.closed()
860
+
861
+ @property
862
+ def datetime_literals(self):
863
+ """target dialect supports rendering of a date, time, or datetime as a
864
+ literal string, e.g. via the TypeEngine.literal_processor() method.
865
+
866
+ """
867
+
868
+ return exclusions.closed()
869
+
870
+ @property
871
+ def datetime(self):
872
+ """target dialect supports representation of Python
873
+ datetime.datetime() objects."""
874
+
875
+ return exclusions.open()
876
+
877
+ @property
878
+ def datetime_timezone(self):
879
+ """target dialect supports representation of Python
880
+ datetime.datetime() with tzinfo with DateTime(timezone=True)."""
881
+
882
+ return exclusions.closed()
883
+
884
+ @property
885
+ def time_timezone(self):
886
+ """target dialect supports representation of Python
887
+ datetime.time() with tzinfo with Time(timezone=True)."""
888
+
889
+ return exclusions.closed()
890
+
891
+ @property
892
+ def date_implicit_bound(self):
893
+ """target dialect when given a date object will bind it such
894
+ that the database server knows the object is a date, and not
895
+ a plain string.
896
+
897
+ """
898
+ return exclusions.open()
899
+
900
+ @property
901
+ def time_implicit_bound(self):
902
+ """target dialect when given a time object will bind it such
903
+ that the database server knows the object is a time, and not
904
+ a plain string.
905
+
906
+ """
907
+ return exclusions.open()
908
+
909
+ @property
910
+ def datetime_implicit_bound(self):
911
+ """target dialect when given a datetime object will bind it such
912
+ that the database server knows the object is a datetime, and not
913
+ a plain string.
914
+
915
+ """
916
+ return exclusions.open()
917
+
918
+ @property
919
+ def datetime_microseconds(self):
920
+ """target dialect supports representation of Python
921
+ datetime.datetime() with microsecond objects."""
922
+
923
+ return exclusions.open()
924
+
925
+ @property
926
+ def timestamp_microseconds(self):
927
+ """target dialect supports representation of Python
928
+ datetime.datetime() with microsecond objects but only
929
+ if TIMESTAMP is used."""
930
+ return exclusions.closed()
931
+
932
+ @property
933
+ def timestamp_microseconds_implicit_bound(self):
934
+ """target dialect when given a datetime object which also includes
935
+ a microseconds portion when using the TIMESTAMP data type
936
+ will bind it such that the database server knows
937
+ the object is a datetime with microseconds, and not a plain string.
938
+
939
+ """
940
+ return self.timestamp_microseconds
941
+
942
+ @property
943
+ def datetime_historic(self):
944
+ """target dialect supports representation of Python
945
+ datetime.datetime() objects with historic (pre 1970) values."""
946
+
947
+ return exclusions.closed()
948
+
949
+ @property
950
+ def date(self):
951
+ """target dialect supports representation of Python
952
+ datetime.date() objects."""
953
+
954
+ return exclusions.open()
955
+
956
+ @property
957
+ def date_coerces_from_datetime(self):
958
+ """target dialect accepts a datetime object as the target
959
+ of a date column."""
960
+
961
+ return exclusions.open()
962
+
963
+ @property
964
+ def date_historic(self):
965
+ """target dialect supports representation of Python
966
+ datetime.datetime() objects with historic (pre 1970) values."""
967
+
968
+ return exclusions.closed()
969
+
970
+ @property
971
+ def time(self):
972
+ """target dialect supports representation of Python
973
+ datetime.time() objects."""
974
+
975
+ return exclusions.open()
976
+
977
+ @property
978
+ def time_microseconds(self):
979
+ """target dialect supports representation of Python
980
+ datetime.time() with microsecond objects."""
981
+
982
+ return exclusions.open()
983
+
984
+ @property
985
+ def binary_comparisons(self):
986
+ """target database/driver can allow BLOB/BINARY fields to be compared
987
+ against a bound parameter value.
988
+ """
989
+
990
+ return exclusions.open()
991
+
992
+ @property
993
+ def binary_literals(self):
994
+ """target backend supports simple binary literals, e.g. an
995
+ expression like::
996
+
997
+ SELECT CAST('foo' AS BINARY)
998
+
999
+ Where ``BINARY`` is the type emitted from :class:`.LargeBinary`,
1000
+ e.g. it could be ``BLOB`` or similar.
1001
+
1002
+ Basically fails on Oracle.
1003
+
1004
+ """
1005
+
1006
+ return exclusions.open()
1007
+
1008
+ @property
1009
+ def autocommit(self):
1010
+ """target dialect supports 'AUTOCOMMIT' as an isolation_level"""
1011
+ return exclusions.closed()
1012
+
1013
+ @property
1014
+ def isolation_level(self):
1015
+ """target dialect supports general isolation level settings.
1016
+
1017
+ Note that this requirement, when enabled, also requires that
1018
+ the get_isolation_levels() method be implemented.
1019
+
1020
+ """
1021
+ return exclusions.closed()
1022
+
1023
+ def get_isolation_levels(self, config):
1024
+ """Return a structure of supported isolation levels for the current
1025
+ testing dialect.
1026
+
1027
+ The structure indicates to the testing suite what the expected
1028
+ "default" isolation should be, as well as the other values that
1029
+ are accepted. The dictionary has two keys, "default" and "supported".
1030
+ The "supported" key refers to a list of all supported levels and
1031
+ it should include AUTOCOMMIT if the dialect supports it.
1032
+
1033
+ If the :meth:`.DefaultRequirements.isolation_level` requirement is
1034
+ not open, then this method has no return value.
1035
+
1036
+ E.g.::
1037
+
1038
+ >>> testing.requirements.get_isolation_levels()
1039
+ {
1040
+ "default": "READ_COMMITTED",
1041
+ "supported": [
1042
+ "SERIALIZABLE", "READ UNCOMMITTED",
1043
+ "READ COMMITTED", "REPEATABLE READ",
1044
+ "AUTOCOMMIT"
1045
+ ]
1046
+ }
1047
+ """
1048
+ with config.db.connect() as conn:
1049
+ try:
1050
+ supported = conn.dialect.get_isolation_level_values(
1051
+ conn.connection.dbapi_connection
1052
+ )
1053
+ except NotImplementedError:
1054
+ return None
1055
+ else:
1056
+ return {
1057
+ "default": conn.dialect.default_isolation_level,
1058
+ "supported": supported,
1059
+ }
1060
+
1061
+ @property
1062
+ def get_isolation_level_values(self):
1063
+ """target dialect supports the
1064
+ :meth:`_engine.Dialect.get_isolation_level_values`
1065
+ method added in SQLAlchemy 2.0.
1066
+
1067
+ """
1068
+
1069
+ def go(config):
1070
+ with config.db.connect() as conn:
1071
+ try:
1072
+ conn.dialect.get_isolation_level_values(
1073
+ conn.connection.dbapi_connection
1074
+ )
1075
+ except NotImplementedError:
1076
+ return False
1077
+ else:
1078
+ return True
1079
+
1080
+ return exclusions.only_if(go)
1081
+
1082
+ @property
1083
+ def dialect_level_isolation_level_param(self):
1084
+ """test that the dialect allows the 'isolation_level' argument
1085
+ to be handled by DefaultDialect"""
1086
+
1087
+ def go(config):
1088
+ try:
1089
+ e = create_engine(
1090
+ config.db.url, isolation_level="READ COMMITTED"
1091
+ )
1092
+ except:
1093
+ return False
1094
+ else:
1095
+ return (
1096
+ e.dialect._on_connect_isolation_level == "READ COMMITTED"
1097
+ )
1098
+
1099
+ return exclusions.only_if(go)
1100
+
1101
+ @property
1102
+ def array_type(self):
1103
+ """Target platform implements a native ARRAY type"""
1104
+ return exclusions.closed()
1105
+
1106
+ @property
1107
+ def json_type(self):
1108
+ """target platform implements a native JSON type."""
1109
+
1110
+ return exclusions.closed()
1111
+
1112
+ @property
1113
+ def json_array_indexes(self):
1114
+ """target platform supports numeric array indexes
1115
+ within a JSON structure"""
1116
+
1117
+ return self.json_type
1118
+
1119
+ @property
1120
+ def json_index_supplementary_unicode_element(self):
1121
+ return exclusions.open()
1122
+
1123
+ @property
1124
+ def legacy_unconditional_json_extract(self):
1125
+ """Backend has a JSON_EXTRACT or similar function that returns a
1126
+ valid JSON string in all cases.
1127
+
1128
+ Used to test a legacy feature and is not needed.
1129
+
1130
+ """
1131
+ return exclusions.closed()
1132
+
1133
+ @property
1134
+ def precision_numerics_general(self):
1135
+ """target backend has general support for moderately high-precision
1136
+ numerics."""
1137
+ return exclusions.open()
1138
+
1139
+ @property
1140
+ def precision_numerics_enotation_small(self):
1141
+ """target backend supports Decimal() objects using E notation
1142
+ to represent very small values."""
1143
+ return exclusions.closed()
1144
+
1145
+ @property
1146
+ def precision_numerics_enotation_large(self):
1147
+ """target backend supports Decimal() objects using E notation
1148
+ to represent very large values."""
1149
+ return exclusions.open()
1150
+
1151
+ @property
1152
+ def precision_numerics_many_significant_digits(self):
1153
+ """target backend supports values with many digits on both sides,
1154
+ such as 319438950232418390.273596, 87673.594069654243
1155
+
1156
+ """
1157
+ return exclusions.closed()
1158
+
1159
+ @property
1160
+ def cast_precision_numerics_many_significant_digits(self):
1161
+ """same as precision_numerics_many_significant_digits but within the
1162
+ context of a CAST statement (hello MySQL)
1163
+
1164
+ """
1165
+ return self.precision_numerics_many_significant_digits
1166
+
1167
+ @property
1168
+ def implicit_decimal_binds(self):
1169
+ """target backend will return a selected Decimal as a Decimal, not
1170
+ a string.
1171
+
1172
+ e.g.::
1173
+
1174
+ expr = decimal.Decimal("15.7563")
1175
+
1176
+ value = e.scalar(
1177
+ select(literal(expr))
1178
+ )
1179
+
1180
+ assert value == expr
1181
+
1182
+ See :ticket:`4036`
1183
+
1184
+ """
1185
+
1186
+ return exclusions.open()
1187
+
1188
+ @property
1189
+ def numeric_received_as_decimal_untyped(self):
1190
+ """target backend will return result columns that are explicitly
1191
+ against NUMERIC or similar precision-numeric datatypes (not including
1192
+ FLOAT or INT types) as Python Decimal objects, and not as floats
1193
+ or ints, including when no SQLAlchemy-side typing information is
1194
+ associated with the statement (e.g. such as a raw SQL string).
1195
+
1196
+ This should be enabled if either the DBAPI itself returns Decimal
1197
+ objects, or if the dialect has set up DBAPI-specific return type
1198
+ handlers such that Decimal objects come back automatically.
1199
+
1200
+ """
1201
+ return exclusions.open()
1202
+
1203
+ @property
1204
+ def nested_aggregates(self):
1205
+ """target database can select an aggregate from a subquery that's
1206
+ also using an aggregate
1207
+
1208
+ """
1209
+ return exclusions.open()
1210
+
1211
+ @property
1212
+ def recursive_fk_cascade(self):
1213
+ """target database must support ON DELETE CASCADE on a self-referential
1214
+ foreign key
1215
+
1216
+ """
1217
+ return exclusions.open()
1218
+
1219
+ @property
1220
+ def precision_numerics_retains_significant_digits(self):
1221
+ """A precision numeric type will return empty significant digits,
1222
+ i.e. a value such as 10.000 will come back in Decimal form with
1223
+ the .000 maintained."""
1224
+
1225
+ return exclusions.closed()
1226
+
1227
+ @property
1228
+ def infinity_floats(self):
1229
+ """The Float type can persist and load float('inf'), float('-inf')."""
1230
+
1231
+ return exclusions.closed()
1232
+
1233
+ @property
1234
+ def float_or_double_precision_behaves_generically(self):
1235
+ return exclusions.closed()
1236
+
1237
+ @property
1238
+ def precision_generic_float_type(self):
1239
+ """target backend will return native floating point numbers with at
1240
+ least seven decimal places when using the generic Float type.
1241
+
1242
+ """
1243
+ return exclusions.open()
1244
+
1245
+ @property
1246
+ def literal_float_coercion(self):
1247
+ """target backend will return the exact float value 15.7563
1248
+ with only four significant digits from this statement:
1249
+
1250
+ SELECT :param
1251
+
1252
+ where :param is the Python float 15.7563
1253
+
1254
+ i.e. it does not return 15.75629997253418
1255
+
1256
+ """
1257
+ return exclusions.open()
1258
+
1259
+ @property
1260
+ def floats_to_four_decimals(self):
1261
+ """target backend can return a floating-point number with four
1262
+ significant digits (such as 15.7563) accurately
1263
+ (i.e. without FP inaccuracies, such as 15.75629997253418).
1264
+
1265
+ """
1266
+ return exclusions.open()
1267
+
1268
+ @property
1269
+ def fetch_null_from_numeric(self):
1270
+ """target backend doesn't crash when you try to select a NUMERIC
1271
+ value that has a value of NULL.
1272
+
1273
+ Added to support Pyodbc bug #351.
1274
+ """
1275
+
1276
+ return exclusions.open()
1277
+
1278
+ @property
1279
+ def float_is_numeric(self):
1280
+ """target backend uses Numeric for Float/Dual"""
1281
+
1282
+ return exclusions.open()
1283
+
1284
+ @property
1285
+ def text_type(self):
1286
+ """Target database must support an unbounded Text() "
1287
+ "type such as TEXT or CLOB"""
1288
+
1289
+ return exclusions.open()
1290
+
1291
+ @property
1292
+ def empty_strings_varchar(self):
1293
+ """target database can persist/return an empty string with a
1294
+ varchar.
1295
+
1296
+ """
1297
+ return exclusions.open()
1298
+
1299
+ @property
1300
+ def empty_strings_text(self):
1301
+ """target database can persist/return an empty string with an
1302
+ unbounded text."""
1303
+
1304
+ return exclusions.open()
1305
+
1306
+ @property
1307
+ def expressions_against_unbounded_text(self):
1308
+ """target database supports use of an unbounded textual field in a
1309
+ WHERE clause."""
1310
+
1311
+ return exclusions.open()
1312
+
1313
+ @property
1314
+ def selectone(self):
1315
+ """target driver must support the literal statement 'select 1'"""
1316
+ return exclusions.open()
1317
+
1318
+ @property
1319
+ def savepoints(self):
1320
+ """Target database must support savepoints."""
1321
+
1322
+ return exclusions.closed()
1323
+
1324
+ @property
1325
+ def two_phase_transactions(self):
1326
+ """Target database must support two-phase transactions."""
1327
+
1328
+ return exclusions.closed()
1329
+
1330
+ @property
1331
+ def update_from(self):
1332
+ """Target must support UPDATE..FROM syntax"""
1333
+ return exclusions.closed()
1334
+
1335
+ @property
1336
+ def delete_from(self):
1337
+ """Target must support DELETE FROM..FROM or DELETE..USING syntax"""
1338
+ return exclusions.closed()
1339
+
1340
+ @property
1341
+ def update_where_target_in_subquery(self):
1342
+ """Target must support UPDATE (or DELETE) where the same table is
1343
+ present in a subquery in the WHERE clause.
1344
+
1345
+ This is an ANSI-standard syntax that apparently MySQL can't handle,
1346
+ such as::
1347
+
1348
+ UPDATE documents SET flag=1 WHERE documents.title IN
1349
+ (SELECT max(documents.title) AS title
1350
+ FROM documents GROUP BY documents.user_id
1351
+ )
1352
+
1353
+ """
1354
+ return exclusions.open()
1355
+
1356
+ @property
1357
+ def mod_operator_as_percent_sign(self):
1358
+ """target database must use a plain percent '%' as the 'modulus'
1359
+ operator."""
1360
+ return exclusions.closed()
1361
+
1362
+ @property
1363
+ def percent_schema_names(self):
1364
+ """target backend supports weird identifiers with percent signs
1365
+ in them, e.g. 'some % column'.
1366
+
1367
+ this is a very weird use case but often has problems because of
1368
+ DBAPIs that use python formatting. It's not a critical use
1369
+ case either.
1370
+
1371
+ """
1372
+ return exclusions.closed()
1373
+
1374
+ @property
1375
+ def order_by_col_from_union(self):
1376
+ """target database supports ordering by a column from a SELECT
1377
+ inside of a UNION
1378
+
1379
+ E.g. (SELECT id, ...) UNION (SELECT id, ...) ORDER BY id
1380
+
1381
+ """
1382
+ return exclusions.open()
1383
+
1384
+ @property
1385
+ def order_by_label_with_expression(self):
1386
+ """target backend supports ORDER BY a column label within an
1387
+ expression.
1388
+
1389
+ Basically this::
1390
+
1391
+ select data as foo from test order by foo || 'bar'
1392
+
1393
+ Lots of databases including PostgreSQL don't support this,
1394
+ so this is off by default.
1395
+
1396
+ """
1397
+ return exclusions.closed()
1398
+
1399
+ @property
1400
+ def order_by_collation(self):
1401
+ def check(config):
1402
+ try:
1403
+ self.get_order_by_collation(config)
1404
+ return False
1405
+ except NotImplementedError:
1406
+ return True
1407
+
1408
+ return exclusions.skip_if(check)
1409
+
1410
+ def get_order_by_collation(self, config):
1411
+ raise NotImplementedError()
1412
+
1413
+ @property
1414
+ def unicode_connections(self):
1415
+ """Target driver must support non-ASCII characters being passed at
1416
+ all.
1417
+ """
1418
+ return exclusions.open()
1419
+
1420
+ @property
1421
+ def graceful_disconnects(self):
1422
+ """Target driver must raise a DBAPI-level exception, such as
1423
+ InterfaceError, when the underlying connection has been closed
1424
+ and the execute() method is called.
1425
+ """
1426
+ return exclusions.open()
1427
+
1428
+ @property
1429
+ def independent_connections(self):
1430
+ """
1431
+ Target must support simultaneous, independent database connections.
1432
+ """
1433
+ return exclusions.open()
1434
+
1435
+ @property
1436
+ def independent_readonly_connections(self):
1437
+ """
1438
+ Target must support simultaneous, independent database connections
1439
+ that will be used in a readonly fashion.
1440
+
1441
+ """
1442
+ return exclusions.open()
1443
+
1444
+ @property
1445
+ def skip_mysql_on_windows(self):
1446
+ """Catchall for a large variety of MySQL on Windows failures"""
1447
+ return exclusions.open()
1448
+
1449
+ @property
1450
+ def ad_hoc_engines(self):
1451
+ """Test environment must allow ad-hoc engine/connection creation.
1452
+
1453
+ DBs that scale poorly for many connections, even when closed, i.e.
1454
+ Oracle, may use the "--low-connections" option which flags this
1455
+ requirement as not present.
1456
+
1457
+ """
1458
+ return exclusions.skip_if(
1459
+ lambda config: config.options.low_connections
1460
+ )
1461
+
1462
+ @property
1463
+ def no_windows(self):
1464
+ return exclusions.skip_if(self._running_on_windows())
1465
+
1466
+ def _running_on_windows(self):
1467
+ return exclusions.LambdaPredicate(
1468
+ lambda: platform.system() == "Windows",
1469
+ description="running on Windows",
1470
+ )
1471
+
1472
+ @property
1473
+ def timing_intensive(self):
1474
+ from . import config
1475
+
1476
+ return config.add_to_marker.timing_intensive
1477
+
1478
+ @property
1479
+ def memory_intensive(self):
1480
+ from . import config
1481
+
1482
+ return config.add_to_marker.memory_intensive
1483
+
1484
+ @property
1485
+ def threading_with_mock(self):
1486
+ """Mark tests that use threading and mock at the same time - stability
1487
+ issues have been observed with coverage
1488
+
1489
+ """
1490
+ return exclusions.skip_if(
1491
+ lambda config: config.options.has_coverage,
1492
+ "Stability issues with coverage",
1493
+ )
1494
+
1495
+ @property
1496
+ def sqlalchemy2_stubs(self):
1497
+ def check(config):
1498
+ try:
1499
+ __import__("sqlalchemy-stubs.ext.mypy")
1500
+ except ImportError:
1501
+ return False
1502
+ else:
1503
+ return True
1504
+
1505
+ return exclusions.only_if(check)
1506
+
1507
+ @property
1508
+ def no_sqlalchemy2_stubs(self):
1509
+ def check(config):
1510
+ try:
1511
+ __import__("sqlalchemy-stubs.ext.mypy")
1512
+ except ImportError:
1513
+ return False
1514
+ else:
1515
+ return True
1516
+
1517
+ return exclusions.skip_if(check)
1518
+
1519
+ @property
1520
+ def python38(self):
1521
+ return exclusions.only_if(
1522
+ lambda: util.py38, "Python 3.8 or above required"
1523
+ )
1524
+
1525
+ @property
1526
+ def python39(self):
1527
+ return exclusions.only_if(
1528
+ lambda: util.py39, "Python 3.9 or above required"
1529
+ )
1530
+
1531
+ @property
1532
+ def python310(self):
1533
+ return exclusions.only_if(
1534
+ lambda: util.py310, "Python 3.10 or above required"
1535
+ )
1536
+
1537
+ @property
1538
+ def python311(self):
1539
+ return exclusions.only_if(
1540
+ lambda: util.py311, "Python 3.11 or above required"
1541
+ )
1542
+
1543
+ @property
1544
+ def python312(self):
1545
+ return exclusions.only_if(
1546
+ lambda: util.py312, "Python 3.12 or above required"
1547
+ )
1548
+
1549
+ @property
1550
+ def cpython(self):
1551
+ return exclusions.only_if(
1552
+ lambda: util.cpython, "cPython interpreter needed"
1553
+ )
1554
+
1555
+ @property
1556
+ def is64bit(self):
1557
+ return exclusions.only_if(lambda: util.is64bit, "64bit required")
1558
+
1559
+ @property
1560
+ def patch_library(self):
1561
+ def check_lib():
1562
+ try:
1563
+ __import__("patch")
1564
+ except ImportError:
1565
+ return False
1566
+ else:
1567
+ return True
1568
+
1569
+ return exclusions.only_if(check_lib, "patch library needed")
1570
+
1571
+ @property
1572
+ def predictable_gc(self):
1573
+ """target platform must remove all cycles unconditionally when
1574
+ gc.collect() is called, as well as clean out unreferenced subclasses.
1575
+
1576
+ """
1577
+ return self.cpython
1578
+
1579
+ @property
1580
+ def no_coverage(self):
1581
+ """Test should be skipped if coverage is enabled.
1582
+
1583
+ This is to block tests that exercise libraries that seem to be
1584
+ sensitive to coverage, such as PostgreSQL notice logging.
1585
+
1586
+ """
1587
+ return exclusions.skip_if(
1588
+ lambda config: config.options.has_coverage,
1589
+ "Issues observed when coverage is enabled",
1590
+ )
1591
+
1592
+ def _has_mysql_on_windows(self, config):
1593
+ return False
1594
+
1595
+ def _has_mysql_fully_case_sensitive(self, config):
1596
+ return False
1597
+
1598
+ @property
1599
+ def sqlite(self):
1600
+ return exclusions.skip_if(lambda: not self._has_sqlite())
1601
+
1602
+ @property
1603
+ def cextensions(self):
1604
+ return exclusions.skip_if(
1605
+ lambda: not util.has_compiled_ext(),
1606
+ "Cython extensions not installed",
1607
+ )
1608
+
1609
+ def _has_sqlite(self):
1610
+ from sqlalchemy import create_engine
1611
+
1612
+ try:
1613
+ create_engine("sqlite://")
1614
+ return True
1615
+ except ImportError:
1616
+ return False
1617
+
1618
+ @property
1619
+ def async_dialect(self):
1620
+ """dialect makes use of await_() to invoke operations on the DBAPI."""
1621
+
1622
+ return exclusions.closed()
1623
+
1624
+ @property
1625
+ def asyncio(self):
1626
+ return self.greenlet
1627
+
1628
+ @property
1629
+ def no_greenlet(self):
1630
+ def go(config):
1631
+ try:
1632
+ import greenlet # noqa: F401
1633
+ except ImportError:
1634
+ return True
1635
+ else:
1636
+ return False
1637
+
1638
+ return exclusions.only_if(go)
1639
+
1640
+ @property
1641
+ def greenlet(self):
1642
+ def go(config):
1643
+ if not _test_asyncio.ENABLE_ASYNCIO:
1644
+ return False
1645
+
1646
+ try:
1647
+ import greenlet # noqa: F401
1648
+ except ImportError:
1649
+ return False
1650
+ else:
1651
+ return True
1652
+
1653
+ return exclusions.only_if(go)
1654
+
1655
+ @property
1656
+ def computed_columns(self):
1657
+ "Supports computed columns"
1658
+ return exclusions.closed()
1659
+
1660
+ @property
1661
+ def computed_columns_stored(self):
1662
+ "Supports computed columns with `persisted=True`"
1663
+ return exclusions.closed()
1664
+
1665
+ @property
1666
+ def computed_columns_virtual(self):
1667
+ "Supports computed columns with `persisted=False`"
1668
+ return exclusions.closed()
1669
+
1670
+ @property
1671
+ def computed_columns_default_persisted(self):
1672
+ """If the default persistence is virtual or stored when `persisted`
1673
+ is omitted"""
1674
+ return exclusions.closed()
1675
+
1676
+ @property
1677
+ def computed_columns_reflect_persisted(self):
1678
+ """If persistence information is returned by the reflection of
1679
+ computed columns"""
1680
+ return exclusions.closed()
1681
+
1682
+ @property
1683
+ def supports_distinct_on(self):
1684
+ """If a backend supports the DISTINCT ON in a select"""
1685
+ return exclusions.closed()
1686
+
1687
+ @property
1688
+ def supports_is_distinct_from(self):
1689
+ """Supports some form of "x IS [NOT] DISTINCT FROM y" construct.
1690
+ Different dialects will implement their own flavour, e.g.,
1691
+ sqlite will emit "x IS NOT y" instead of "x IS DISTINCT FROM y".
1692
+
1693
+ .. seealso::
1694
+
1695
+ :meth:`.ColumnOperators.is_distinct_from`
1696
+
1697
+ """
1698
+ return exclusions.skip_if(
1699
+ lambda config: not config.db.dialect.supports_is_distinct_from,
1700
+ "driver doesn't support an IS DISTINCT FROM construct",
1701
+ )
1702
+
1703
+ @property
1704
+ def identity_columns(self):
1705
+ """If a backend supports GENERATED { ALWAYS | BY DEFAULT }
1706
+ AS IDENTITY"""
1707
+ return exclusions.closed()
1708
+
1709
+ @property
1710
+ def identity_columns_standard(self):
1711
+ """If a backend supports GENERATED { ALWAYS | BY DEFAULT }
1712
+ AS IDENTITY with a standard syntax.
1713
+ This is mainly to exclude MSSql.
1714
+ """
1715
+ return exclusions.closed()
1716
+
1717
+ @property
1718
+ def regexp_match(self):
1719
+ """backend supports the regexp_match operator."""
1720
+ return exclusions.closed()
1721
+
1722
+ @property
1723
+ def regexp_replace(self):
1724
+ """backend supports the regexp_replace operator."""
1725
+ return exclusions.closed()
1726
+
1727
+ @property
1728
+ def fetch_first(self):
1729
+ """backend supports the fetch first clause."""
1730
+ return exclusions.closed()
1731
+
1732
+ @property
1733
+ def fetch_percent(self):
1734
+ """backend supports the fetch first clause with percent."""
1735
+ return exclusions.closed()
1736
+
1737
+ @property
1738
+ def fetch_ties(self):
1739
+ """backend supports the fetch first clause with ties."""
1740
+ return exclusions.closed()
1741
+
1742
+ @property
1743
+ def fetch_no_order_by(self):
1744
+ """backend supports the fetch first without order by"""
1745
+ return exclusions.closed()
1746
+
1747
+ @property
1748
+ def fetch_offset_with_options(self):
1749
+ """backend supports the offset when using fetch first with percent
1750
+ or ties. basically this is "not mssql"
1751
+ """
1752
+ return exclusions.closed()
1753
+
1754
+ @property
1755
+ def fetch_expression(self):
1756
+ """backend supports fetch / offset with expression in them, like
1757
+
1758
+ SELECT * FROM some_table
1759
+ OFFSET 1 + 1 ROWS FETCH FIRST 1 + 1 ROWS ONLY
1760
+ """
1761
+ return exclusions.closed()
1762
+
1763
+ @property
1764
+ def autoincrement_without_sequence(self):
1765
+ """If autoincrement=True on a column does not require an explicit
1766
+ sequence. This should be false only for oracle.
1767
+ """
1768
+ return exclusions.open()
1769
+
1770
+ @property
1771
+ def generic_classes(self):
1772
+ "If X[Y] can be implemented with ``__class_getitem__``. py3.7+"
1773
+ return exclusions.open()
1774
+
1775
+ @property
1776
+ def json_deserializer_binary(self):
1777
+ "indicates if the json_deserializer function is called with bytes"
1778
+ return exclusions.closed()
1779
+
1780
+ @property
1781
+ def reflect_table_options(self):
1782
+ """Target database must support reflecting table_options."""
1783
+ return exclusions.closed()
1784
+
1785
+ @property
1786
+ def materialized_views(self):
1787
+ """Target database must support MATERIALIZED VIEWs."""
1788
+ return exclusions.closed()
1789
+
1790
+ @property
1791
+ def materialized_views_reflect_pk(self):
1792
+ """Target database reflect MATERIALIZED VIEWs pks."""
1793
+ return exclusions.closed()
1794
+
1795
+ @property
1796
+ def supports_bitwise_or(self):
1797
+ """Target database supports bitwise or"""
1798
+ return exclusions.closed()
1799
+
1800
+ @property
1801
+ def supports_bitwise_and(self):
1802
+ """Target database supports bitwise and"""
1803
+ return exclusions.closed()
1804
+
1805
+ @property
1806
+ def supports_bitwise_not(self):
1807
+ """Target database supports bitwise not"""
1808
+ return exclusions.closed()
1809
+
1810
+ @property
1811
+ def supports_bitwise_xor(self):
1812
+ """Target database supports bitwise xor"""
1813
+ return exclusions.closed()
1814
+
1815
+ @property
1816
+ def supports_bitwise_shift(self):
1817
+ """Target database supports bitwise left or right shift"""
1818
+ return exclusions.closed()