SQLAlchemy 2.0.47__cp313-cp313t-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. sqlalchemy/__init__.py +283 -0
  2. sqlalchemy/connectors/__init__.py +18 -0
  3. sqlalchemy/connectors/aioodbc.py +184 -0
  4. sqlalchemy/connectors/asyncio.py +429 -0
  5. sqlalchemy/connectors/pyodbc.py +250 -0
  6. sqlalchemy/cyextension/__init__.py +6 -0
  7. sqlalchemy/cyextension/collections.cp313t-win_amd64.pyd +0 -0
  8. sqlalchemy/cyextension/collections.pyx +409 -0
  9. sqlalchemy/cyextension/immutabledict.cp313t-win_amd64.pyd +0 -0
  10. sqlalchemy/cyextension/immutabledict.pxd +8 -0
  11. sqlalchemy/cyextension/immutabledict.pyx +133 -0
  12. sqlalchemy/cyextension/processors.cp313t-win_amd64.pyd +0 -0
  13. sqlalchemy/cyextension/processors.pyx +68 -0
  14. sqlalchemy/cyextension/resultproxy.cp313t-win_amd64.pyd +0 -0
  15. sqlalchemy/cyextension/resultproxy.pyx +102 -0
  16. sqlalchemy/cyextension/util.cp313t-win_amd64.pyd +0 -0
  17. sqlalchemy/cyextension/util.pyx +90 -0
  18. sqlalchemy/dialects/__init__.py +62 -0
  19. sqlalchemy/dialects/_typing.py +30 -0
  20. sqlalchemy/dialects/mssql/__init__.py +88 -0
  21. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  22. sqlalchemy/dialects/mssql/base.py +4093 -0
  23. sqlalchemy/dialects/mssql/information_schema.py +285 -0
  24. sqlalchemy/dialects/mssql/json.py +129 -0
  25. sqlalchemy/dialects/mssql/provision.py +185 -0
  26. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  27. sqlalchemy/dialects/mssql/pyodbc.py +760 -0
  28. sqlalchemy/dialects/mysql/__init__.py +104 -0
  29. sqlalchemy/dialects/mysql/aiomysql.py +250 -0
  30. sqlalchemy/dialects/mysql/asyncmy.py +231 -0
  31. sqlalchemy/dialects/mysql/base.py +3949 -0
  32. sqlalchemy/dialects/mysql/cymysql.py +106 -0
  33. sqlalchemy/dialects/mysql/dml.py +225 -0
  34. sqlalchemy/dialects/mysql/enumerated.py +282 -0
  35. sqlalchemy/dialects/mysql/expression.py +146 -0
  36. sqlalchemy/dialects/mysql/json.py +91 -0
  37. sqlalchemy/dialects/mysql/mariadb.py +72 -0
  38. sqlalchemy/dialects/mysql/mariadbconnector.py +322 -0
  39. sqlalchemy/dialects/mysql/mysqlconnector.py +302 -0
  40. sqlalchemy/dialects/mysql/mysqldb.py +314 -0
  41. sqlalchemy/dialects/mysql/provision.py +153 -0
  42. sqlalchemy/dialects/mysql/pymysql.py +158 -0
  43. sqlalchemy/dialects/mysql/pyodbc.py +157 -0
  44. sqlalchemy/dialects/mysql/reflection.py +727 -0
  45. sqlalchemy/dialects/mysql/reserved_words.py +570 -0
  46. sqlalchemy/dialects/mysql/types.py +835 -0
  47. sqlalchemy/dialects/oracle/__init__.py +81 -0
  48. sqlalchemy/dialects/oracle/base.py +3802 -0
  49. sqlalchemy/dialects/oracle/cx_oracle.py +1555 -0
  50. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  51. sqlalchemy/dialects/oracle/oracledb.py +941 -0
  52. sqlalchemy/dialects/oracle/provision.py +297 -0
  53. sqlalchemy/dialects/oracle/types.py +316 -0
  54. sqlalchemy/dialects/oracle/vector.py +365 -0
  55. sqlalchemy/dialects/postgresql/__init__.py +167 -0
  56. sqlalchemy/dialects/postgresql/_psycopg_common.py +189 -0
  57. sqlalchemy/dialects/postgresql/array.py +519 -0
  58. sqlalchemy/dialects/postgresql/asyncpg.py +1284 -0
  59. sqlalchemy/dialects/postgresql/base.py +5378 -0
  60. sqlalchemy/dialects/postgresql/dml.py +339 -0
  61. sqlalchemy/dialects/postgresql/ext.py +540 -0
  62. sqlalchemy/dialects/postgresql/hstore.py +406 -0
  63. sqlalchemy/dialects/postgresql/json.py +404 -0
  64. sqlalchemy/dialects/postgresql/named_types.py +524 -0
  65. sqlalchemy/dialects/postgresql/operators.py +129 -0
  66. sqlalchemy/dialects/postgresql/pg8000.py +669 -0
  67. sqlalchemy/dialects/postgresql/pg_catalog.py +326 -0
  68. sqlalchemy/dialects/postgresql/provision.py +183 -0
  69. sqlalchemy/dialects/postgresql/psycopg.py +862 -0
  70. sqlalchemy/dialects/postgresql/psycopg2.py +892 -0
  71. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  72. sqlalchemy/dialects/postgresql/ranges.py +1031 -0
  73. sqlalchemy/dialects/postgresql/types.py +313 -0
  74. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  75. sqlalchemy/dialects/sqlite/aiosqlite.py +482 -0
  76. sqlalchemy/dialects/sqlite/base.py +3056 -0
  77. sqlalchemy/dialects/sqlite/dml.py +263 -0
  78. sqlalchemy/dialects/sqlite/json.py +92 -0
  79. sqlalchemy/dialects/sqlite/provision.py +229 -0
  80. sqlalchemy/dialects/sqlite/pysqlcipher.py +157 -0
  81. sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
  82. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  83. sqlalchemy/engine/__init__.py +62 -0
  84. sqlalchemy/engine/_py_processors.py +136 -0
  85. sqlalchemy/engine/_py_row.py +128 -0
  86. sqlalchemy/engine/_py_util.py +74 -0
  87. sqlalchemy/engine/base.py +3390 -0
  88. sqlalchemy/engine/characteristics.py +155 -0
  89. sqlalchemy/engine/create.py +893 -0
  90. sqlalchemy/engine/cursor.py +2298 -0
  91. sqlalchemy/engine/default.py +2394 -0
  92. sqlalchemy/engine/events.py +965 -0
  93. sqlalchemy/engine/interfaces.py +3471 -0
  94. sqlalchemy/engine/mock.py +134 -0
  95. sqlalchemy/engine/processors.py +61 -0
  96. sqlalchemy/engine/reflection.py +2102 -0
  97. sqlalchemy/engine/result.py +2399 -0
  98. sqlalchemy/engine/row.py +400 -0
  99. sqlalchemy/engine/strategies.py +16 -0
  100. sqlalchemy/engine/url.py +924 -0
  101. sqlalchemy/engine/util.py +167 -0
  102. sqlalchemy/event/__init__.py +26 -0
  103. sqlalchemy/event/api.py +220 -0
  104. sqlalchemy/event/attr.py +676 -0
  105. sqlalchemy/event/base.py +472 -0
  106. sqlalchemy/event/legacy.py +258 -0
  107. sqlalchemy/event/registry.py +390 -0
  108. sqlalchemy/events.py +17 -0
  109. sqlalchemy/exc.py +832 -0
  110. sqlalchemy/ext/__init__.py +11 -0
  111. sqlalchemy/ext/associationproxy.py +2027 -0
  112. sqlalchemy/ext/asyncio/__init__.py +25 -0
  113. sqlalchemy/ext/asyncio/base.py +281 -0
  114. sqlalchemy/ext/asyncio/engine.py +1471 -0
  115. sqlalchemy/ext/asyncio/exc.py +21 -0
  116. sqlalchemy/ext/asyncio/result.py +965 -0
  117. sqlalchemy/ext/asyncio/scoping.py +1599 -0
  118. sqlalchemy/ext/asyncio/session.py +1947 -0
  119. sqlalchemy/ext/automap.py +1701 -0
  120. sqlalchemy/ext/baked.py +570 -0
  121. sqlalchemy/ext/compiler.py +600 -0
  122. sqlalchemy/ext/declarative/__init__.py +65 -0
  123. sqlalchemy/ext/declarative/extensions.py +564 -0
  124. sqlalchemy/ext/horizontal_shard.py +478 -0
  125. sqlalchemy/ext/hybrid.py +1535 -0
  126. sqlalchemy/ext/indexable.py +364 -0
  127. sqlalchemy/ext/instrumentation.py +450 -0
  128. sqlalchemy/ext/mutable.py +1085 -0
  129. sqlalchemy/ext/mypy/__init__.py +6 -0
  130. sqlalchemy/ext/mypy/apply.py +324 -0
  131. sqlalchemy/ext/mypy/decl_class.py +515 -0
  132. sqlalchemy/ext/mypy/infer.py +590 -0
  133. sqlalchemy/ext/mypy/names.py +335 -0
  134. sqlalchemy/ext/mypy/plugin.py +303 -0
  135. sqlalchemy/ext/mypy/util.py +357 -0
  136. sqlalchemy/ext/orderinglist.py +439 -0
  137. sqlalchemy/ext/serializer.py +185 -0
  138. sqlalchemy/future/__init__.py +16 -0
  139. sqlalchemy/future/engine.py +15 -0
  140. sqlalchemy/inspection.py +174 -0
  141. sqlalchemy/log.py +288 -0
  142. sqlalchemy/orm/__init__.py +171 -0
  143. sqlalchemy/orm/_orm_constructors.py +2661 -0
  144. sqlalchemy/orm/_typing.py +179 -0
  145. sqlalchemy/orm/attributes.py +2845 -0
  146. sqlalchemy/orm/base.py +971 -0
  147. sqlalchemy/orm/bulk_persistence.py +2135 -0
  148. sqlalchemy/orm/clsregistry.py +571 -0
  149. sqlalchemy/orm/collections.py +1627 -0
  150. sqlalchemy/orm/context.py +3334 -0
  151. sqlalchemy/orm/decl_api.py +2004 -0
  152. sqlalchemy/orm/decl_base.py +2192 -0
  153. sqlalchemy/orm/dependency.py +1302 -0
  154. sqlalchemy/orm/descriptor_props.py +1092 -0
  155. sqlalchemy/orm/dynamic.py +300 -0
  156. sqlalchemy/orm/evaluator.py +379 -0
  157. sqlalchemy/orm/events.py +3252 -0
  158. sqlalchemy/orm/exc.py +237 -0
  159. sqlalchemy/orm/identity.py +302 -0
  160. sqlalchemy/orm/instrumentation.py +754 -0
  161. sqlalchemy/orm/interfaces.py +1496 -0
  162. sqlalchemy/orm/loading.py +1686 -0
  163. sqlalchemy/orm/mapped_collection.py +557 -0
  164. sqlalchemy/orm/mapper.py +4444 -0
  165. sqlalchemy/orm/path_registry.py +809 -0
  166. sqlalchemy/orm/persistence.py +1788 -0
  167. sqlalchemy/orm/properties.py +935 -0
  168. sqlalchemy/orm/query.py +3459 -0
  169. sqlalchemy/orm/relationships.py +3508 -0
  170. sqlalchemy/orm/scoping.py +2148 -0
  171. sqlalchemy/orm/session.py +5280 -0
  172. sqlalchemy/orm/state.py +1168 -0
  173. sqlalchemy/orm/state_changes.py +196 -0
  174. sqlalchemy/orm/strategies.py +3470 -0
  175. sqlalchemy/orm/strategy_options.py +2568 -0
  176. sqlalchemy/orm/sync.py +164 -0
  177. sqlalchemy/orm/unitofwork.py +796 -0
  178. sqlalchemy/orm/util.py +2403 -0
  179. sqlalchemy/orm/writeonly.py +674 -0
  180. sqlalchemy/pool/__init__.py +44 -0
  181. sqlalchemy/pool/base.py +1524 -0
  182. sqlalchemy/pool/events.py +375 -0
  183. sqlalchemy/pool/impl.py +588 -0
  184. sqlalchemy/py.typed +0 -0
  185. sqlalchemy/schema.py +69 -0
  186. sqlalchemy/sql/__init__.py +145 -0
  187. sqlalchemy/sql/_dml_constructors.py +132 -0
  188. sqlalchemy/sql/_elements_constructors.py +1872 -0
  189. sqlalchemy/sql/_orm_types.py +20 -0
  190. sqlalchemy/sql/_py_util.py +75 -0
  191. sqlalchemy/sql/_selectable_constructors.py +763 -0
  192. sqlalchemy/sql/_typing.py +482 -0
  193. sqlalchemy/sql/annotation.py +587 -0
  194. sqlalchemy/sql/base.py +2293 -0
  195. sqlalchemy/sql/cache_key.py +1057 -0
  196. sqlalchemy/sql/coercions.py +1404 -0
  197. sqlalchemy/sql/compiler.py +8081 -0
  198. sqlalchemy/sql/crud.py +1752 -0
  199. sqlalchemy/sql/ddl.py +1444 -0
  200. sqlalchemy/sql/default_comparator.py +551 -0
  201. sqlalchemy/sql/dml.py +1850 -0
  202. sqlalchemy/sql/elements.py +5589 -0
  203. sqlalchemy/sql/events.py +458 -0
  204. sqlalchemy/sql/expression.py +159 -0
  205. sqlalchemy/sql/functions.py +2158 -0
  206. sqlalchemy/sql/lambdas.py +1442 -0
  207. sqlalchemy/sql/naming.py +209 -0
  208. sqlalchemy/sql/operators.py +2623 -0
  209. sqlalchemy/sql/roles.py +323 -0
  210. sqlalchemy/sql/schema.py +6222 -0
  211. sqlalchemy/sql/selectable.py +7265 -0
  212. sqlalchemy/sql/sqltypes.py +3930 -0
  213. sqlalchemy/sql/traversals.py +1024 -0
  214. sqlalchemy/sql/type_api.py +2368 -0
  215. sqlalchemy/sql/util.py +1485 -0
  216. sqlalchemy/sql/visitors.py +1164 -0
  217. sqlalchemy/testing/__init__.py +96 -0
  218. sqlalchemy/testing/assertions.py +994 -0
  219. sqlalchemy/testing/assertsql.py +520 -0
  220. sqlalchemy/testing/asyncio.py +135 -0
  221. sqlalchemy/testing/config.py +434 -0
  222. sqlalchemy/testing/engines.py +483 -0
  223. sqlalchemy/testing/entities.py +117 -0
  224. sqlalchemy/testing/exclusions.py +476 -0
  225. sqlalchemy/testing/fixtures/__init__.py +28 -0
  226. sqlalchemy/testing/fixtures/base.py +384 -0
  227. sqlalchemy/testing/fixtures/mypy.py +332 -0
  228. sqlalchemy/testing/fixtures/orm.py +227 -0
  229. sqlalchemy/testing/fixtures/sql.py +482 -0
  230. sqlalchemy/testing/pickleable.py +155 -0
  231. sqlalchemy/testing/plugin/__init__.py +6 -0
  232. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  233. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  234. sqlalchemy/testing/plugin/pytestplugin.py +892 -0
  235. sqlalchemy/testing/profiling.py +329 -0
  236. sqlalchemy/testing/provision.py +603 -0
  237. sqlalchemy/testing/requirements.py +1945 -0
  238. sqlalchemy/testing/schema.py +198 -0
  239. sqlalchemy/testing/suite/__init__.py +19 -0
  240. sqlalchemy/testing/suite/test_cte.py +237 -0
  241. sqlalchemy/testing/suite/test_ddl.py +389 -0
  242. sqlalchemy/testing/suite/test_deprecations.py +153 -0
  243. sqlalchemy/testing/suite/test_dialect.py +776 -0
  244. sqlalchemy/testing/suite/test_insert.py +630 -0
  245. sqlalchemy/testing/suite/test_reflection.py +3557 -0
  246. sqlalchemy/testing/suite/test_results.py +504 -0
  247. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  248. sqlalchemy/testing/suite/test_select.py +2010 -0
  249. sqlalchemy/testing/suite/test_sequence.py +317 -0
  250. sqlalchemy/testing/suite/test_types.py +2147 -0
  251. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  252. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  253. sqlalchemy/testing/util.py +535 -0
  254. sqlalchemy/testing/warnings.py +52 -0
  255. sqlalchemy/types.py +74 -0
  256. sqlalchemy/util/__init__.py +162 -0
  257. sqlalchemy/util/_collections.py +712 -0
  258. sqlalchemy/util/_concurrency_py3k.py +288 -0
  259. sqlalchemy/util/_has_cy.py +40 -0
  260. sqlalchemy/util/_py_collections.py +541 -0
  261. sqlalchemy/util/compat.py +421 -0
  262. sqlalchemy/util/concurrency.py +110 -0
  263. sqlalchemy/util/deprecations.py +401 -0
  264. sqlalchemy/util/langhelpers.py +2203 -0
  265. sqlalchemy/util/preloaded.py +150 -0
  266. sqlalchemy/util/queue.py +322 -0
  267. sqlalchemy/util/tool_support.py +201 -0
  268. sqlalchemy/util/topological.py +120 -0
  269. sqlalchemy/util/typing.py +734 -0
  270. sqlalchemy-2.0.47.dist-info/METADATA +243 -0
  271. sqlalchemy-2.0.47.dist-info/RECORD +274 -0
  272. sqlalchemy-2.0.47.dist-info/WHEEL +5 -0
  273. sqlalchemy-2.0.47.dist-info/licenses/LICENSE +19 -0
  274. sqlalchemy-2.0.47.dist-info/top_level.txt +1 -0
@@ -0,0 +1,150 @@
1
+ # util/preloaded.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+ # mypy: allow-untyped-defs, allow-untyped-calls
8
+
9
+ """supplies the "preloaded" registry to resolve circular module imports at
10
+ runtime.
11
+
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import sys
16
+ from typing import Any
17
+ from typing import Callable
18
+ from typing import TYPE_CHECKING
19
+ from typing import TypeVar
20
+
21
+ _FN = TypeVar("_FN", bound=Callable[..., Any])
22
+
23
+
24
+ if TYPE_CHECKING:
25
+ from sqlalchemy import dialects as _dialects
26
+ from sqlalchemy import orm as _orm
27
+ from sqlalchemy.engine import cursor as _engine_cursor
28
+ from sqlalchemy.engine import default as _engine_default
29
+ from sqlalchemy.engine import reflection as _engine_reflection
30
+ from sqlalchemy.engine import result as _engine_result
31
+ from sqlalchemy.engine import url as _engine_url
32
+ from sqlalchemy.orm import attributes as _orm_attributes
33
+ from sqlalchemy.orm import base as _orm_base
34
+ from sqlalchemy.orm import clsregistry as _orm_clsregistry
35
+ from sqlalchemy.orm import decl_api as _orm_decl_api
36
+ from sqlalchemy.orm import decl_base as _orm_decl_base
37
+ from sqlalchemy.orm import dependency as _orm_dependency
38
+ from sqlalchemy.orm import descriptor_props as _orm_descriptor_props
39
+ from sqlalchemy.orm import mapperlib as _orm_mapper
40
+ from sqlalchemy.orm import properties as _orm_properties
41
+ from sqlalchemy.orm import relationships as _orm_relationships
42
+ from sqlalchemy.orm import session as _orm_session
43
+ from sqlalchemy.orm import state as _orm_state
44
+ from sqlalchemy.orm import strategies as _orm_strategies
45
+ from sqlalchemy.orm import strategy_options as _orm_strategy_options
46
+ from sqlalchemy.orm import util as _orm_util
47
+ from sqlalchemy.sql import default_comparator as _sql_default_comparator
48
+ from sqlalchemy.sql import dml as _sql_dml
49
+ from sqlalchemy.sql import elements as _sql_elements
50
+ from sqlalchemy.sql import functions as _sql_functions
51
+ from sqlalchemy.sql import naming as _sql_naming
52
+ from sqlalchemy.sql import schema as _sql_schema
53
+ from sqlalchemy.sql import selectable as _sql_selectable
54
+ from sqlalchemy.sql import sqltypes as _sql_sqltypes
55
+ from sqlalchemy.sql import traversals as _sql_traversals
56
+ from sqlalchemy.sql import util as _sql_util
57
+
58
+ # sigh, appease mypy 0.971 which does not accept imports as instance
59
+ # variables of a module
60
+ dialects = _dialects
61
+ engine_cursor = _engine_cursor
62
+ engine_default = _engine_default
63
+ engine_reflection = _engine_reflection
64
+ engine_result = _engine_result
65
+ engine_url = _engine_url
66
+ orm_clsregistry = _orm_clsregistry
67
+ orm_base = _orm_base
68
+ orm = _orm
69
+ orm_attributes = _orm_attributes
70
+ orm_decl_api = _orm_decl_api
71
+ orm_decl_base = _orm_decl_base
72
+ orm_descriptor_props = _orm_descriptor_props
73
+ orm_dependency = _orm_dependency
74
+ orm_mapper = _orm_mapper
75
+ orm_properties = _orm_properties
76
+ orm_relationships = _orm_relationships
77
+ orm_session = _orm_session
78
+ orm_strategies = _orm_strategies
79
+ orm_strategy_options = _orm_strategy_options
80
+ orm_state = _orm_state
81
+ orm_util = _orm_util
82
+ sql_default_comparator = _sql_default_comparator
83
+ sql_dml = _sql_dml
84
+ sql_elements = _sql_elements
85
+ sql_functions = _sql_functions
86
+ sql_naming = _sql_naming
87
+ sql_selectable = _sql_selectable
88
+ sql_traversals = _sql_traversals
89
+ sql_schema = _sql_schema
90
+ sql_sqltypes = _sql_sqltypes
91
+ sql_util = _sql_util
92
+
93
+
94
+ class _ModuleRegistry:
95
+ """Registry of modules to load in a package init file.
96
+
97
+ To avoid potential thread safety issues for imports that are deferred
98
+ in a function, like https://bugs.python.org/issue38884, these modules
99
+ are added to the system module cache by importing them after the packages
100
+ has finished initialization.
101
+
102
+ A global instance is provided under the name :attr:`.preloaded`. Use
103
+ the function :func:`.preload_module` to register modules to load and
104
+ :meth:`.import_prefix` to load all the modules that start with the
105
+ given path.
106
+
107
+ While the modules are loaded in the global module cache, it's advisable
108
+ to access them using :attr:`.preloaded` to ensure that it was actually
109
+ registered. Each registered module is added to the instance ``__dict__``
110
+ in the form `<package>_<module>`, omitting ``sqlalchemy`` from the package
111
+ name. Example: ``sqlalchemy.sql.util`` becomes ``preloaded.sql_util``.
112
+ """
113
+
114
+ def __init__(self, prefix="sqlalchemy."):
115
+ self.module_registry = set()
116
+ self.prefix = prefix
117
+
118
+ def preload_module(self, *deps: str) -> Callable[[_FN], _FN]:
119
+ """Adds the specified modules to the list to load.
120
+
121
+ This method can be used both as a normal function and as a decorator.
122
+ No change is performed to the decorated object.
123
+ """
124
+ self.module_registry.update(deps)
125
+ return lambda fn: fn
126
+
127
+ def import_prefix(self, path: str) -> None:
128
+ """Resolve all the modules in the registry that start with the
129
+ specified path.
130
+ """
131
+ for module in self.module_registry:
132
+ if self.prefix:
133
+ key = module.split(self.prefix)[-1].replace(".", "_")
134
+ else:
135
+ key = module
136
+ if (
137
+ not path or module.startswith(path)
138
+ ) and key not in self.__dict__:
139
+ __import__(module, globals(), locals())
140
+ self.__dict__[key] = globals()[key] = sys.modules[module]
141
+
142
+
143
+ _reg = _ModuleRegistry()
144
+ preload_module = _reg.preload_module
145
+ import_prefix = _reg.import_prefix
146
+
147
+ # this appears to do absolutely nothing for any version of mypy
148
+ # if TYPE_CHECKING:
149
+ # def __getattr__(key: str) -> ModuleType:
150
+ # ...
@@ -0,0 +1,322 @@
1
+ # util/queue.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+ # mypy: allow-untyped-defs, allow-untyped-calls
8
+
9
+ """An adaptation of Py2.3/2.4's Queue module which supports reentrant
10
+ behavior, using RLock instead of Lock for its mutex object. The
11
+ Queue object is used exclusively by the sqlalchemy.pool.QueuePool
12
+ class.
13
+
14
+ This is to support the connection pool's usage of weakref callbacks to return
15
+ connections to the underlying Queue, which can in extremely
16
+ rare cases be invoked within the ``get()`` method of the Queue itself,
17
+ producing a ``put()`` inside the ``get()`` and therefore a reentrant
18
+ condition.
19
+
20
+ """
21
+ from __future__ import annotations
22
+
23
+ import asyncio
24
+ from collections import deque
25
+ import threading
26
+ from time import time as _time
27
+ import typing
28
+ from typing import Any
29
+ from typing import Awaitable
30
+ from typing import Deque
31
+ from typing import Generic
32
+ from typing import Optional
33
+ from typing import TypeVar
34
+
35
+ from .concurrency import await_fallback
36
+ from .concurrency import await_only
37
+ from .langhelpers import memoized_property
38
+
39
+
40
+ _T = TypeVar("_T", bound=Any)
41
+ __all__ = ["Empty", "Full", "Queue"]
42
+
43
+
44
+ class Empty(Exception):
45
+ "Exception raised by Queue.get(block=0)/get_nowait()."
46
+
47
+ pass
48
+
49
+
50
+ class Full(Exception):
51
+ "Exception raised by Queue.put(block=0)/put_nowait()."
52
+
53
+ pass
54
+
55
+
56
+ class QueueCommon(Generic[_T]):
57
+ maxsize: int
58
+ use_lifo: bool
59
+
60
+ def __init__(self, maxsize: int = 0, use_lifo: bool = False): ...
61
+
62
+ def empty(self) -> bool:
63
+ raise NotImplementedError()
64
+
65
+ def full(self) -> bool:
66
+ raise NotImplementedError()
67
+
68
+ def qsize(self) -> int:
69
+ raise NotImplementedError()
70
+
71
+ def put_nowait(self, item: _T) -> None:
72
+ raise NotImplementedError()
73
+
74
+ def put(
75
+ self, item: _T, block: bool = True, timeout: Optional[float] = None
76
+ ) -> None:
77
+ raise NotImplementedError()
78
+
79
+ def get_nowait(self) -> _T:
80
+ raise NotImplementedError()
81
+
82
+ def get(self, block: bool = True, timeout: Optional[float] = None) -> _T:
83
+ raise NotImplementedError()
84
+
85
+
86
+ class Queue(QueueCommon[_T]):
87
+ queue: Deque[_T]
88
+
89
+ def __init__(self, maxsize: int = 0, use_lifo: bool = False):
90
+ """Initialize a queue object with a given maximum size.
91
+
92
+ If `maxsize` is <= 0, the queue size is infinite.
93
+
94
+ If `use_lifo` is True, this Queue acts like a Stack (LIFO).
95
+ """
96
+
97
+ self._init(maxsize)
98
+ # mutex must be held whenever the queue is mutating. All methods
99
+ # that acquire mutex must release it before returning. mutex
100
+ # is shared between the two conditions, so acquiring and
101
+ # releasing the conditions also acquires and releases mutex.
102
+ self.mutex = threading.RLock()
103
+ # Notify not_empty whenever an item is added to the queue; a
104
+ # thread waiting to get is notified then.
105
+ self.not_empty = threading.Condition(self.mutex)
106
+ # Notify not_full whenever an item is removed from the queue;
107
+ # a thread waiting to put is notified then.
108
+ self.not_full = threading.Condition(self.mutex)
109
+ # If this queue uses LIFO or FIFO
110
+ self.use_lifo = use_lifo
111
+
112
+ def qsize(self) -> int:
113
+ """Return the approximate size of the queue (not reliable!)."""
114
+
115
+ with self.mutex:
116
+ return self._qsize()
117
+
118
+ def empty(self) -> bool:
119
+ """Return True if the queue is empty, False otherwise (not
120
+ reliable!)."""
121
+
122
+ with self.mutex:
123
+ return self._empty()
124
+
125
+ def full(self) -> bool:
126
+ """Return True if the queue is full, False otherwise (not
127
+ reliable!)."""
128
+
129
+ with self.mutex:
130
+ return self._full()
131
+
132
+ def put(
133
+ self, item: _T, block: bool = True, timeout: Optional[float] = None
134
+ ) -> None:
135
+ """Put an item into the queue.
136
+
137
+ If optional args `block` is True and `timeout` is None (the
138
+ default), block if necessary until a free slot is
139
+ available. If `timeout` is a positive number, it blocks at
140
+ most `timeout` seconds and raises the ``Full`` exception if no
141
+ free slot was available within that time. Otherwise (`block`
142
+ is false), put an item on the queue if a free slot is
143
+ immediately available, else raise the ``Full`` exception
144
+ (`timeout` is ignored in that case).
145
+ """
146
+
147
+ with self.not_full:
148
+ if not block:
149
+ if self._full():
150
+ raise Full
151
+ elif timeout is None:
152
+ while self._full():
153
+ self.not_full.wait()
154
+ else:
155
+ if timeout < 0:
156
+ raise ValueError("'timeout' must be a positive number")
157
+ endtime = _time() + timeout
158
+ while self._full():
159
+ remaining = endtime - _time()
160
+ if remaining <= 0.0:
161
+ raise Full
162
+ self.not_full.wait(remaining)
163
+ self._put(item)
164
+ self.not_empty.notify()
165
+
166
+ def put_nowait(self, item: _T) -> None:
167
+ """Put an item into the queue without blocking.
168
+
169
+ Only enqueue the item if a free slot is immediately available.
170
+ Otherwise raise the ``Full`` exception.
171
+ """
172
+ return self.put(item, False)
173
+
174
+ def get(self, block: bool = True, timeout: Optional[float] = None) -> _T:
175
+ """Remove and return an item from the queue.
176
+
177
+ If optional args `block` is True and `timeout` is None (the
178
+ default), block if necessary until an item is available. If
179
+ `timeout` is a positive number, it blocks at most `timeout`
180
+ seconds and raises the ``Empty`` exception if no item was
181
+ available within that time. Otherwise (`block` is false),
182
+ return an item if one is immediately available, else raise the
183
+ ``Empty`` exception (`timeout` is ignored in that case).
184
+
185
+ """
186
+ with self.not_empty:
187
+ if not block:
188
+ if self._empty():
189
+ raise Empty
190
+ elif timeout is None:
191
+ while self._empty():
192
+ self.not_empty.wait()
193
+ else:
194
+ if timeout < 0:
195
+ raise ValueError("'timeout' must be a positive number")
196
+ endtime = _time() + timeout
197
+ while self._empty():
198
+ remaining = endtime - _time()
199
+ if remaining <= 0.0:
200
+ raise Empty
201
+ self.not_empty.wait(remaining)
202
+ item = self._get()
203
+ self.not_full.notify()
204
+ return item
205
+
206
+ def get_nowait(self) -> _T:
207
+ """Remove and return an item from the queue without blocking.
208
+
209
+ Only get an item if one is immediately available. Otherwise
210
+ raise the ``Empty`` exception.
211
+ """
212
+
213
+ return self.get(False)
214
+
215
+ def _init(self, maxsize: int) -> None:
216
+ self.maxsize = maxsize
217
+ self.queue = deque()
218
+
219
+ def _qsize(self) -> int:
220
+ return len(self.queue)
221
+
222
+ def _empty(self) -> bool:
223
+ return not self.queue
224
+
225
+ def _full(self) -> bool:
226
+ return self.maxsize > 0 and len(self.queue) == self.maxsize
227
+
228
+ def _put(self, item: _T) -> None:
229
+ self.queue.append(item)
230
+
231
+ def _get(self) -> _T:
232
+ if self.use_lifo:
233
+ # LIFO
234
+ return self.queue.pop()
235
+ else:
236
+ # FIFO
237
+ return self.queue.popleft()
238
+
239
+
240
+ class AsyncAdaptedQueue(QueueCommon[_T]):
241
+ if typing.TYPE_CHECKING:
242
+
243
+ @staticmethod
244
+ def await_(coroutine: Awaitable[Any]) -> _T: ...
245
+
246
+ else:
247
+ await_ = staticmethod(await_only)
248
+
249
+ def __init__(self, maxsize: int = 0, use_lifo: bool = False):
250
+ self.use_lifo = use_lifo
251
+ self.maxsize = maxsize
252
+
253
+ def empty(self) -> bool:
254
+ return self._queue.empty()
255
+
256
+ def full(self):
257
+ return self._queue.full()
258
+
259
+ def qsize(self):
260
+ return self._queue.qsize()
261
+
262
+ @memoized_property
263
+ def _queue(self) -> asyncio.Queue[_T]:
264
+ # Delay creation of the queue until it is first used, to avoid
265
+ # binding it to a possibly wrong event loop.
266
+ # By delaying the creation of the pool we accommodate the common
267
+ # usage pattern of instantiating the engine at module level, where a
268
+ # different event loop is in present compared to when the application
269
+ # is actually run.
270
+
271
+ queue: asyncio.Queue[_T]
272
+
273
+ if self.use_lifo:
274
+ queue = asyncio.LifoQueue(maxsize=self.maxsize)
275
+ else:
276
+ queue = asyncio.Queue(maxsize=self.maxsize)
277
+ return queue
278
+
279
+ def put_nowait(self, item: _T) -> None:
280
+ try:
281
+ self._queue.put_nowait(item)
282
+ except asyncio.QueueFull as err:
283
+ raise Full() from err
284
+
285
+ def put(
286
+ self, item: _T, block: bool = True, timeout: Optional[float] = None
287
+ ) -> None:
288
+ if not block:
289
+ return self.put_nowait(item)
290
+
291
+ try:
292
+ if timeout is not None:
293
+ self.await_(asyncio.wait_for(self._queue.put(item), timeout))
294
+ else:
295
+ self.await_(self._queue.put(item))
296
+ except (asyncio.QueueFull, asyncio.TimeoutError) as err:
297
+ raise Full() from err
298
+
299
+ def get_nowait(self) -> _T:
300
+ try:
301
+ return self._queue.get_nowait()
302
+ except asyncio.QueueEmpty as err:
303
+ raise Empty() from err
304
+
305
+ def get(self, block: bool = True, timeout: Optional[float] = None) -> _T:
306
+ if not block:
307
+ return self.get_nowait()
308
+
309
+ try:
310
+ if timeout is not None:
311
+ return self.await_(
312
+ asyncio.wait_for(self._queue.get(), timeout)
313
+ )
314
+ else:
315
+ return self.await_(self._queue.get())
316
+ except (asyncio.QueueEmpty, asyncio.TimeoutError) as err:
317
+ raise Empty() from err
318
+
319
+
320
+ class FallbackAsyncAdaptedQueue(AsyncAdaptedQueue[_T]):
321
+ if not typing.TYPE_CHECKING:
322
+ await_ = staticmethod(await_fallback)
@@ -0,0 +1,201 @@
1
+ # util/tool_support.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+ # mypy: allow-untyped-defs, allow-untyped-calls
8
+ """support routines for the helpers in tools/.
9
+
10
+ These aren't imported by the enclosing util package as the are not
11
+ needed for normal library use.
12
+
13
+ """
14
+ from __future__ import annotations
15
+
16
+ from argparse import ArgumentParser
17
+ from argparse import Namespace
18
+ import contextlib
19
+ import difflib
20
+ import os
21
+ from pathlib import Path
22
+ import shlex
23
+ import shutil
24
+ import subprocess
25
+ import sys
26
+ from typing import Any
27
+ from typing import Dict
28
+ from typing import Iterator
29
+ from typing import Optional
30
+ from typing import Union
31
+
32
+ from . import compat
33
+
34
+
35
+ class code_writer_cmd:
36
+ parser: ArgumentParser
37
+ args: Namespace
38
+ suppress_output: bool
39
+ diffs_detected: bool
40
+ source_root: Path
41
+ pyproject_toml_path: Path
42
+
43
+ def __init__(self, tool_script: str):
44
+ self.source_root = Path(tool_script).parent.parent
45
+ self.pyproject_toml_path = self.source_root / Path("pyproject.toml")
46
+ assert self.pyproject_toml_path.exists()
47
+
48
+ self.parser = ArgumentParser()
49
+ self.parser.add_argument(
50
+ "--stdout",
51
+ action="store_true",
52
+ help="Write to stdout instead of saving to file",
53
+ )
54
+ self.parser.add_argument(
55
+ "-c",
56
+ "--check",
57
+ help="Don't write the files back, just return the "
58
+ "status. Return code 0 means nothing would change. "
59
+ "Return code 1 means some files would be reformatted",
60
+ action="store_true",
61
+ )
62
+
63
+ def run_zimports(self, tempfile: str) -> None:
64
+ self._run_console_script(
65
+ str(tempfile),
66
+ {
67
+ "entrypoint": "zimports",
68
+ "options": f"--toml-config {self.pyproject_toml_path}",
69
+ },
70
+ )
71
+
72
+ def run_black(self, tempfile: str) -> None:
73
+ self._run_console_script(
74
+ str(tempfile),
75
+ {
76
+ "entrypoint": "black",
77
+ "options": f"--config {self.pyproject_toml_path}",
78
+ },
79
+ )
80
+
81
+ def _run_console_script(self, path: str, options: Dict[str, Any]) -> None:
82
+ """Run a Python console application from within the process.
83
+
84
+ Used for black, zimports
85
+
86
+ """
87
+
88
+ is_posix = os.name == "posix"
89
+
90
+ entrypoint_name = options["entrypoint"]
91
+
92
+ for entry in compat.importlib_metadata_get("console_scripts"):
93
+ if entry.name == entrypoint_name:
94
+ impl = entry
95
+ break
96
+ else:
97
+ raise Exception(
98
+ f"Could not find entrypoint console_scripts.{entrypoint_name}"
99
+ )
100
+ cmdline_options_str = options.get("options", "")
101
+ cmdline_options_list = shlex.split(
102
+ cmdline_options_str, posix=is_posix
103
+ ) + [path]
104
+
105
+ kw: Dict[str, Any] = {}
106
+ if self.suppress_output:
107
+ kw["stdout"] = kw["stderr"] = subprocess.DEVNULL
108
+
109
+ subprocess.run(
110
+ [
111
+ sys.executable,
112
+ "-c",
113
+ "import %s; %s.%s()" % (impl.module, impl.module, impl.attr),
114
+ ]
115
+ + cmdline_options_list,
116
+ cwd=str(self.source_root),
117
+ **kw,
118
+ )
119
+
120
+ def write_status(self, *text: str) -> None:
121
+ if not self.suppress_output:
122
+ sys.stderr.write(" ".join(text))
123
+
124
+ def write_output_file_from_text(
125
+ self, text: str, destination_path: Union[str, Path]
126
+ ) -> None:
127
+ if self.args.check:
128
+ self._run_diff(destination_path, source=text)
129
+ elif self.args.stdout:
130
+ print(text)
131
+ else:
132
+ self.write_status(f"Writing {destination_path}...")
133
+ Path(destination_path).write_text(
134
+ text, encoding="utf-8", newline="\n"
135
+ )
136
+ self.write_status("done\n")
137
+
138
+ def write_output_file_from_tempfile(
139
+ self, tempfile: str, destination_path: str
140
+ ) -> None:
141
+ if self.args.check:
142
+ self._run_diff(destination_path, source_file=tempfile)
143
+ os.unlink(tempfile)
144
+ elif self.args.stdout:
145
+ with open(tempfile) as tf:
146
+ print(tf.read())
147
+ os.unlink(tempfile)
148
+ else:
149
+ self.write_status(f"Writing {destination_path}...")
150
+ shutil.move(tempfile, destination_path)
151
+ self.write_status("done\n")
152
+
153
+ def _run_diff(
154
+ self,
155
+ destination_path: Union[str, Path],
156
+ *,
157
+ source: Optional[str] = None,
158
+ source_file: Optional[str] = None,
159
+ ) -> None:
160
+ if source_file:
161
+ with open(source_file, encoding="utf-8") as tf:
162
+ source_lines = list(tf)
163
+ elif source is not None:
164
+ source_lines = source.splitlines(keepends=True)
165
+ else:
166
+ assert False, "source or source_file is required"
167
+
168
+ with open(destination_path, encoding="utf-8") as dp:
169
+ d = difflib.unified_diff(
170
+ list(dp),
171
+ source_lines,
172
+ fromfile=Path(destination_path).as_posix(),
173
+ tofile="<proposed changes>",
174
+ n=3,
175
+ lineterm="\n",
176
+ )
177
+ d_as_list = list(d)
178
+ if d_as_list:
179
+ self.diffs_detected = True
180
+ print("".join(d_as_list))
181
+
182
+ @contextlib.contextmanager
183
+ def add_arguments(self) -> Iterator[ArgumentParser]:
184
+ yield self.parser
185
+
186
+ @contextlib.contextmanager
187
+ def run_program(self) -> Iterator[None]:
188
+ self.args = self.parser.parse_args()
189
+ if self.args.check:
190
+ self.diffs_detected = False
191
+ self.suppress_output = True
192
+ elif self.args.stdout:
193
+ self.suppress_output = True
194
+ else:
195
+ self.suppress_output = False
196
+ yield
197
+
198
+ if self.args.check and self.diffs_detected:
199
+ sys.exit(1)
200
+ else:
201
+ sys.exit(0)