SQLAlchemy 2.1.0rc1__cp315-cp315-win_arm64.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_arm64.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp315-win_arm64.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +711 -0
  80. sqlalchemy/engine/_row_cy.cp315-win_arm64.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp315-win_arm64.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_arm64.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_arm64.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_arm64.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_arm64.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,188 @@
1
+ # inspection.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+
8
+ """The inspection module provides the :func:`_sa.inspect` function,
9
+ which delivers runtime information about a wide variety
10
+ of SQLAlchemy objects, both within the Core as well as the
11
+ ORM.
12
+
13
+ The :func:`_sa.inspect` function is the entry point to SQLAlchemy's
14
+ public API for viewing the configuration and construction
15
+ of in-memory objects. Depending on the type of object
16
+ passed to :func:`_sa.inspect`, the return value will either be
17
+ a related object which provides a known interface, or in many
18
+ cases it will return the object itself.
19
+
20
+ The rationale for :func:`_sa.inspect` is twofold. One is that
21
+ it replaces the need to be aware of a large variety of "information
22
+ getting" functions in SQLAlchemy, such as
23
+ :meth:`_reflection.Inspector.from_engine` (deprecated in 1.4),
24
+ :func:`.orm.attributes.instance_state`, :func:`_orm.class_mapper`,
25
+ and others. The other is that the return value of :func:`_sa.inspect`
26
+ is guaranteed to obey a documented API, thus allowing third party
27
+ tools which build on top of SQLAlchemy configurations to be constructed
28
+ in a forwards-compatible way.
29
+
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ from typing import Any
35
+ from typing import Callable
36
+ from typing import Dict
37
+ from typing import Generic
38
+ from typing import Literal
39
+ from typing import Optional
40
+ from typing import overload
41
+ from typing import Protocol
42
+ from typing import Type
43
+ from typing import TypeVar
44
+ from typing import Union
45
+
46
+ from . import exc
47
+
48
+ _T = TypeVar("_T", bound=Any)
49
+ _TCov = TypeVar("_TCov", bound=Any, covariant=True)
50
+ _F = TypeVar("_F", bound=Callable[..., Any])
51
+
52
+ _IN = TypeVar("_IN", bound=Any)
53
+
54
+ _registrars: Dict[type, Union[Literal[True], Callable[[Any], Any]]] = {}
55
+
56
+
57
+ class Inspectable(Generic[_T]):
58
+ """define a class as inspectable.
59
+
60
+ This allows typing to set up a linkage between an object that
61
+ can be inspected and the type of inspection it returns.
62
+
63
+ Unfortunately we cannot at the moment get all classes that are
64
+ returned by inspection to suit this interface as we get into
65
+ MRO issues.
66
+
67
+ """
68
+
69
+ __slots__ = ()
70
+
71
+
72
+ class _InspectableTypeProtocol(Protocol[_TCov]):
73
+ """a protocol defining a method that's used when a type (ie the class
74
+ itself) is passed to inspect().
75
+
76
+ """
77
+
78
+ def _sa_inspect_type(self) -> _TCov: ...
79
+
80
+
81
+ class _InspectableProtocol(Protocol[_TCov]):
82
+ """a protocol defining a method that's used when an instance is
83
+ passed to inspect().
84
+
85
+ """
86
+
87
+ def _sa_inspect_instance(self) -> _TCov: ...
88
+
89
+
90
+ @overload
91
+ def inspect(
92
+ subject: Type[_InspectableTypeProtocol[_IN]], raiseerr: bool = True
93
+ ) -> _IN: ...
94
+
95
+
96
+ @overload
97
+ def inspect(
98
+ subject: _InspectableProtocol[_IN], raiseerr: bool = True
99
+ ) -> _IN: ...
100
+
101
+
102
+ @overload
103
+ def inspect(subject: Inspectable[_IN], raiseerr: bool = True) -> _IN: ...
104
+
105
+
106
+ @overload
107
+ def inspect(subject: Any, raiseerr: Literal[False] = ...) -> Optional[Any]: ...
108
+
109
+
110
+ @overload
111
+ def inspect(subject: Any, raiseerr: bool = True) -> Any: ...
112
+
113
+
114
+ def inspect(subject: Any, raiseerr: bool = True) -> Any:
115
+ """Produce an inspection object for the given target.
116
+
117
+ The returned value in some cases may be the
118
+ same object as the one given, such as if a
119
+ :class:`_orm.Mapper` object is passed. In other
120
+ cases, it will be an instance of the registered
121
+ inspection type for the given object, such as
122
+ if an :class:`_engine.Engine` is passed, an
123
+ :class:`_reflection.Inspector` object is returned.
124
+
125
+ :param subject: the subject to be inspected.
126
+ :param raiseerr: When ``True``, if the given subject
127
+ does not
128
+ correspond to a known SQLAlchemy inspected type,
129
+ :class:`sqlalchemy.exc.NoInspectionAvailable`
130
+ is raised. If ``False``, ``None`` is returned.
131
+
132
+ """
133
+ type_ = type(subject)
134
+ for cls in type_.__mro__:
135
+ if cls in _registrars:
136
+ reg = _registrars.get(cls, None)
137
+ if reg is None:
138
+ continue
139
+ elif reg is True:
140
+ return subject
141
+ ret = reg(subject)
142
+ if ret is not None:
143
+ return ret
144
+ else:
145
+ reg = ret = None
146
+
147
+ if raiseerr and (reg is None or ret is None):
148
+ raise exc.NoInspectionAvailable(
149
+ "No inspection system is "
150
+ "available for object of type %s" % type_
151
+ )
152
+ return ret
153
+
154
+
155
+ def _inspects(
156
+ *types: Type[Any],
157
+ ) -> Callable[[_F], _F]:
158
+ def decorate(fn_or_cls: _F) -> _F:
159
+ for type_ in types:
160
+ if type_ in _registrars:
161
+ existing = _registrars[type_]
162
+ existing_name = getattr(existing, "__name__", None)
163
+ existing_module = getattr(existing, "__module__", None)
164
+
165
+ # allow a new version of the same function or class, that is,
166
+ # a module reload; compare name/module attributes because
167
+ # classes may define custom __eq__ behavior.
168
+ if (
169
+ existing_name != fn_or_cls.__name__
170
+ or existing_module != fn_or_cls.__module__
171
+ ):
172
+ raise AssertionError(
173
+ "Type %s is already registered" % type_
174
+ )
175
+ _registrars[type_] = fn_or_cls
176
+ return fn_or_cls
177
+
178
+ return decorate
179
+
180
+
181
+ _TT = TypeVar("_TT", bound="Type[Any]")
182
+
183
+
184
+ def _self_inspects(cls: _TT) -> _TT:
185
+ if cls in _registrars:
186
+ raise AssertionError("Type %s is already registered" % cls)
187
+ _registrars[cls] = True
188
+ return cls
sqlalchemy/log.py ADDED
@@ -0,0 +1,279 @@
1
+ # log.py
2
+ # Copyright (C) 2006-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ # Includes alterations by Vinay Sajip vinay_sajip@yahoo.co.uk
5
+ #
6
+ # This module is part of SQLAlchemy and is released under
7
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
8
+
9
+ """Logging control and utilities.
10
+
11
+ Control of logging for SA can be performed from the regular python logging
12
+ module. The regular dotted module namespace is used, starting at
13
+ 'sqlalchemy'. For class-level logging, the class name is appended.
14
+
15
+ The "echo" keyword parameter, available on SQLA :class:`_engine.Engine`
16
+ and :class:`_pool.Pool` objects, corresponds to a logger specific to that
17
+ instance only.
18
+
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import logging
24
+ import sys
25
+ from typing import Any
26
+ from typing import Literal
27
+ from typing import Optional
28
+ from typing import overload
29
+ from typing import Set
30
+ from typing import Type
31
+ from typing import TypeVar
32
+ from typing import Union
33
+
34
+ STACKLEVEL = True
35
+ STACKLEVEL_OFFSET = 2
36
+
37
+ _IT = TypeVar("_IT", bound="Identified")
38
+
39
+ _EchoFlagType = Union[None, bool, Literal["debug"]]
40
+
41
+ # set initial level to WARN. This so that
42
+ # log statements don't occur in the absence of explicit
43
+ # logging being enabled for 'sqlalchemy'.
44
+ rootlogger = logging.getLogger("sqlalchemy")
45
+ if rootlogger.level == logging.NOTSET:
46
+ rootlogger.setLevel(logging.WARNING)
47
+
48
+
49
+ def _add_default_handler(logger: logging.Logger) -> None:
50
+ handler = logging.StreamHandler(sys.stdout)
51
+ handler.setFormatter(
52
+ logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s")
53
+ )
54
+ logger.addHandler(handler)
55
+
56
+
57
+ _logged_classes: Set[Type[Identified]] = set()
58
+
59
+
60
+ def _qual_logger_name_for_cls(cls: Type[Identified]) -> str:
61
+ return (
62
+ getattr(cls, "_sqla_logger_namespace", None)
63
+ or cls.__module__ + "." + cls.__name__
64
+ )
65
+
66
+
67
+ def class_logger(cls: Type[_IT]) -> Type[_IT]:
68
+ logger = logging.getLogger(_qual_logger_name_for_cls(cls))
69
+ cls._should_log_debug = lambda self: logger.isEnabledFor( # type: ignore[method-assign] # noqa: E501
70
+ logging.DEBUG
71
+ )
72
+ cls._should_log_info = lambda self: logger.isEnabledFor( # type: ignore[method-assign] # noqa: E501
73
+ logging.INFO
74
+ )
75
+ cls.logger = logger
76
+ _logged_classes.add(cls)
77
+ return cls
78
+
79
+
80
+ _IdentifiedLoggerType = Union[logging.Logger, "InstanceLogger"]
81
+
82
+
83
+ class Identified:
84
+ __slots__ = ()
85
+
86
+ logging_name: Optional[str] = None
87
+
88
+ logger: _IdentifiedLoggerType
89
+
90
+ _echo: _EchoFlagType
91
+
92
+ def _should_log_debug(self) -> bool:
93
+ return self.logger.isEnabledFor(logging.DEBUG)
94
+
95
+ def _should_log_info(self) -> bool:
96
+ return self.logger.isEnabledFor(logging.INFO)
97
+
98
+
99
+ class InstanceLogger:
100
+ """A logger adapter (wrapper) for :class:`.Identified` subclasses.
101
+
102
+ This allows multiple instances (e.g. Engine or Pool instances)
103
+ to share a logger, but have its verbosity controlled on a
104
+ per-instance basis.
105
+
106
+ The basic functionality is to return a logging level
107
+ which is based on an instance's echo setting.
108
+
109
+ Default implementation is:
110
+
111
+ 'debug' -> logging.DEBUG
112
+ True -> logging.INFO
113
+ False -> Effective level of underlying logger (
114
+ logging.WARNING by default)
115
+ None -> same as False
116
+ """
117
+
118
+ # Map echo settings to logger levels
119
+ _echo_map = {
120
+ None: logging.NOTSET,
121
+ False: logging.NOTSET,
122
+ True: logging.INFO,
123
+ "debug": logging.DEBUG,
124
+ }
125
+
126
+ _echo: _EchoFlagType
127
+
128
+ __slots__ = ("echo", "logger")
129
+
130
+ def __init__(self, echo: _EchoFlagType, name: str):
131
+ self.echo = echo
132
+ self.logger = logging.getLogger(name)
133
+
134
+ # if echo flag is enabled and no handlers,
135
+ # add a handler to the list
136
+ if self._echo_map[echo] <= logging.INFO and not self.logger.handlers:
137
+ _add_default_handler(self.logger)
138
+
139
+ #
140
+ # Boilerplate convenience methods
141
+ #
142
+ def debug(self, msg: str, *args: Any, **kwargs: Any) -> None:
143
+ """Delegate a debug call to the underlying logger."""
144
+
145
+ self.log(logging.DEBUG, msg, *args, **kwargs)
146
+
147
+ def info(self, msg: str, *args: Any, **kwargs: Any) -> None:
148
+ """Delegate an info call to the underlying logger."""
149
+
150
+ self.log(logging.INFO, msg, *args, **kwargs)
151
+
152
+ def warning(self, msg: str, *args: Any, **kwargs: Any) -> None:
153
+ """Delegate a warning call to the underlying logger."""
154
+
155
+ self.log(logging.WARNING, msg, *args, **kwargs)
156
+
157
+ warn = warning
158
+
159
+ def error(self, msg: str, *args: Any, **kwargs: Any) -> None:
160
+ """
161
+ Delegate an error call to the underlying logger.
162
+ """
163
+ self.log(logging.ERROR, msg, *args, **kwargs)
164
+
165
+ def exception(self, msg: str, *args: Any, **kwargs: Any) -> None:
166
+ """Delegate an exception call to the underlying logger."""
167
+
168
+ kwargs["exc_info"] = 1
169
+ self.log(logging.ERROR, msg, *args, **kwargs)
170
+
171
+ def critical(self, msg: str, *args: Any, **kwargs: Any) -> None:
172
+ """Delegate a critical call to the underlying logger."""
173
+
174
+ self.log(logging.CRITICAL, msg, *args, **kwargs)
175
+
176
+ def log(self, level: int, msg: str, *args: Any, **kwargs: Any) -> None:
177
+ """Delegate a log call to the underlying logger.
178
+
179
+ The level here is determined by the echo
180
+ flag as well as that of the underlying logger, and
181
+ logger._log() is called directly.
182
+
183
+ """
184
+
185
+ # inline the logic from isEnabledFor(),
186
+ # getEffectiveLevel(), to avoid overhead.
187
+
188
+ if self.logger.manager.disable >= level:
189
+ return
190
+
191
+ selected_level = self._echo_map[self.echo]
192
+ if selected_level == logging.NOTSET:
193
+ selected_level = self.logger.getEffectiveLevel()
194
+
195
+ if level >= selected_level:
196
+ if STACKLEVEL:
197
+ kwargs["stacklevel"] = (
198
+ kwargs.get("stacklevel", 1) + STACKLEVEL_OFFSET
199
+ )
200
+
201
+ self.logger._log(level, msg, args, **kwargs)
202
+
203
+ def isEnabledFor(self, level: int) -> bool:
204
+ """Is this logger enabled for level 'level'?"""
205
+
206
+ if self.logger.manager.disable >= level:
207
+ return False
208
+ return level >= self.getEffectiveLevel()
209
+
210
+ def getEffectiveLevel(self) -> int:
211
+ """What's the effective level for this logger?"""
212
+
213
+ level = self._echo_map[self.echo]
214
+ if level == logging.NOTSET:
215
+ level = self.logger.getEffectiveLevel()
216
+ return level
217
+
218
+
219
+ def instance_logger(
220
+ instance: Identified, echoflag: _EchoFlagType = None
221
+ ) -> None:
222
+ """create a logger for an instance that implements :class:`.Identified`."""
223
+
224
+ if instance.logging_name:
225
+ name = "%s.%s" % (
226
+ _qual_logger_name_for_cls(instance.__class__),
227
+ instance.logging_name,
228
+ )
229
+ else:
230
+ name = _qual_logger_name_for_cls(instance.__class__)
231
+
232
+ instance._echo = echoflag # type: ignore[misc]
233
+
234
+ logger: Union[logging.Logger, InstanceLogger]
235
+
236
+ if echoflag in (False, None):
237
+ # if no echo setting or False, return a Logger directly,
238
+ # avoiding overhead of filtering
239
+ logger = logging.getLogger(name)
240
+ else:
241
+ # if a specified echo flag, return an EchoLogger,
242
+ # which checks the flag, overrides normal log
243
+ # levels by calling logger._log()
244
+ logger = InstanceLogger(echoflag, name)
245
+
246
+ instance.logger = logger # type: ignore[misc]
247
+
248
+
249
+ class echo_property:
250
+ __doc__ = """\
251
+ When ``True``, enable log output for this element.
252
+
253
+ This has the effect of setting the Python logging level for the namespace
254
+ of this element's class and object reference. A value of boolean ``True``
255
+ indicates that the loglevel ``logging.INFO`` will be set for the logger,
256
+ whereas the string value ``debug`` will set the loglevel to
257
+ ``logging.DEBUG``.
258
+ """
259
+
260
+ @overload
261
+ def __get__(
262
+ self, instance: Literal[None], owner: Type[Identified]
263
+ ) -> echo_property: ...
264
+
265
+ @overload
266
+ def __get__(
267
+ self, instance: Identified, owner: Type[Identified]
268
+ ) -> _EchoFlagType: ...
269
+
270
+ def __get__(
271
+ self, instance: Optional[Identified], owner: Type[Identified]
272
+ ) -> Union[echo_property, _EchoFlagType]:
273
+ if instance is None:
274
+ return self
275
+ else:
276
+ return instance._echo
277
+
278
+ def __set__(self, instance: Identified, value: _EchoFlagType) -> None:
279
+ instance_logger(instance, echoflag=value)
@@ -0,0 +1,176 @@
1
+ # orm/__init__.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+
8
+ """
9
+ Functional constructs for ORM configuration.
10
+
11
+ See the SQLAlchemy object relational tutorial and mapper configuration
12
+ documentation for an overview of how this module is used.
13
+
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from typing import Any
19
+
20
+ from . import exc as exc
21
+ from . import mapper as mapperlib
22
+ from . import strategy_options as strategy_options
23
+ from ._orm_constructors import _mapper_fn as mapper
24
+ from ._orm_constructors import aliased as aliased
25
+ from ._orm_constructors import backref as backref
26
+ from ._orm_constructors import clear_mappers as clear_mappers
27
+ from ._orm_constructors import column_property as column_property
28
+ from ._orm_constructors import composite as composite
29
+ from ._orm_constructors import contains_alias as contains_alias
30
+ from ._orm_constructors import create_session as create_session
31
+ from ._orm_constructors import deferred as deferred
32
+ from ._orm_constructors import dynamic_loader as dynamic_loader
33
+ from ._orm_constructors import join as join
34
+ from ._orm_constructors import mapped_column as mapped_column
35
+ from ._orm_constructors import orm_insert_sentinel as orm_insert_sentinel
36
+ from ._orm_constructors import outerjoin as outerjoin
37
+ from ._orm_constructors import query_expression as query_expression
38
+ from ._orm_constructors import relationship as relationship
39
+ from ._orm_constructors import synonym as synonym
40
+ from ._orm_constructors import with_loader_criteria as with_loader_criteria
41
+ from ._orm_constructors import with_polymorphic as with_polymorphic
42
+ from .attributes import AttributeEventToken as AttributeEventToken
43
+ from .attributes import InstrumentedAttribute as InstrumentedAttribute
44
+ from .attributes import QueryableAttribute as QueryableAttribute
45
+ from .base import class_mapper as class_mapper
46
+ from .base import DynamicMapped as DynamicMapped
47
+ from .base import InspectionAttrExtensionType as InspectionAttrExtensionType
48
+ from .base import LoaderCallableStatus as LoaderCallableStatus
49
+ from .base import Mapped as Mapped
50
+ from .base import NotExtension as NotExtension
51
+ from .base import ORMDescriptor as ORMDescriptor
52
+ from .base import PassiveFlag as PassiveFlag
53
+ from .base import SQLORMExpression as SQLORMExpression
54
+ from .base import WriteOnlyMapped as WriteOnlyMapped
55
+ from .context import FromStatement as FromStatement
56
+ from .context import QueryContext as QueryContext
57
+ from .decl_api import add_mapped_attribute as add_mapped_attribute
58
+ from .decl_api import as_declarative as as_declarative
59
+ from .decl_api import as_typed_table as as_typed_table
60
+ from .decl_api import declarative_base as declarative_base
61
+ from .decl_api import declarative_mixin as declarative_mixin
62
+ from .decl_api import DeclarativeBase as DeclarativeBase
63
+ from .decl_api import DeclarativeBaseNoMeta as DeclarativeBaseNoMeta
64
+ from .decl_api import DeclarativeMeta as DeclarativeMeta
65
+ from .decl_api import declared_attr as declared_attr
66
+ from .decl_api import has_inherited_table as has_inherited_table
67
+ from .decl_api import mapped_as_dataclass as mapped_as_dataclass
68
+ from .decl_api import MappedAsDataclass as MappedAsDataclass
69
+ from .decl_api import registry as registry
70
+ from .decl_api import synonym_for as synonym_for
71
+ from .decl_api import TypeResolve as TypeResolve
72
+ from .decl_api import unmapped_dataclass as unmapped_dataclass
73
+ from .decl_base import MappedClassProtocol as MappedClassProtocol
74
+ from .descriptor_props import Composite as Composite
75
+ from .descriptor_props import CompositeProperty as CompositeProperty
76
+ from .descriptor_props import Synonym as Synonym
77
+ from .descriptor_props import SynonymProperty as SynonymProperty
78
+ from .dynamic import AppenderQuery as AppenderQuery
79
+ from .events import AttributeEvents as AttributeEvents
80
+ from .events import InstanceEvents as InstanceEvents
81
+ from .events import InstrumentationEvents as InstrumentationEvents
82
+ from .events import MapperEvents as MapperEvents
83
+ from .events import QueryEvents as QueryEvents
84
+ from .events import RegistryEvents as RegistryEvents
85
+ from .events import SessionEvents as SessionEvents
86
+ from .identity import IdentityMap as IdentityMap
87
+ from .instrumentation import ClassManager as ClassManager
88
+ from .interfaces import EXT_CONTINUE as EXT_CONTINUE
89
+ from .interfaces import EXT_SKIP as EXT_SKIP
90
+ from .interfaces import EXT_STOP as EXT_STOP
91
+ from .interfaces import InspectionAttr as InspectionAttr
92
+ from .interfaces import InspectionAttrInfo as InspectionAttrInfo
93
+ from .interfaces import MANYTOMANY as MANYTOMANY
94
+ from .interfaces import MANYTOONE as MANYTOONE
95
+ from .interfaces import MapperProperty as MapperProperty
96
+ from .interfaces import NO_KEY as NO_KEY
97
+ from .interfaces import NO_VALUE as NO_VALUE
98
+ from .interfaces import ONETOMANY as ONETOMANY
99
+ from .interfaces import PropComparator as PropComparator
100
+ from .interfaces import RelationshipDirection as RelationshipDirection
101
+ from .interfaces import UserDefinedOption as UserDefinedOption
102
+ from .loading import merge_frozen_result as merge_frozen_result
103
+ from .loading import merge_result as merge_result
104
+ from .mapped_collection import attribute_keyed_dict as attribute_keyed_dict
105
+ from .mapped_collection import (
106
+ attribute_mapped_collection as attribute_mapped_collection,
107
+ )
108
+ from .mapped_collection import column_keyed_dict as column_keyed_dict
109
+ from .mapped_collection import (
110
+ column_mapped_collection as column_mapped_collection,
111
+ )
112
+ from .mapped_collection import keyfunc_mapping as keyfunc_mapping
113
+ from .mapped_collection import KeyFuncDict as KeyFuncDict
114
+ from .mapped_collection import mapped_collection as mapped_collection
115
+ from .mapped_collection import MappedCollection as MappedCollection
116
+ from .mapper import configure_mappers as configure_mappers
117
+ from .mapper import Mapper as Mapper
118
+ from .mapper import reconstructor as reconstructor
119
+ from .mapper import validates as validates
120
+ from .properties import ColumnProperty as ColumnProperty
121
+ from .properties import MappedColumn as MappedColumn
122
+ from .properties import MappedSQLExpression as MappedSQLExpression
123
+ from .query import AliasOption as AliasOption
124
+ from .query import Query as Query
125
+ from .relationships import foreign as foreign
126
+ from .relationships import Relationship as Relationship
127
+ from .relationships import RelationshipProperty as RelationshipProperty
128
+ from .relationships import remote as remote
129
+ from .scoping import QueryPropertyDescriptor as QueryPropertyDescriptor
130
+ from .scoping import scoped_session as scoped_session
131
+ from .session import close_all_sessions as close_all_sessions
132
+ from .session import make_transient as make_transient
133
+ from .session import make_transient_to_detached as make_transient_to_detached
134
+ from .session import object_session as object_session
135
+ from .session import ORMExecuteState as ORMExecuteState
136
+ from .session import Session as Session
137
+ from .session import sessionmaker as sessionmaker
138
+ from .session import SessionTransaction as SessionTransaction
139
+ from .session import SessionTransactionOrigin as SessionTransactionOrigin
140
+ from .state import AttributeState as AttributeState
141
+ from .state import InstanceState as InstanceState
142
+ from .strategy_options import contains_eager as contains_eager
143
+ from .strategy_options import defaultload as defaultload
144
+ from .strategy_options import defer as defer
145
+ from .strategy_options import immediateload as immediateload
146
+ from .strategy_options import joinedload as joinedload
147
+ from .strategy_options import lazyload as lazyload
148
+ from .strategy_options import Load as Load
149
+ from .strategy_options import load_only as load_only
150
+ from .strategy_options import noload as noload
151
+ from .strategy_options import raiseload as raiseload
152
+ from .strategy_options import selectin_polymorphic as selectin_polymorphic
153
+ from .strategy_options import selectinload as selectinload
154
+ from .strategy_options import subqueryload as subqueryload
155
+ from .strategy_options import undefer as undefer
156
+ from .strategy_options import undefer_group as undefer_group
157
+ from .strategy_options import with_expression as with_expression
158
+ from .unitofwork import UOWTransaction as UOWTransaction
159
+ from .util import Bundle as Bundle
160
+ from .util import CascadeOptions as CascadeOptions
161
+ from .util import DictBundle as DictBundle
162
+ from .util import LoaderCriteriaOption as LoaderCriteriaOption
163
+ from .util import object_mapper as object_mapper
164
+ from .util import polymorphic_union as polymorphic_union
165
+ from .util import was_deleted as was_deleted
166
+ from .util import with_parent as with_parent
167
+ from .writeonly import WriteOnlyCollection as WriteOnlyCollection
168
+ from .. import util as _sa_util
169
+
170
+
171
+ def __go(lcls: Any) -> None:
172
+ _sa_util.preloaded.import_prefix("sqlalchemy.orm")
173
+ _sa_util.preloaded.import_prefix("sqlalchemy.ext")
174
+
175
+
176
+ __go(locals())