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,756 @@
1
+ # dialects/sqlite/pysqlite.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
+ r"""
11
+ .. dialect:: sqlite+pysqlite
12
+ :name: pysqlite
13
+ :dbapi: sqlite3
14
+ :connectstring: sqlite+pysqlite:///file_path
15
+ :url: https://docs.python.org/library/sqlite3.html
16
+
17
+ Note that ``pysqlite`` is the same driver as the ``sqlite3``
18
+ module included with the Python distribution.
19
+
20
+ Driver
21
+ ------
22
+
23
+ The ``sqlite3`` Python DBAPI is standard on all modern Python versions;
24
+ for cPython and Pypy, no additional installation is necessary.
25
+
26
+
27
+ Connect Strings
28
+ ---------------
29
+
30
+ The file specification for the SQLite database is taken as the "database"
31
+ portion of the URL. Note that the format of a SQLAlchemy url is::
32
+
33
+ driver://user:pass@host/database
34
+
35
+ This means that the actual filename to be used starts with the characters to
36
+ the **right** of the third slash. So connecting to a relative filepath
37
+ looks like::
38
+
39
+ # relative path
40
+ e = create_engine('sqlite:///path/to/database.db')
41
+
42
+ An absolute path, which is denoted by starting with a slash, means you
43
+ need **four** slashes::
44
+
45
+ # absolute path
46
+ e = create_engine('sqlite:////path/to/database.db')
47
+
48
+ To use a Windows path, regular drive specifications and backslashes can be
49
+ used. Double backslashes are probably needed::
50
+
51
+ # absolute path on Windows
52
+ e = create_engine('sqlite:///C:\\path\\to\\database.db')
53
+
54
+ To use sqlite ``:memory:`` database specify it as the filename using
55
+ ``sqlite:///:memory:``. It's also the default if no filepath is
56
+ present, specifying only ``sqlite://`` and nothing else::
57
+
58
+ # in-memory database (note three slashes)
59
+ e = create_engine('sqlite:///:memory:')
60
+ # also in-memory database
61
+ e2 = create_engine('sqlite://')
62
+
63
+ .. _pysqlite_uri_connections:
64
+
65
+ URI Connections
66
+ ^^^^^^^^^^^^^^^
67
+
68
+ Modern versions of SQLite support an alternative system of connecting using a
69
+ `driver level URI <https://www.sqlite.org/uri.html>`_, which has the advantage
70
+ that additional driver-level arguments can be passed including options such as
71
+ "read only". The Python sqlite3 driver supports this mode under modern Python
72
+ 3 versions. The SQLAlchemy pysqlite driver supports this mode of use by
73
+ specifying "uri=true" in the URL query string. The SQLite-level "URI" is kept
74
+ as the "database" portion of the SQLAlchemy url (that is, following a slash)::
75
+
76
+ e = create_engine("sqlite:///file:path/to/database?mode=ro&uri=true")
77
+
78
+ .. note:: The "uri=true" parameter must appear in the **query string**
79
+ of the URL. It will not currently work as expected if it is only
80
+ present in the :paramref:`_sa.create_engine.connect_args`
81
+ parameter dictionary.
82
+
83
+ The logic reconciles the simultaneous presence of SQLAlchemy's query string and
84
+ SQLite's query string by separating out the parameters that belong to the
85
+ Python sqlite3 driver vs. those that belong to the SQLite URI. This is
86
+ achieved through the use of a fixed list of parameters known to be accepted by
87
+ the Python side of the driver. For example, to include a URL that indicates
88
+ the Python sqlite3 "timeout" and "check_same_thread" parameters, along with the
89
+ SQLite "mode" and "nolock" parameters, they can all be passed together on the
90
+ query string::
91
+
92
+ e = create_engine(
93
+ "sqlite:///file:path/to/database?"
94
+ "check_same_thread=true&timeout=10&mode=ro&nolock=1&uri=true"
95
+ )
96
+
97
+ Above, the pysqlite / sqlite3 DBAPI would be passed arguments as::
98
+
99
+ sqlite3.connect(
100
+ "file:path/to/database?mode=ro&nolock=1",
101
+ check_same_thread=True, timeout=10, uri=True
102
+ )
103
+
104
+ Regarding future parameters added to either the Python or native drivers. new
105
+ parameter names added to the SQLite URI scheme should be automatically
106
+ accommodated by this scheme. New parameter names added to the Python driver
107
+ side can be accommodated by specifying them in the
108
+ :paramref:`_sa.create_engine.connect_args` dictionary,
109
+ until dialect support is
110
+ added by SQLAlchemy. For the less likely case that the native SQLite driver
111
+ adds a new parameter name that overlaps with one of the existing, known Python
112
+ driver parameters (such as "timeout" perhaps), SQLAlchemy's dialect would
113
+ require adjustment for the URL scheme to continue to support this.
114
+
115
+ As is always the case for all SQLAlchemy dialects, the entire "URL" process
116
+ can be bypassed in :func:`_sa.create_engine` through the use of the
117
+ :paramref:`_sa.create_engine.creator`
118
+ parameter which allows for a custom callable
119
+ that creates a Python sqlite3 driver level connection directly.
120
+
121
+ .. versionadded:: 1.3.9
122
+
123
+ .. seealso::
124
+
125
+ `Uniform Resource Identifiers <https://www.sqlite.org/uri.html>`_ - in
126
+ the SQLite documentation
127
+
128
+ .. _pysqlite_regexp:
129
+
130
+ Regular Expression Support
131
+ ---------------------------
132
+
133
+ .. versionadded:: 1.4
134
+
135
+ Support for the :meth:`_sql.ColumnOperators.regexp_match` operator is provided
136
+ using Python's re.search_ function. SQLite itself does not include a working
137
+ regular expression operator; instead, it includes a non-implemented placeholder
138
+ operator ``REGEXP`` that calls a user-defined function that must be provided.
139
+
140
+ SQLAlchemy's implementation makes use of the pysqlite create_function_ hook
141
+ as follows::
142
+
143
+
144
+ def regexp(a, b):
145
+ return re.search(a, b) is not None
146
+
147
+ sqlite_connection.create_function(
148
+ "regexp", 2, regexp,
149
+ )
150
+
151
+ There is currently no support for regular expression flags as a separate
152
+ argument, as these are not supported by SQLite's REGEXP operator, however these
153
+ may be included inline within the regular expression string. See `Python regular expressions`_ for
154
+ details.
155
+
156
+ .. seealso::
157
+
158
+ `Python regular expressions`_: Documentation for Python's regular expression syntax.
159
+
160
+ .. _create_function: https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.create_function
161
+
162
+ .. _re.search: https://docs.python.org/3/library/re.html#re.search
163
+
164
+ .. _Python regular expressions: https://docs.python.org/3/library/re.html#re.search
165
+
166
+
167
+
168
+ Compatibility with sqlite3 "native" date and datetime types
169
+ -----------------------------------------------------------
170
+
171
+ The pysqlite driver includes the sqlite3.PARSE_DECLTYPES and
172
+ sqlite3.PARSE_COLNAMES options, which have the effect of any column
173
+ or expression explicitly cast as "date" or "timestamp" will be converted
174
+ to a Python date or datetime object. The date and datetime types provided
175
+ with the pysqlite dialect are not currently compatible with these options,
176
+ since they render the ISO date/datetime including microseconds, which
177
+ pysqlite's driver does not. Additionally, SQLAlchemy does not at
178
+ this time automatically render the "cast" syntax required for the
179
+ freestanding functions "current_timestamp" and "current_date" to return
180
+ datetime/date types natively. Unfortunately, pysqlite
181
+ does not provide the standard DBAPI types in ``cursor.description``,
182
+ leaving SQLAlchemy with no way to detect these types on the fly
183
+ without expensive per-row type checks.
184
+
185
+ Keeping in mind that pysqlite's parsing option is not recommended,
186
+ nor should be necessary, for use with SQLAlchemy, usage of PARSE_DECLTYPES
187
+ can be forced if one configures "native_datetime=True" on create_engine()::
188
+
189
+ engine = create_engine('sqlite://',
190
+ connect_args={'detect_types':
191
+ sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES},
192
+ native_datetime=True
193
+ )
194
+
195
+ With this flag enabled, the DATE and TIMESTAMP types (but note - not the
196
+ DATETIME or TIME types...confused yet ?) will not perform any bind parameter
197
+ or result processing. Execution of "func.current_date()" will return a string.
198
+ "func.current_timestamp()" is registered as returning a DATETIME type in
199
+ SQLAlchemy, so this function still receives SQLAlchemy-level result
200
+ processing.
201
+
202
+ .. _pysqlite_threading_pooling:
203
+
204
+ Threading/Pooling Behavior
205
+ ---------------------------
206
+
207
+ The ``sqlite3`` DBAPI by default prohibits the use of a particular connection
208
+ in a thread which is not the one in which it was created. As SQLite has
209
+ matured, it's behavior under multiple threads has improved, and even includes
210
+ options for memory only databases to be used in multiple threads.
211
+
212
+ The thread prohibition is known as "check same thread" and may be controlled
213
+ using the ``sqlite3`` parameter ``check_same_thread``, which will disable or
214
+ enable this check. SQLAlchemy's default behavior here is to set
215
+ ``check_same_thread`` to ``False`` automatically whenever a file-based database
216
+ is in use, to establish compatibility with the default pool class
217
+ :class:`.QueuePool`.
218
+
219
+ The SQLAlchemy ``pysqlite`` DBAPI establishes the connection pool differently
220
+ based on the kind of SQLite database that's requested:
221
+
222
+ * When a ``:memory:`` SQLite database is specified, the dialect by default
223
+ will use :class:`.SingletonThreadPool`. This pool maintains a single
224
+ connection per thread, so that all access to the engine within the current
225
+ thread use the same ``:memory:`` database - other threads would access a
226
+ different ``:memory:`` database. The ``check_same_thread`` parameter
227
+ defaults to ``True``.
228
+ * When a file-based database is specified, the dialect will use
229
+ :class:`.QueuePool` as the source of connections. at the same time,
230
+ the ``check_same_thread`` flag is set to False by default unless overridden.
231
+
232
+ .. versionchanged:: 2.0
233
+
234
+ SQLite file database engines now use :class:`.QueuePool` by default.
235
+ Previously, :class:`.NullPool` were used. The :class:`.NullPool` class
236
+ may be used by specifying it via the
237
+ :paramref:`_sa.create_engine.poolclass` parameter.
238
+
239
+ Disabling Connection Pooling for File Databases
240
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
241
+
242
+ Pooling may be disabled for a file based database by specifying the
243
+ :class:`.NullPool` implementation for the :func:`_sa.create_engine.poolclass`
244
+ parameter::
245
+
246
+ from sqlalchemy import NullPool
247
+ engine = create_engine("sqlite:///myfile.db", poolclass=NullPool)
248
+
249
+ It's been observed that the :class:`.NullPool` implementation incurs an
250
+ extremely small performance overhead for repeated checkouts due to the lack of
251
+ connection re-use implemented by :class:`.QueuePool`. However, it still
252
+ may be beneficial to use this class if the application is experiencing
253
+ issues with files being locked.
254
+
255
+ Using a Memory Database in Multiple Threads
256
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
257
+
258
+ To use a ``:memory:`` database in a multithreaded scenario, the same
259
+ connection object must be shared among threads, since the database exists
260
+ only within the scope of that connection. The
261
+ :class:`.StaticPool` implementation will maintain a single connection
262
+ globally, and the ``check_same_thread`` flag can be passed to Pysqlite
263
+ as ``False``::
264
+
265
+ from sqlalchemy.pool import StaticPool
266
+ engine = create_engine('sqlite://',
267
+ connect_args={'check_same_thread':False},
268
+ poolclass=StaticPool)
269
+
270
+ Note that using a ``:memory:`` database in multiple threads requires a recent
271
+ version of SQLite.
272
+
273
+ Using Temporary Tables with SQLite
274
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
275
+
276
+ Due to the way SQLite deals with temporary tables, if you wish to use a
277
+ temporary table in a file-based SQLite database across multiple checkouts
278
+ from the connection pool, such as when using an ORM :class:`.Session` where
279
+ the temporary table should continue to remain after :meth:`.Session.commit` or
280
+ :meth:`.Session.rollback` is called, a pool which maintains a single
281
+ connection must be used. Use :class:`.SingletonThreadPool` if the scope is
282
+ only needed within the current thread, or :class:`.StaticPool` is scope is
283
+ needed within multiple threads for this case::
284
+
285
+ # maintain the same connection per thread
286
+ from sqlalchemy.pool import SingletonThreadPool
287
+ engine = create_engine('sqlite:///mydb.db',
288
+ poolclass=SingletonThreadPool)
289
+
290
+
291
+ # maintain the same connection across all threads
292
+ from sqlalchemy.pool import StaticPool
293
+ engine = create_engine('sqlite:///mydb.db',
294
+ poolclass=StaticPool)
295
+
296
+ Note that :class:`.SingletonThreadPool` should be configured for the number
297
+ of threads that are to be used; beyond that number, connections will be
298
+ closed out in a non deterministic way.
299
+
300
+
301
+ Dealing with Mixed String / Binary Columns
302
+ ------------------------------------------------------
303
+
304
+ The SQLite database is weakly typed, and as such it is possible when using
305
+ binary values, which in Python are represented as ``b'some string'``, that a
306
+ particular SQLite database can have data values within different rows where
307
+ some of them will be returned as a ``b''`` value by the Pysqlite driver, and
308
+ others will be returned as Python strings, e.g. ``''`` values. This situation
309
+ is not known to occur if the SQLAlchemy :class:`.LargeBinary` datatype is used
310
+ consistently, however if a particular SQLite database has data that was
311
+ inserted using the Pysqlite driver directly, or when using the SQLAlchemy
312
+ :class:`.String` type which was later changed to :class:`.LargeBinary`, the
313
+ table will not be consistently readable because SQLAlchemy's
314
+ :class:`.LargeBinary` datatype does not handle strings so it has no way of
315
+ "encoding" a value that is in string format.
316
+
317
+ To deal with a SQLite table that has mixed string / binary data in the
318
+ same column, use a custom type that will check each row individually::
319
+
320
+ from sqlalchemy import String
321
+ from sqlalchemy import TypeDecorator
322
+
323
+ class MixedBinary(TypeDecorator):
324
+ impl = String
325
+ cache_ok = True
326
+
327
+ def process_result_value(self, value, dialect):
328
+ if isinstance(value, str):
329
+ value = bytes(value, 'utf-8')
330
+ elif value is not None:
331
+ value = bytes(value)
332
+
333
+ return value
334
+
335
+ Then use the above ``MixedBinary`` datatype in the place where
336
+ :class:`.LargeBinary` would normally be used.
337
+
338
+ .. _pysqlite_serializable:
339
+
340
+ Serializable isolation / Savepoints / Transactional DDL
341
+ -------------------------------------------------------
342
+
343
+ In the section :ref:`sqlite_concurrency`, we refer to the pysqlite
344
+ driver's assortment of issues that prevent several features of SQLite
345
+ from working correctly. The pysqlite DBAPI driver has several
346
+ long-standing bugs which impact the correctness of its transactional
347
+ behavior. In its default mode of operation, SQLite features such as
348
+ SERIALIZABLE isolation, transactional DDL, and SAVEPOINT support are
349
+ non-functional, and in order to use these features, workarounds must
350
+ be taken.
351
+
352
+ The issue is essentially that the driver attempts to second-guess the user's
353
+ intent, failing to start transactions and sometimes ending them prematurely, in
354
+ an effort to minimize the SQLite databases's file locking behavior, even
355
+ though SQLite itself uses "shared" locks for read-only activities.
356
+
357
+ SQLAlchemy chooses to not alter this behavior by default, as it is the
358
+ long-expected behavior of the pysqlite driver; if and when the pysqlite
359
+ driver attempts to repair these issues, that will be more of a driver towards
360
+ defaults for SQLAlchemy.
361
+
362
+ The good news is that with a few events, we can implement transactional
363
+ support fully, by disabling pysqlite's feature entirely and emitting BEGIN
364
+ ourselves. This is achieved using two event listeners::
365
+
366
+ from sqlalchemy import create_engine, event
367
+
368
+ engine = create_engine("sqlite:///myfile.db")
369
+
370
+ @event.listens_for(engine, "connect")
371
+ def do_connect(dbapi_connection, connection_record):
372
+ # disable pysqlite's emitting of the BEGIN statement entirely.
373
+ # also stops it from emitting COMMIT before any DDL.
374
+ dbapi_connection.isolation_level = None
375
+
376
+ @event.listens_for(engine, "begin")
377
+ def do_begin(conn):
378
+ # emit our own BEGIN
379
+ conn.exec_driver_sql("BEGIN")
380
+
381
+ .. warning:: When using the above recipe, it is advised to not use the
382
+ :paramref:`.Connection.execution_options.isolation_level` setting on
383
+ :class:`_engine.Connection` and :func:`_sa.create_engine`
384
+ with the SQLite driver,
385
+ as this function necessarily will also alter the ".isolation_level" setting.
386
+
387
+
388
+ Above, we intercept a new pysqlite connection and disable any transactional
389
+ integration. Then, at the point at which SQLAlchemy knows that transaction
390
+ scope is to begin, we emit ``"BEGIN"`` ourselves.
391
+
392
+ When we take control of ``"BEGIN"``, we can also control directly SQLite's
393
+ locking modes, introduced at
394
+ `BEGIN TRANSACTION <https://sqlite.org/lang_transaction.html>`_,
395
+ by adding the desired locking mode to our ``"BEGIN"``::
396
+
397
+ @event.listens_for(engine, "begin")
398
+ def do_begin(conn):
399
+ conn.exec_driver_sql("BEGIN EXCLUSIVE")
400
+
401
+ .. seealso::
402
+
403
+ `BEGIN TRANSACTION <https://sqlite.org/lang_transaction.html>`_ -
404
+ on the SQLite site
405
+
406
+ `sqlite3 SELECT does not BEGIN a transaction <https://bugs.python.org/issue9924>`_ -
407
+ on the Python bug tracker
408
+
409
+ `sqlite3 module breaks transactions and potentially corrupts data <https://bugs.python.org/issue10740>`_ -
410
+ on the Python bug tracker
411
+
412
+ .. _pysqlite_udfs:
413
+
414
+ User-Defined Functions
415
+ ----------------------
416
+
417
+ pysqlite supports a `create_function() <https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.create_function>`_
418
+ method that allows us to create our own user-defined functions (UDFs) in Python and use them directly in SQLite queries.
419
+ These functions are registered with a specific DBAPI Connection.
420
+
421
+ SQLAlchemy uses connection pooling with file-based SQLite databases, so we need to ensure that the UDF is attached to the
422
+ connection when it is created. That is accomplished with an event listener::
423
+
424
+ from sqlalchemy import create_engine
425
+ from sqlalchemy import event
426
+ from sqlalchemy import text
427
+
428
+
429
+ def udf():
430
+ return "udf-ok"
431
+
432
+
433
+ engine = create_engine("sqlite:///./db_file")
434
+
435
+
436
+ @event.listens_for(engine, "connect")
437
+ def connect(conn, rec):
438
+ conn.create_function("udf", 0, udf)
439
+
440
+
441
+ for i in range(5):
442
+ with engine.connect() as conn:
443
+ print(conn.scalar(text("SELECT UDF()")))
444
+
445
+
446
+ """ # noqa
447
+
448
+ import math
449
+ import os
450
+ import re
451
+
452
+ from .base import DATE
453
+ from .base import DATETIME
454
+ from .base import SQLiteDialect
455
+ from ... import exc
456
+ from ... import pool
457
+ from ... import types as sqltypes
458
+ from ... import util
459
+
460
+
461
+ class _SQLite_pysqliteTimeStamp(DATETIME):
462
+ def bind_processor(self, dialect):
463
+ if dialect.native_datetime:
464
+ return None
465
+ else:
466
+ return DATETIME.bind_processor(self, dialect)
467
+
468
+ def result_processor(self, dialect, coltype):
469
+ if dialect.native_datetime:
470
+ return None
471
+ else:
472
+ return DATETIME.result_processor(self, dialect, coltype)
473
+
474
+
475
+ class _SQLite_pysqliteDate(DATE):
476
+ def bind_processor(self, dialect):
477
+ if dialect.native_datetime:
478
+ return None
479
+ else:
480
+ return DATE.bind_processor(self, dialect)
481
+
482
+ def result_processor(self, dialect, coltype):
483
+ if dialect.native_datetime:
484
+ return None
485
+ else:
486
+ return DATE.result_processor(self, dialect, coltype)
487
+
488
+
489
+ class SQLiteDialect_pysqlite(SQLiteDialect):
490
+ default_paramstyle = "qmark"
491
+ supports_statement_cache = True
492
+ returns_native_bytes = True
493
+
494
+ colspecs = util.update_copy(
495
+ SQLiteDialect.colspecs,
496
+ {
497
+ sqltypes.Date: _SQLite_pysqliteDate,
498
+ sqltypes.TIMESTAMP: _SQLite_pysqliteTimeStamp,
499
+ },
500
+ )
501
+
502
+ description_encoding = None
503
+
504
+ driver = "pysqlite"
505
+
506
+ @classmethod
507
+ def import_dbapi(cls):
508
+ from sqlite3 import dbapi2 as sqlite
509
+
510
+ return sqlite
511
+
512
+ @classmethod
513
+ def _is_url_file_db(cls, url):
514
+ if (url.database and url.database != ":memory:") and (
515
+ url.query.get("mode", None) != "memory"
516
+ ):
517
+ return True
518
+ else:
519
+ return False
520
+
521
+ @classmethod
522
+ def get_pool_class(cls, url):
523
+ if cls._is_url_file_db(url):
524
+ return pool.QueuePool
525
+ else:
526
+ return pool.SingletonThreadPool
527
+
528
+ def _get_server_version_info(self, connection):
529
+ return self.dbapi.sqlite_version_info
530
+
531
+ _isolation_lookup = SQLiteDialect._isolation_lookup.union(
532
+ {
533
+ "AUTOCOMMIT": None,
534
+ }
535
+ )
536
+
537
+ def set_isolation_level(self, dbapi_connection, level):
538
+ if level == "AUTOCOMMIT":
539
+ dbapi_connection.isolation_level = None
540
+ else:
541
+ dbapi_connection.isolation_level = ""
542
+ return super().set_isolation_level(dbapi_connection, level)
543
+
544
+ def on_connect(self):
545
+ def regexp(a, b):
546
+ if b is None:
547
+ return None
548
+ return re.search(a, b) is not None
549
+
550
+ if util.py38 and self._get_server_version_info(None) >= (3, 9):
551
+ # sqlite must be greater than 3.8.3 for deterministic=True
552
+ # https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.create_function
553
+ # the check is more conservative since there were still issues
554
+ # with following 3.8 sqlite versions
555
+ create_func_kw = {"deterministic": True}
556
+ else:
557
+ create_func_kw = {}
558
+
559
+ def set_regexp(dbapi_connection):
560
+ dbapi_connection.create_function(
561
+ "regexp", 2, regexp, **create_func_kw
562
+ )
563
+
564
+ def floor_func(dbapi_connection):
565
+ # NOTE: floor is optionally present in sqlite 3.35+ , however
566
+ # as it is normally non-present we deliver floor() unconditionally
567
+ # for now.
568
+ # https://www.sqlite.org/lang_mathfunc.html
569
+ dbapi_connection.create_function(
570
+ "floor", 1, math.floor, **create_func_kw
571
+ )
572
+
573
+ fns = [set_regexp, floor_func]
574
+
575
+ def connect(conn):
576
+ for fn in fns:
577
+ fn(conn)
578
+
579
+ return connect
580
+
581
+ def create_connect_args(self, url):
582
+ if url.username or url.password or url.host or url.port:
583
+ raise exc.ArgumentError(
584
+ "Invalid SQLite URL: %s\n"
585
+ "Valid SQLite URL forms are:\n"
586
+ " sqlite:///:memory: (or, sqlite://)\n"
587
+ " sqlite:///relative/path/to/file.db\n"
588
+ " sqlite:////absolute/path/to/file.db" % (url,)
589
+ )
590
+
591
+ # theoretically, this list can be augmented, at least as far as
592
+ # parameter names accepted by sqlite3/pysqlite, using
593
+ # inspect.getfullargspec(). for the moment this seems like overkill
594
+ # as these parameters don't change very often, and as always,
595
+ # parameters passed to connect_args will always go to the
596
+ # sqlite3/pysqlite driver.
597
+ pysqlite_args = [
598
+ ("uri", bool),
599
+ ("timeout", float),
600
+ ("isolation_level", str),
601
+ ("detect_types", int),
602
+ ("check_same_thread", bool),
603
+ ("cached_statements", int),
604
+ ]
605
+ opts = url.query
606
+ pysqlite_opts = {}
607
+ for key, type_ in pysqlite_args:
608
+ util.coerce_kw_type(opts, key, type_, dest=pysqlite_opts)
609
+
610
+ if pysqlite_opts.get("uri", False):
611
+ uri_opts = dict(opts)
612
+ # here, we are actually separating the parameters that go to
613
+ # sqlite3/pysqlite vs. those that go the SQLite URI. What if
614
+ # two names conflict? again, this seems to be not the case right
615
+ # now, and in the case that new names are added to
616
+ # either side which overlap, again the sqlite3/pysqlite parameters
617
+ # can be passed through connect_args instead of in the URL.
618
+ # If SQLite native URIs add a parameter like "timeout" that
619
+ # we already have listed here for the python driver, then we need
620
+ # to adjust for that here.
621
+ for key, type_ in pysqlite_args:
622
+ uri_opts.pop(key, None)
623
+ filename = url.database
624
+ if uri_opts:
625
+ # sorting of keys is for unit test support
626
+ filename += "?" + (
627
+ "&".join(
628
+ "%s=%s" % (key, uri_opts[key])
629
+ for key in sorted(uri_opts)
630
+ )
631
+ )
632
+ else:
633
+ filename = url.database or ":memory:"
634
+ if filename != ":memory:":
635
+ filename = os.path.abspath(filename)
636
+
637
+ pysqlite_opts.setdefault(
638
+ "check_same_thread", not self._is_url_file_db(url)
639
+ )
640
+
641
+ return ([filename], pysqlite_opts)
642
+
643
+ def is_disconnect(self, e, connection, cursor):
644
+ return isinstance(
645
+ e, self.dbapi.ProgrammingError
646
+ ) and "Cannot operate on a closed database." in str(e)
647
+
648
+
649
+ dialect = SQLiteDialect_pysqlite
650
+
651
+
652
+ class _SQLiteDialect_pysqlite_numeric(SQLiteDialect_pysqlite):
653
+ """numeric dialect for testing only
654
+
655
+ internal use only. This dialect is **NOT** supported by SQLAlchemy
656
+ and may change at any time.
657
+
658
+ """
659
+
660
+ supports_statement_cache = True
661
+ default_paramstyle = "numeric"
662
+ driver = "pysqlite_numeric"
663
+
664
+ _first_bind = ":1"
665
+ _not_in_statement_regexp = None
666
+
667
+ def __init__(self, *arg, **kw):
668
+ kw.setdefault("paramstyle", "numeric")
669
+ super().__init__(*arg, **kw)
670
+
671
+ def create_connect_args(self, url):
672
+ arg, opts = super().create_connect_args(url)
673
+ opts["factory"] = self._fix_sqlite_issue_99953()
674
+ return arg, opts
675
+
676
+ def _fix_sqlite_issue_99953(self):
677
+ import sqlite3
678
+
679
+ first_bind = self._first_bind
680
+ if self._not_in_statement_regexp:
681
+ nis = self._not_in_statement_regexp
682
+
683
+ def _test_sql(sql):
684
+ m = nis.search(sql)
685
+ assert not m, f"Found {nis.pattern!r} in {sql!r}"
686
+
687
+ else:
688
+
689
+ def _test_sql(sql):
690
+ pass
691
+
692
+ def _numeric_param_as_dict(parameters):
693
+ if parameters:
694
+ assert isinstance(parameters, tuple)
695
+ return {
696
+ str(idx): value for idx, value in enumerate(parameters, 1)
697
+ }
698
+ else:
699
+ return ()
700
+
701
+ class SQLiteFix99953Cursor(sqlite3.Cursor):
702
+ def execute(self, sql, parameters=()):
703
+ _test_sql(sql)
704
+ if first_bind in sql:
705
+ parameters = _numeric_param_as_dict(parameters)
706
+ return super().execute(sql, parameters)
707
+
708
+ def executemany(self, sql, parameters):
709
+ _test_sql(sql)
710
+ if first_bind in sql:
711
+ parameters = [
712
+ _numeric_param_as_dict(p) for p in parameters
713
+ ]
714
+ return super().executemany(sql, parameters)
715
+
716
+ class SQLiteFix99953Connection(sqlite3.Connection):
717
+ def cursor(self, factory=None):
718
+ if factory is None:
719
+ factory = SQLiteFix99953Cursor
720
+ return super().cursor(factory=factory)
721
+
722
+ def execute(self, sql, parameters=()):
723
+ _test_sql(sql)
724
+ if first_bind in sql:
725
+ parameters = _numeric_param_as_dict(parameters)
726
+ return super().execute(sql, parameters)
727
+
728
+ def executemany(self, sql, parameters):
729
+ _test_sql(sql)
730
+ if first_bind in sql:
731
+ parameters = [
732
+ _numeric_param_as_dict(p) for p in parameters
733
+ ]
734
+ return super().executemany(sql, parameters)
735
+
736
+ return SQLiteFix99953Connection
737
+
738
+
739
+ class _SQLiteDialect_pysqlite_dollar(_SQLiteDialect_pysqlite_numeric):
740
+ """numeric dialect that uses $ for testing only
741
+
742
+ internal use only. This dialect is **NOT** supported by SQLAlchemy
743
+ and may change at any time.
744
+
745
+ """
746
+
747
+ supports_statement_cache = True
748
+ default_paramstyle = "numeric_dollar"
749
+ driver = "pysqlite_dollar"
750
+
751
+ _first_bind = "$1"
752
+ _not_in_statement_regexp = re.compile(r"[^\d]:\d+")
753
+
754
+ def __init__(self, *arg, **kw):
755
+ kw.setdefault("paramstyle", "numeric_dollar")
756
+ super().__init__(*arg, **kw)