SQLAlchemy 2.1.0rc1__cp315-cp315-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. sqlalchemy/__init__.py +299 -0
  2. sqlalchemy/connectors/__init__.py +18 -0
  3. sqlalchemy/connectors/aioodbc.py +171 -0
  4. sqlalchemy/connectors/asyncio.py +476 -0
  5. sqlalchemy/connectors/pyodbc.py +248 -0
  6. sqlalchemy/dialects/__init__.py +62 -0
  7. sqlalchemy/dialects/_typing.py +29 -0
  8. sqlalchemy/dialects/mssql/__init__.py +88 -0
  9. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  10. sqlalchemy/dialects/mssql/base.py +4833 -0
  11. sqlalchemy/dialects/mssql/information_schema.py +345 -0
  12. sqlalchemy/dialects/mssql/json.py +140 -0
  13. sqlalchemy/dialects/mssql/mssqlpython.py +242 -0
  14. sqlalchemy/dialects/mssql/provision.py +196 -0
  15. sqlalchemy/dialects/mssql/pymssql.py +130 -0
  16. sqlalchemy/dialects/mssql/pyodbc.py +697 -0
  17. sqlalchemy/dialects/mysql/__init__.py +106 -0
  18. sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
  19. sqlalchemy/dialects/mysql/aiomysql.py +260 -0
  20. sqlalchemy/dialects/mysql/asyncmy.py +241 -0
  21. sqlalchemy/dialects/mysql/base.py +3896 -0
  22. sqlalchemy/dialects/mysql/cymysql.py +107 -0
  23. sqlalchemy/dialects/mysql/dml.py +279 -0
  24. sqlalchemy/dialects/mysql/enumerated.py +277 -0
  25. sqlalchemy/dialects/mysql/expression.py +146 -0
  26. sqlalchemy/dialects/mysql/json.py +92 -0
  27. sqlalchemy/dialects/mysql/mariadb.py +67 -0
  28. sqlalchemy/dialects/mysql/mariadbconnector.py +314 -0
  29. sqlalchemy/dialects/mysql/mysqlconnector.py +291 -0
  30. sqlalchemy/dialects/mysql/mysqldb.py +318 -0
  31. sqlalchemy/dialects/mysql/provision.py +153 -0
  32. sqlalchemy/dialects/mysql/pymysql.py +188 -0
  33. sqlalchemy/dialects/mysql/pyodbc.py +157 -0
  34. sqlalchemy/dialects/mysql/reflection.py +724 -0
  35. sqlalchemy/dialects/mysql/reserved_words.py +570 -0
  36. sqlalchemy/dialects/mysql/types.py +845 -0
  37. sqlalchemy/dialects/oracle/__init__.py +85 -0
  38. sqlalchemy/dialects/oracle/base.py +3847 -0
  39. sqlalchemy/dialects/oracle/cx_oracle.py +1736 -0
  40. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  41. sqlalchemy/dialects/oracle/json.py +157 -0
  42. sqlalchemy/dialects/oracle/oracledb.py +898 -0
  43. sqlalchemy/dialects/oracle/provision.py +288 -0
  44. sqlalchemy/dialects/oracle/types.py +367 -0
  45. sqlalchemy/dialects/oracle/vector.py +366 -0
  46. sqlalchemy/dialects/postgresql/__init__.py +170 -0
  47. sqlalchemy/dialects/postgresql/_psycopg_common.py +232 -0
  48. sqlalchemy/dialects/postgresql/array.py +534 -0
  49. sqlalchemy/dialects/postgresql/asyncpg.py +1318 -0
  50. sqlalchemy/dialects/postgresql/base.py +5935 -0
  51. sqlalchemy/dialects/postgresql/bitstring.py +327 -0
  52. sqlalchemy/dialects/postgresql/dml.py +360 -0
  53. sqlalchemy/dialects/postgresql/ext.py +599 -0
  54. sqlalchemy/dialects/postgresql/hstore.py +422 -0
  55. sqlalchemy/dialects/postgresql/json.py +411 -0
  56. sqlalchemy/dialects/postgresql/named_types.py +535 -0
  57. sqlalchemy/dialects/postgresql/operators.py +129 -0
  58. sqlalchemy/dialects/postgresql/pg8000.py +655 -0
  59. sqlalchemy/dialects/postgresql/pg_catalog.py +345 -0
  60. sqlalchemy/dialects/postgresql/provision.py +202 -0
  61. sqlalchemy/dialects/postgresql/psycopg.py +800 -0
  62. sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
  63. sqlalchemy/dialects/postgresql/psycopg2cffi.py +62 -0
  64. sqlalchemy/dialects/postgresql/ranges.py +1002 -0
  65. sqlalchemy/dialects/postgresql/types.py +388 -0
  66. sqlalchemy/dialects/sqlite/__init__.py +59 -0
  67. sqlalchemy/dialects/sqlite/aiosqlite.py +375 -0
  68. sqlalchemy/dialects/sqlite/base.py +3103 -0
  69. sqlalchemy/dialects/sqlite/dml.py +314 -0
  70. sqlalchemy/dialects/sqlite/json.py +134 -0
  71. sqlalchemy/dialects/sqlite/provision.py +237 -0
  72. sqlalchemy/dialects/sqlite/pysqlcipher.py +166 -0
  73. sqlalchemy/dialects/sqlite/pysqlite.py +959 -0
  74. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  75. sqlalchemy/engine/__init__.py +62 -0
  76. sqlalchemy/engine/_processors_cy.cp315-win_amd64.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp315-win_amd64.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +711 -0
  80. sqlalchemy/engine/_row_cy.cp315-win_amd64.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp315-win_amd64.pyd +0 -0
  83. sqlalchemy/engine/_util_cy.py +136 -0
  84. sqlalchemy/engine/base.py +3357 -0
  85. sqlalchemy/engine/characteristics.py +155 -0
  86. sqlalchemy/engine/create.py +877 -0
  87. sqlalchemy/engine/cursor.py +2425 -0
  88. sqlalchemy/engine/default.py +2627 -0
  89. sqlalchemy/engine/events.py +965 -0
  90. sqlalchemy/engine/interfaces.py +3636 -0
  91. sqlalchemy/engine/mock.py +133 -0
  92. sqlalchemy/engine/processors.py +83 -0
  93. sqlalchemy/engine/reflection.py +2141 -0
  94. sqlalchemy/engine/result.py +2012 -0
  95. sqlalchemy/engine/row.py +397 -0
  96. sqlalchemy/engine/strategies.py +16 -0
  97. sqlalchemy/engine/url.py +922 -0
  98. sqlalchemy/engine/util.py +164 -0
  99. sqlalchemy/event/__init__.py +26 -0
  100. sqlalchemy/event/api.py +220 -0
  101. sqlalchemy/event/attr.py +675 -0
  102. sqlalchemy/event/base.py +473 -0
  103. sqlalchemy/event/legacy.py +259 -0
  104. sqlalchemy/event/registry.py +391 -0
  105. sqlalchemy/events.py +17 -0
  106. sqlalchemy/exc.py +939 -0
  107. sqlalchemy/ext/__init__.py +10 -0
  108. sqlalchemy/ext/associationproxy.py +2073 -0
  109. sqlalchemy/ext/asyncio/__init__.py +29 -0
  110. sqlalchemy/ext/asyncio/base.py +281 -0
  111. sqlalchemy/ext/asyncio/engine.py +1487 -0
  112. sqlalchemy/ext/asyncio/exc.py +21 -0
  113. sqlalchemy/ext/asyncio/result.py +994 -0
  114. sqlalchemy/ext/asyncio/scoping.py +1679 -0
  115. sqlalchemy/ext/asyncio/session.py +2006 -0
  116. sqlalchemy/ext/automap.py +1702 -0
  117. sqlalchemy/ext/baked.py +558 -0
  118. sqlalchemy/ext/compiler.py +601 -0
  119. sqlalchemy/ext/declarative/__init__.py +65 -0
  120. sqlalchemy/ext/declarative/extensions.py +561 -0
  121. sqlalchemy/ext/horizontal_shard.py +481 -0
  122. sqlalchemy/ext/hybrid.py +1877 -0
  123. sqlalchemy/ext/indexable.py +364 -0
  124. sqlalchemy/ext/instrumentation.py +450 -0
  125. sqlalchemy/ext/mutable.py +1081 -0
  126. sqlalchemy/ext/orderinglist.py +440 -0
  127. sqlalchemy/ext/serializer.py +184 -0
  128. sqlalchemy/future/__init__.py +17 -0
  129. sqlalchemy/future/engine.py +15 -0
  130. sqlalchemy/inspection.py +188 -0
  131. sqlalchemy/log.py +279 -0
  132. sqlalchemy/orm/__init__.py +176 -0
  133. sqlalchemy/orm/_orm_constructors.py +2694 -0
  134. sqlalchemy/orm/_typing.py +180 -0
  135. sqlalchemy/orm/attributes.py +2868 -0
  136. sqlalchemy/orm/base.py +991 -0
  137. sqlalchemy/orm/bulk_persistence.py +2168 -0
  138. sqlalchemy/orm/clsregistry.py +630 -0
  139. sqlalchemy/orm/collections.py +1569 -0
  140. sqlalchemy/orm/context.py +3475 -0
  141. sqlalchemy/orm/decl_api.py +2283 -0
  142. sqlalchemy/orm/decl_base.py +2320 -0
  143. sqlalchemy/orm/dependency.py +1306 -0
  144. sqlalchemy/orm/descriptor_props.py +1183 -0
  145. sqlalchemy/orm/dynamic.py +306 -0
  146. sqlalchemy/orm/evaluator.py +378 -0
  147. sqlalchemy/orm/events.py +3387 -0
  148. sqlalchemy/orm/exc.py +237 -0
  149. sqlalchemy/orm/identity.py +302 -0
  150. sqlalchemy/orm/instrumentation.py +749 -0
  151. sqlalchemy/orm/interfaces.py +1595 -0
  152. sqlalchemy/orm/loading.py +1712 -0
  153. sqlalchemy/orm/mapped_collection.py +557 -0
  154. sqlalchemy/orm/mapper.py +4465 -0
  155. sqlalchemy/orm/path_registry.py +907 -0
  156. sqlalchemy/orm/persistence.py +1790 -0
  157. sqlalchemy/orm/properties.py +972 -0
  158. sqlalchemy/orm/query.py +3528 -0
  159. sqlalchemy/orm/relationships.py +3608 -0
  160. sqlalchemy/orm/scoping.py +2233 -0
  161. sqlalchemy/orm/session.py +5468 -0
  162. sqlalchemy/orm/state.py +1175 -0
  163. sqlalchemy/orm/state_changes.py +196 -0
  164. sqlalchemy/orm/strategies.py +3552 -0
  165. sqlalchemy/orm/strategy_options.py +2648 -0
  166. sqlalchemy/orm/sync.py +164 -0
  167. sqlalchemy/orm/unitofwork.py +797 -0
  168. sqlalchemy/orm/util.py +2461 -0
  169. sqlalchemy/orm/writeonly.py +701 -0
  170. sqlalchemy/pool/__init__.py +41 -0
  171. sqlalchemy/pool/base.py +1540 -0
  172. sqlalchemy/pool/events.py +375 -0
  173. sqlalchemy/pool/impl.py +583 -0
  174. sqlalchemy/py.typed +0 -0
  175. sqlalchemy/schema.py +75 -0
  176. sqlalchemy/sql/__init__.py +156 -0
  177. sqlalchemy/sql/_annotated_cols.py +402 -0
  178. sqlalchemy/sql/_cache_key_cy.cp315-win_amd64.pyd +0 -0
  179. sqlalchemy/sql/_cache_key_cy.py +363 -0
  180. sqlalchemy/sql/_dml_constructors.py +132 -0
  181. sqlalchemy/sql/_elements_constructors.py +2190 -0
  182. sqlalchemy/sql/_orm_types.py +19 -0
  183. sqlalchemy/sql/_selectable_constructors.py +840 -0
  184. sqlalchemy/sql/_typing.py +500 -0
  185. sqlalchemy/sql/_util_cy.cp315-win_amd64.pyd +0 -0
  186. sqlalchemy/sql/_util_cy.pxd +11 -0
  187. sqlalchemy/sql/_util_cy.py +127 -0
  188. sqlalchemy/sql/annotation.py +590 -0
  189. sqlalchemy/sql/base.py +2702 -0
  190. sqlalchemy/sql/cache_key.py +915 -0
  191. sqlalchemy/sql/coercions.py +1373 -0
  192. sqlalchemy/sql/compiler.py +8453 -0
  193. sqlalchemy/sql/crud.py +1816 -0
  194. sqlalchemy/sql/ddl.py +1962 -0
  195. sqlalchemy/sql/default_comparator.py +660 -0
  196. sqlalchemy/sql/dml.py +2018 -0
  197. sqlalchemy/sql/elements.py +6057 -0
  198. sqlalchemy/sql/events.py +458 -0
  199. sqlalchemy/sql/expression.py +171 -0
  200. sqlalchemy/sql/functions.py +2380 -0
  201. sqlalchemy/sql/lambdas.py +1442 -0
  202. sqlalchemy/sql/naming.py +204 -0
  203. sqlalchemy/sql/operators.py +2909 -0
  204. sqlalchemy/sql/roles.py +332 -0
  205. sqlalchemy/sql/schema.py +7075 -0
  206. sqlalchemy/sql/selectable.py +7634 -0
  207. sqlalchemy/sql/sqltypes.py +4130 -0
  208. sqlalchemy/sql/traversals.py +1041 -0
  209. sqlalchemy/sql/type_api.py +2450 -0
  210. sqlalchemy/sql/util.py +1496 -0
  211. sqlalchemy/sql/visitors.py +1153 -0
  212. sqlalchemy/testing/__init__.py +97 -0
  213. sqlalchemy/testing/assertions.py +1007 -0
  214. sqlalchemy/testing/assertsql.py +519 -0
  215. sqlalchemy/testing/asyncio.py +128 -0
  216. sqlalchemy/testing/cancellation.py +237 -0
  217. sqlalchemy/testing/config.py +440 -0
  218. sqlalchemy/testing/engines.py +482 -0
  219. sqlalchemy/testing/entities.py +117 -0
  220. sqlalchemy/testing/exclusions.py +501 -0
  221. sqlalchemy/testing/fixtures/__init__.py +30 -0
  222. sqlalchemy/testing/fixtures/base.py +426 -0
  223. sqlalchemy/testing/fixtures/mypy.py +247 -0
  224. sqlalchemy/testing/fixtures/orm.py +227 -0
  225. sqlalchemy/testing/fixtures/sql.py +538 -0
  226. sqlalchemy/testing/pickleable.py +155 -0
  227. sqlalchemy/testing/plugin/__init__.py +6 -0
  228. sqlalchemy/testing/plugin/bootstrap.py +50 -0
  229. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  230. sqlalchemy/testing/plugin/pytestplugin.py +896 -0
  231. sqlalchemy/testing/profiles_file.py +350 -0
  232. sqlalchemy/testing/profiling.py +294 -0
  233. sqlalchemy/testing/provision.py +633 -0
  234. sqlalchemy/testing/requirements.py +1971 -0
  235. sqlalchemy/testing/schema.py +198 -0
  236. sqlalchemy/testing/suite/__init__.py +19 -0
  237. sqlalchemy/testing/suite/test_cte.py +237 -0
  238. sqlalchemy/testing/suite/test_ddl.py +420 -0
  239. sqlalchemy/testing/suite/test_dialect.py +776 -0
  240. sqlalchemy/testing/suite/test_insert.py +630 -0
  241. sqlalchemy/testing/suite/test_reflection.py +3815 -0
  242. sqlalchemy/testing/suite/test_results.py +660 -0
  243. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  244. sqlalchemy/testing/suite/test_select.py +2112 -0
  245. sqlalchemy/testing/suite/test_sequence.py +317 -0
  246. sqlalchemy/testing/suite/test_table_via_select.py +686 -0
  247. sqlalchemy/testing/suite/test_types.py +2271 -0
  248. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  249. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  250. sqlalchemy/testing/util.py +575 -0
  251. sqlalchemy/testing/warnings.py +52 -0
  252. sqlalchemy/types.py +75 -0
  253. sqlalchemy/util/__init__.py +165 -0
  254. sqlalchemy/util/_collections.py +688 -0
  255. sqlalchemy/util/_collections_cy.cp315-win_amd64.pyd +0 -0
  256. sqlalchemy/util/_collections_cy.pxd +8 -0
  257. sqlalchemy/util/_collections_cy.py +516 -0
  258. sqlalchemy/util/_has_cython.py +48 -0
  259. sqlalchemy/util/_immutabledict_cy.cp315-win_amd64.pyd +0 -0
  260. sqlalchemy/util/_immutabledict_cy.py +240 -0
  261. sqlalchemy/util/compat.py +298 -0
  262. sqlalchemy/util/concurrency.py +272 -0
  263. sqlalchemy/util/cython.py +95 -0
  264. sqlalchemy/util/deprecations.py +401 -0
  265. sqlalchemy/util/langhelpers.py +2797 -0
  266. sqlalchemy/util/preloaded.py +153 -0
  267. sqlalchemy/util/queue.py +304 -0
  268. sqlalchemy/util/tool_support.py +202 -0
  269. sqlalchemy/util/topological.py +120 -0
  270. sqlalchemy/util/typing.py +709 -0
  271. sqlalchemy-2.1.0rc1.dist-info/METADATA +270 -0
  272. sqlalchemy-2.1.0rc1.dist-info/RECORD +276 -0
  273. sqlalchemy-2.1.0rc1.dist-info/WHEEL +5 -0
  274. sqlalchemy-2.1.0rc1.dist-info/licenses/AUTHORS +30 -0
  275. sqlalchemy-2.1.0rc1.dist-info/licenses/LICENSE +19 -0
  276. sqlalchemy-2.1.0rc1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,153 @@
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
+
14
+ from __future__ import annotations
15
+
16
+ import sys
17
+ from typing import Any
18
+ from typing import Callable
19
+ from typing import TYPE_CHECKING
20
+ from typing import TypeVar
21
+
22
+ _FN = TypeVar("_FN", bound=Callable[..., Any])
23
+
24
+
25
+ if TYPE_CHECKING:
26
+ from sqlalchemy import dialects as _dialects
27
+ from sqlalchemy import orm as _orm
28
+ from sqlalchemy.engine import cursor as _engine_cursor
29
+ from sqlalchemy.engine import default as _engine_default
30
+ from sqlalchemy.engine import reflection as _engine_reflection
31
+ from sqlalchemy.engine import result as _engine_result
32
+ from sqlalchemy.engine import url as _engine_url
33
+ from sqlalchemy.orm import attributes as _orm_attributes
34
+ from sqlalchemy.orm import base as _orm_base
35
+ from sqlalchemy.orm import clsregistry as _orm_clsregistry
36
+ from sqlalchemy.orm import decl_api as _orm_decl_api
37
+ from sqlalchemy.orm import decl_base as _orm_decl_base
38
+ from sqlalchemy.orm import dependency as _orm_dependency
39
+ from sqlalchemy.orm import descriptor_props as _orm_descriptor_props
40
+ from sqlalchemy.orm import mapperlib as _orm_mapper
41
+ from sqlalchemy.orm import properties as _orm_properties
42
+ from sqlalchemy.orm import relationships as _orm_relationships
43
+ from sqlalchemy.orm import session as _orm_session
44
+ from sqlalchemy.orm import state as _orm_state
45
+ from sqlalchemy.orm import strategies as _orm_strategies
46
+ from sqlalchemy.orm import strategy_options as _orm_strategy_options
47
+ from sqlalchemy.orm import util as _orm_util
48
+ from sqlalchemy.sql import ddl as _sql_ddl
49
+ from sqlalchemy.sql import default_comparator as _sql_default_comparator
50
+ from sqlalchemy.sql import dml as _sql_dml
51
+ from sqlalchemy.sql import elements as _sql_elements
52
+ from sqlalchemy.sql import functions as _sql_functions
53
+ from sqlalchemy.sql import naming as _sql_naming
54
+ from sqlalchemy.sql import schema as _sql_schema
55
+ from sqlalchemy.sql import selectable as _sql_selectable
56
+ from sqlalchemy.sql import sqltypes as _sql_sqltypes
57
+ from sqlalchemy.sql import traversals as _sql_traversals
58
+ from sqlalchemy.sql import util as _sql_util
59
+
60
+ # sigh, appease mypy 0.971 which does not accept imports as instance
61
+ # variables of a module
62
+ dialects = _dialects
63
+ engine_cursor = _engine_cursor
64
+ engine_default = _engine_default
65
+ engine_reflection = _engine_reflection
66
+ engine_result = _engine_result
67
+ engine_url = _engine_url
68
+ orm_clsregistry = _orm_clsregistry
69
+ orm_base = _orm_base
70
+ orm = _orm
71
+ orm_attributes = _orm_attributes
72
+ orm_decl_api = _orm_decl_api
73
+ orm_decl_base = _orm_decl_base
74
+ orm_descriptor_props = _orm_descriptor_props
75
+ orm_dependency = _orm_dependency
76
+ orm_mapper = _orm_mapper
77
+ orm_properties = _orm_properties
78
+ orm_relationships = _orm_relationships
79
+ orm_session = _orm_session
80
+ orm_strategies = _orm_strategies
81
+ orm_strategy_options = _orm_strategy_options
82
+ orm_state = _orm_state
83
+ orm_util = _orm_util
84
+ sql_ddl = _sql_ddl
85
+ sql_default_comparator = _sql_default_comparator
86
+ sql_dml = _sql_dml
87
+ sql_elements = _sql_elements
88
+ sql_functions = _sql_functions
89
+ sql_naming = _sql_naming
90
+ sql_selectable = _sql_selectable
91
+ sql_traversals = _sql_traversals
92
+ sql_schema = _sql_schema
93
+ sql_sqltypes = _sql_sqltypes
94
+ sql_util = _sql_util
95
+
96
+
97
+ class _ModuleRegistry:
98
+ """Registry of modules to load in a package init file.
99
+
100
+ To avoid potential thread safety issues for imports that are deferred
101
+ in a function, like https://bugs.python.org/issue38884, these modules
102
+ are added to the system module cache by importing them after the packages
103
+ has finished initialization.
104
+
105
+ A global instance is provided under the name :attr:`.preloaded`. Use
106
+ the function :func:`.preload_module` to register modules to load and
107
+ :meth:`.import_prefix` to load all the modules that start with the
108
+ given path.
109
+
110
+ While the modules are loaded in the global module cache, it's advisable
111
+ to access them using :attr:`.preloaded` to ensure that it was actually
112
+ registered. Each registered module is added to the instance ``__dict__``
113
+ in the form `<package>_<module>`, omitting ``sqlalchemy`` from the package
114
+ name. Example: ``sqlalchemy.sql.util`` becomes ``preloaded.sql_util``.
115
+ """
116
+
117
+ def __init__(self, prefix="sqlalchemy."):
118
+ self.module_registry = set()
119
+ self.prefix = prefix
120
+
121
+ def preload_module(self, *deps: str) -> Callable[[_FN], _FN]:
122
+ """Adds the specified modules to the list to load.
123
+
124
+ This method can be used both as a normal function and as a decorator.
125
+ No change is performed to the decorated object.
126
+ """
127
+ self.module_registry.update(deps)
128
+ return lambda fn: fn
129
+
130
+ def import_prefix(self, path: str) -> None:
131
+ """Resolve all the modules in the registry that start with the
132
+ specified path.
133
+ """
134
+ for module in self.module_registry:
135
+ if self.prefix:
136
+ key = module.split(self.prefix)[-1].replace(".", "_")
137
+ else:
138
+ key = module
139
+ if (
140
+ not path or module.startswith(path)
141
+ ) and key not in self.__dict__:
142
+ __import__(module, globals(), locals())
143
+ self.__dict__[key] = globals()[key] = sys.modules[module]
144
+
145
+
146
+ _reg = _ModuleRegistry()
147
+ preload_module = _reg.preload_module
148
+ import_prefix = _reg.import_prefix
149
+
150
+ # this appears to do absolutely nothing for any version of mypy
151
+ # if TYPE_CHECKING:
152
+ # def __getattr__(key: str) -> ModuleType:
153
+ # ...
@@ -0,0 +1,304 @@
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
+
22
+ from __future__ import annotations
23
+
24
+ import asyncio
25
+ from collections import deque
26
+ import threading
27
+ from time import time as _time
28
+ from typing import Any
29
+ from typing import Deque
30
+ from typing import Generic
31
+ from typing import Optional
32
+ from typing import TypeVar
33
+
34
+ from .concurrency import await_
35
+ from .langhelpers import memoized_property
36
+
37
+ _T = TypeVar("_T", bound=Any)
38
+ __all__ = ["Empty", "Full", "Queue"]
39
+
40
+
41
+ class Empty(Exception):
42
+ "Exception raised by Queue.get(block=0)/get_nowait()."
43
+
44
+ pass
45
+
46
+
47
+ class Full(Exception):
48
+ "Exception raised by Queue.put(block=0)/put_nowait()."
49
+
50
+ pass
51
+
52
+
53
+ class QueueCommon(Generic[_T]):
54
+ maxsize: int
55
+ use_lifo: bool
56
+
57
+ def __init__(self, maxsize: int = 0, use_lifo: bool = False): ...
58
+
59
+ def empty(self) -> bool:
60
+ raise NotImplementedError()
61
+
62
+ def full(self) -> bool:
63
+ raise NotImplementedError()
64
+
65
+ def qsize(self) -> int:
66
+ raise NotImplementedError()
67
+
68
+ def put_nowait(self, item: _T) -> None:
69
+ raise NotImplementedError()
70
+
71
+ def put(
72
+ self, item: _T, block: bool = True, timeout: Optional[float] = None
73
+ ) -> None:
74
+ raise NotImplementedError()
75
+
76
+ def get_nowait(self) -> _T:
77
+ raise NotImplementedError()
78
+
79
+ def get(self, block: bool = True, timeout: Optional[float] = None) -> _T:
80
+ raise NotImplementedError()
81
+
82
+
83
+ class Queue(QueueCommon[_T]):
84
+ queue: Deque[_T]
85
+
86
+ def __init__(self, maxsize: int = 0, use_lifo: bool = False):
87
+ """Initialize a queue object with a given maximum size.
88
+
89
+ If `maxsize` is <= 0, the queue size is infinite.
90
+
91
+ If `use_lifo` is True, this Queue acts like a Stack (LIFO).
92
+ """
93
+
94
+ self._init(maxsize)
95
+ # mutex must be held whenever the queue is mutating. All methods
96
+ # that acquire mutex must release it before returning. mutex
97
+ # is shared between the two conditions, so acquiring and
98
+ # releasing the conditions also acquires and releases mutex.
99
+ self.mutex = threading.RLock()
100
+ # Notify not_empty whenever an item is added to the queue; a
101
+ # thread waiting to get is notified then.
102
+ self.not_empty = threading.Condition(self.mutex)
103
+ # Notify not_full whenever an item is removed from the queue;
104
+ # a thread waiting to put is notified then.
105
+ self.not_full = threading.Condition(self.mutex)
106
+ # If this queue uses LIFO or FIFO
107
+ self.use_lifo = use_lifo
108
+
109
+ def qsize(self) -> int:
110
+ """Return the approximate size of the queue (not reliable!)."""
111
+
112
+ with self.mutex:
113
+ return self._qsize()
114
+
115
+ def empty(self) -> bool:
116
+ """Return True if the queue is empty, False otherwise (not
117
+ reliable!)."""
118
+
119
+ with self.mutex:
120
+ return self._empty()
121
+
122
+ def full(self) -> bool:
123
+ """Return True if the queue is full, False otherwise (not
124
+ reliable!)."""
125
+
126
+ with self.mutex:
127
+ return self._full()
128
+
129
+ def put(
130
+ self, item: _T, block: bool = True, timeout: Optional[float] = None
131
+ ) -> None:
132
+ """Put an item into the queue.
133
+
134
+ If optional args `block` is True and `timeout` is None (the
135
+ default), block if necessary until a free slot is
136
+ available. If `timeout` is a positive number, it blocks at
137
+ most `timeout` seconds and raises the ``Full`` exception if no
138
+ free slot was available within that time. Otherwise (`block`
139
+ is false), put an item on the queue if a free slot is
140
+ immediately available, else raise the ``Full`` exception
141
+ (`timeout` is ignored in that case).
142
+ """
143
+
144
+ with self.not_full:
145
+ if not block:
146
+ if self._full():
147
+ raise Full
148
+ elif timeout is None:
149
+ while self._full():
150
+ self.not_full.wait()
151
+ else:
152
+ if timeout < 0:
153
+ raise ValueError("'timeout' must be a positive number")
154
+ endtime = _time() + timeout
155
+ while self._full():
156
+ remaining = endtime - _time()
157
+ if remaining <= 0.0:
158
+ raise Full
159
+ self.not_full.wait(remaining)
160
+ self._put(item)
161
+ self.not_empty.notify()
162
+
163
+ def put_nowait(self, item: _T) -> None:
164
+ """Put an item into the queue without blocking.
165
+
166
+ Only enqueue the item if a free slot is immediately available.
167
+ Otherwise raise the ``Full`` exception.
168
+ """
169
+ return self.put(item, False)
170
+
171
+ def get(self, block: bool = True, timeout: Optional[float] = None) -> _T:
172
+ """Remove and return an item from the queue.
173
+
174
+ If optional args `block` is True and `timeout` is None (the
175
+ default), block if necessary until an item is available. If
176
+ `timeout` is a positive number, it blocks at most `timeout`
177
+ seconds and raises the ``Empty`` exception if no item was
178
+ available within that time. Otherwise (`block` is false),
179
+ return an item if one is immediately available, else raise the
180
+ ``Empty`` exception (`timeout` is ignored in that case).
181
+
182
+ """
183
+ with self.not_empty:
184
+ if not block:
185
+ if self._empty():
186
+ raise Empty
187
+ elif timeout is None:
188
+ while self._empty():
189
+ self.not_empty.wait()
190
+ else:
191
+ if timeout < 0:
192
+ raise ValueError("'timeout' must be a positive number")
193
+ endtime = _time() + timeout
194
+ while self._empty():
195
+ remaining = endtime - _time()
196
+ if remaining <= 0.0:
197
+ raise Empty
198
+ self.not_empty.wait(remaining)
199
+ item = self._get()
200
+ self.not_full.notify()
201
+ return item
202
+
203
+ def get_nowait(self) -> _T:
204
+ """Remove and return an item from the queue without blocking.
205
+
206
+ Only get an item if one is immediately available. Otherwise
207
+ raise the ``Empty`` exception.
208
+ """
209
+
210
+ return self.get(False)
211
+
212
+ def _init(self, maxsize: int) -> None:
213
+ self.maxsize = maxsize
214
+ self.queue = deque()
215
+
216
+ def _qsize(self) -> int:
217
+ return len(self.queue)
218
+
219
+ def _empty(self) -> bool:
220
+ return not self.queue
221
+
222
+ def _full(self) -> bool:
223
+ return self.maxsize > 0 and len(self.queue) == self.maxsize
224
+
225
+ def _put(self, item: _T) -> None:
226
+ self.queue.append(item)
227
+
228
+ def _get(self) -> _T:
229
+ if self.use_lifo:
230
+ # LIFO
231
+ return self.queue.pop()
232
+ else:
233
+ # FIFO
234
+ return self.queue.popleft()
235
+
236
+
237
+ class AsyncAdaptedQueue(QueueCommon[_T]):
238
+ def __init__(self, maxsize: int = 0, use_lifo: bool = False):
239
+ self.use_lifo = use_lifo
240
+ self.maxsize = maxsize
241
+
242
+ def empty(self) -> bool:
243
+ return self._queue.empty()
244
+
245
+ def full(self):
246
+ return self._queue.full()
247
+
248
+ def qsize(self):
249
+ return self._queue.qsize()
250
+
251
+ @memoized_property
252
+ def _queue(self) -> asyncio.Queue[_T]:
253
+ # Delay creation of the queue until it is first used, to avoid
254
+ # binding it to a possibly wrong event loop.
255
+ # By delaying the creation of the pool we accommodate the common
256
+ # usage pattern of instantiating the engine at module level, where a
257
+ # different event loop is in present compared to when the application
258
+ # is actually run.
259
+
260
+ queue: asyncio.Queue[_T]
261
+
262
+ if self.use_lifo:
263
+ queue = asyncio.LifoQueue(maxsize=self.maxsize)
264
+ else:
265
+ queue = asyncio.Queue(maxsize=self.maxsize)
266
+ return queue
267
+
268
+ def put_nowait(self, item: _T) -> None:
269
+ try:
270
+ self._queue.put_nowait(item)
271
+ except asyncio.QueueFull as err:
272
+ raise Full() from err
273
+
274
+ def put(
275
+ self, item: _T, block: bool = True, timeout: Optional[float] = None
276
+ ) -> None:
277
+ if not block:
278
+ return self.put_nowait(item)
279
+
280
+ try:
281
+ if timeout is not None:
282
+ await_(asyncio.wait_for(self._queue.put(item), timeout))
283
+ else:
284
+ await_(self._queue.put(item))
285
+ except (asyncio.QueueFull, asyncio.TimeoutError) as err:
286
+ raise Full() from err
287
+
288
+ def get_nowait(self) -> _T:
289
+ try:
290
+ return self._queue.get_nowait()
291
+ except asyncio.QueueEmpty as err:
292
+ raise Empty() from err
293
+
294
+ def get(self, block: bool = True, timeout: Optional[float] = None) -> _T:
295
+ if not block:
296
+ return self.get_nowait()
297
+
298
+ try:
299
+ if timeout is not None:
300
+ return await_(asyncio.wait_for(self._queue.get(), timeout))
301
+ else:
302
+ return await_(self._queue.get())
303
+ except (asyncio.QueueEmpty, asyncio.TimeoutError) as err:
304
+ raise Empty() from err
@@ -0,0 +1,202 @@
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
+
15
+ from __future__ import annotations
16
+
17
+ from argparse import ArgumentParser
18
+ from argparse import Namespace
19
+ import contextlib
20
+ import difflib
21
+ import os
22
+ from pathlib import Path
23
+ import shlex
24
+ import shutil
25
+ import subprocess
26
+ import sys
27
+ from typing import Any
28
+ from typing import Dict
29
+ from typing import Iterator
30
+ from typing import Optional
31
+ from typing import Union
32
+
33
+ from . import compat
34
+
35
+
36
+ class code_writer_cmd:
37
+ parser: ArgumentParser
38
+ args: Namespace
39
+ suppress_output: bool
40
+ diffs_detected: bool
41
+ source_root: Path
42
+ pyproject_toml_path: Path
43
+
44
+ def __init__(self, tool_script: str):
45
+ self.source_root = Path(tool_script).parent.parent
46
+ self.pyproject_toml_path = self.source_root / Path("pyproject.toml")
47
+ assert self.pyproject_toml_path.exists()
48
+
49
+ self.parser = ArgumentParser()
50
+ self.parser.add_argument(
51
+ "--stdout",
52
+ action="store_true",
53
+ help="Write to stdout instead of saving to file",
54
+ )
55
+ self.parser.add_argument(
56
+ "-c",
57
+ "--check",
58
+ help="Don't write the files back, just return the "
59
+ "status. Return code 0 means nothing would change. "
60
+ "Return code 1 means some files would be reformatted",
61
+ action="store_true",
62
+ )
63
+
64
+ def run_zimports(self, tempfile: str) -> None:
65
+ self._run_console_script(
66
+ str(tempfile),
67
+ {
68
+ "entrypoint": "zimports",
69
+ "options": f"--toml-config {self.pyproject_toml_path}",
70
+ },
71
+ )
72
+
73
+ def run_black(self, tempfile: str) -> None:
74
+ self._run_console_script(
75
+ str(tempfile),
76
+ {
77
+ "entrypoint": "black",
78
+ "options": f"--config {self.pyproject_toml_path}",
79
+ },
80
+ )
81
+
82
+ def _run_console_script(self, path: str, options: Dict[str, Any]) -> None:
83
+ """Run a Python console application from within the process.
84
+
85
+ Used for black, zimports
86
+
87
+ """
88
+
89
+ is_posix = os.name == "posix"
90
+
91
+ entrypoint_name = options["entrypoint"]
92
+
93
+ for entry in compat.importlib_metadata_get("console_scripts"):
94
+ if entry.name == entrypoint_name:
95
+ impl = entry
96
+ break
97
+ else:
98
+ raise Exception(
99
+ f"Could not find entrypoint console_scripts.{entrypoint_name}"
100
+ )
101
+ cmdline_options_str = options.get("options", "")
102
+ cmdline_options_list = shlex.split(
103
+ cmdline_options_str, posix=is_posix
104
+ ) + [path]
105
+
106
+ kw: Dict[str, Any] = {}
107
+ if self.suppress_output:
108
+ kw["stdout"] = kw["stderr"] = subprocess.DEVNULL
109
+
110
+ subprocess.run(
111
+ [
112
+ sys.executable,
113
+ "-c",
114
+ "import %s; %s.%s()" % (impl.module, impl.module, impl.attr),
115
+ ]
116
+ + cmdline_options_list,
117
+ cwd=str(self.source_root),
118
+ **kw,
119
+ )
120
+
121
+ def write_status(self, *text: str) -> None:
122
+ if not self.suppress_output:
123
+ sys.stderr.write(" ".join(text))
124
+
125
+ def write_output_file_from_text(
126
+ self, text: str, destination_path: Union[str, Path]
127
+ ) -> None:
128
+ if self.args.check:
129
+ self._run_diff(destination_path, source=text)
130
+ elif self.args.stdout:
131
+ print(text)
132
+ else:
133
+ self.write_status(f"Writing {destination_path}...")
134
+ Path(destination_path).write_text(
135
+ text, encoding="utf-8", newline="\n"
136
+ )
137
+ self.write_status("done\n")
138
+
139
+ def write_output_file_from_tempfile(
140
+ self, tempfile: str, destination_path: str
141
+ ) -> None:
142
+ if self.args.check:
143
+ self._run_diff(destination_path, source_file=tempfile)
144
+ os.unlink(tempfile)
145
+ elif self.args.stdout:
146
+ with open(tempfile) as tf:
147
+ print(tf.read())
148
+ os.unlink(tempfile)
149
+ else:
150
+ self.write_status(f"Writing {destination_path}...")
151
+ shutil.move(tempfile, destination_path)
152
+ self.write_status("done\n")
153
+
154
+ def _run_diff(
155
+ self,
156
+ destination_path: Union[str, Path],
157
+ *,
158
+ source: Optional[str] = None,
159
+ source_file: Optional[str] = None,
160
+ ) -> None:
161
+ if source_file:
162
+ with open(source_file, encoding="utf-8") as tf:
163
+ source_lines = list(tf)
164
+ elif source is not None:
165
+ source_lines = source.splitlines(keepends=True)
166
+ else:
167
+ assert False, "source or source_file is required"
168
+
169
+ with open(destination_path, encoding="utf-8") as dp:
170
+ d = difflib.unified_diff(
171
+ list(dp),
172
+ source_lines,
173
+ fromfile=Path(destination_path).as_posix(),
174
+ tofile="<proposed changes>",
175
+ n=3,
176
+ lineterm="\n",
177
+ )
178
+ d_as_list = list(d)
179
+ if d_as_list:
180
+ self.diffs_detected = True
181
+ print("".join(d_as_list))
182
+
183
+ @contextlib.contextmanager
184
+ def add_arguments(self) -> Iterator[ArgumentParser]:
185
+ yield self.parser
186
+
187
+ @contextlib.contextmanager
188
+ def run_program(self) -> Iterator[None]:
189
+ self.args = self.parser.parse_args()
190
+ if self.args.check:
191
+ self.diffs_detected = False
192
+ self.suppress_output = True
193
+ elif self.args.stdout:
194
+ self.suppress_output = True
195
+ else:
196
+ self.suppress_output = False
197
+ yield
198
+
199
+ if self.args.check and self.diffs_detected:
200
+ sys.exit(1)
201
+ else:
202
+ sys.exit(0)