SQLAlchemy 2.1.0b2__cp313-cp313t-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 (270) hide show
  1. sqlalchemy/__init__.py +298 -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 +250 -0
  6. sqlalchemy/dialects/__init__.py +62 -0
  7. sqlalchemy/dialects/_typing.py +30 -0
  8. sqlalchemy/dialects/mssql/__init__.py +89 -0
  9. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  10. sqlalchemy/dialects/mssql/base.py +4166 -0
  11. sqlalchemy/dialects/mssql/information_schema.py +285 -0
  12. sqlalchemy/dialects/mssql/json.py +140 -0
  13. sqlalchemy/dialects/mssql/mssqlpython.py +220 -0
  14. sqlalchemy/dialects/mssql/provision.py +196 -0
  15. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  16. sqlalchemy/dialects/mssql/pyodbc.py +698 -0
  17. sqlalchemy/dialects/mysql/__init__.py +106 -0
  18. sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
  19. sqlalchemy/dialects/mysql/aiomysql.py +226 -0
  20. sqlalchemy/dialects/mysql/asyncmy.py +214 -0
  21. sqlalchemy/dialects/mysql/base.py +3877 -0
  22. sqlalchemy/dialects/mysql/cymysql.py +106 -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 +330 -0
  29. sqlalchemy/dialects/mysql/mysqlconnector.py +296 -0
  30. sqlalchemy/dialects/mysql/mysqldb.py +312 -0
  31. sqlalchemy/dialects/mysql/provision.py +153 -0
  32. sqlalchemy/dialects/mysql/pymysql.py +157 -0
  33. sqlalchemy/dialects/mysql/pyodbc.py +156 -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 +3977 -0
  39. sqlalchemy/dialects/oracle/cx_oracle.py +1601 -0
  40. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  41. sqlalchemy/dialects/oracle/json.py +158 -0
  42. sqlalchemy/dialects/oracle/oracledb.py +909 -0
  43. sqlalchemy/dialects/oracle/provision.py +288 -0
  44. sqlalchemy/dialects/oracle/types.py +367 -0
  45. sqlalchemy/dialects/oracle/vector.py +368 -0
  46. sqlalchemy/dialects/postgresql/__init__.py +171 -0
  47. sqlalchemy/dialects/postgresql/_psycopg_common.py +229 -0
  48. sqlalchemy/dialects/postgresql/array.py +534 -0
  49. sqlalchemy/dialects/postgresql/asyncpg.py +1323 -0
  50. sqlalchemy/dialects/postgresql/base.py +5789 -0
  51. sqlalchemy/dialects/postgresql/bitstring.py +327 -0
  52. sqlalchemy/dialects/postgresql/dml.py +360 -0
  53. sqlalchemy/dialects/postgresql/ext.py +593 -0
  54. sqlalchemy/dialects/postgresql/hstore.py +423 -0
  55. sqlalchemy/dialects/postgresql/json.py +408 -0
  56. sqlalchemy/dialects/postgresql/named_types.py +521 -0
  57. sqlalchemy/dialects/postgresql/operators.py +130 -0
  58. sqlalchemy/dialects/postgresql/pg8000.py +670 -0
  59. sqlalchemy/dialects/postgresql/pg_catalog.py +344 -0
  60. sqlalchemy/dialects/postgresql/provision.py +184 -0
  61. sqlalchemy/dialects/postgresql/psycopg.py +799 -0
  62. sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
  63. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  64. sqlalchemy/dialects/postgresql/ranges.py +1002 -0
  65. sqlalchemy/dialects/postgresql/types.py +388 -0
  66. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  67. sqlalchemy/dialects/sqlite/aiosqlite.py +321 -0
  68. sqlalchemy/dialects/sqlite/base.py +3063 -0
  69. sqlalchemy/dialects/sqlite/dml.py +279 -0
  70. sqlalchemy/dialects/sqlite/json.py +100 -0
  71. sqlalchemy/dialects/sqlite/provision.py +229 -0
  72. sqlalchemy/dialects/sqlite/pysqlcipher.py +161 -0
  73. sqlalchemy/dialects/sqlite/pysqlite.py +754 -0
  74. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  75. sqlalchemy/engine/__init__.py +62 -0
  76. sqlalchemy/engine/_processors_cy.cp313t-win_arm64.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp313t-win_arm64.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +633 -0
  80. sqlalchemy/engine/_row_cy.cp313t-win_arm64.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp313t-win_arm64.pyd +0 -0
  83. sqlalchemy/engine/_util_cy.py +136 -0
  84. sqlalchemy/engine/base.py +3354 -0
  85. sqlalchemy/engine/characteristics.py +155 -0
  86. sqlalchemy/engine/create.py +877 -0
  87. sqlalchemy/engine/cursor.py +2421 -0
  88. sqlalchemy/engine/default.py +2402 -0
  89. sqlalchemy/engine/events.py +965 -0
  90. sqlalchemy/engine/interfaces.py +3495 -0
  91. sqlalchemy/engine/mock.py +134 -0
  92. sqlalchemy/engine/processors.py +82 -0
  93. sqlalchemy/engine/reflection.py +2100 -0
  94. sqlalchemy/engine/result.py +1966 -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 +156 -0
  99. sqlalchemy/event/__init__.py +26 -0
  100. sqlalchemy/event/api.py +220 -0
  101. sqlalchemy/event/attr.py +674 -0
  102. sqlalchemy/event/base.py +472 -0
  103. sqlalchemy/event/legacy.py +258 -0
  104. sqlalchemy/event/registry.py +390 -0
  105. sqlalchemy/events.py +17 -0
  106. sqlalchemy/exc.py +922 -0
  107. sqlalchemy/ext/__init__.py +11 -0
  108. sqlalchemy/ext/associationproxy.py +2072 -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 +2007 -0
  116. sqlalchemy/ext/automap.py +1701 -0
  117. sqlalchemy/ext/baked.py +559 -0
  118. sqlalchemy/ext/compiler.py +600 -0
  119. sqlalchemy/ext/declarative/__init__.py +65 -0
  120. sqlalchemy/ext/declarative/extensions.py +560 -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 +439 -0
  127. sqlalchemy/ext/serializer.py +185 -0
  128. sqlalchemy/future/__init__.py +16 -0
  129. sqlalchemy/future/engine.py +15 -0
  130. sqlalchemy/inspection.py +174 -0
  131. sqlalchemy/log.py +283 -0
  132. sqlalchemy/orm/__init__.py +176 -0
  133. sqlalchemy/orm/_orm_constructors.py +2694 -0
  134. sqlalchemy/orm/_typing.py +179 -0
  135. sqlalchemy/orm/attributes.py +2868 -0
  136. sqlalchemy/orm/base.py +976 -0
  137. sqlalchemy/orm/bulk_persistence.py +2152 -0
  138. sqlalchemy/orm/clsregistry.py +582 -0
  139. sqlalchemy/orm/collections.py +1568 -0
  140. sqlalchemy/orm/context.py +3471 -0
  141. sqlalchemy/orm/decl_api.py +2280 -0
  142. sqlalchemy/orm/decl_base.py +2309 -0
  143. sqlalchemy/orm/dependency.py +1306 -0
  144. sqlalchemy/orm/descriptor_props.py +1183 -0
  145. sqlalchemy/orm/dynamic.py +307 -0
  146. sqlalchemy/orm/evaluator.py +379 -0
  147. sqlalchemy/orm/events.py +3386 -0
  148. sqlalchemy/orm/exc.py +237 -0
  149. sqlalchemy/orm/identity.py +302 -0
  150. sqlalchemy/orm/instrumentation.py +746 -0
  151. sqlalchemy/orm/interfaces.py +1589 -0
  152. sqlalchemy/orm/loading.py +1684 -0
  153. sqlalchemy/orm/mapped_collection.py +557 -0
  154. sqlalchemy/orm/mapper.py +4411 -0
  155. sqlalchemy/orm/path_registry.py +829 -0
  156. sqlalchemy/orm/persistence.py +1789 -0
  157. sqlalchemy/orm/properties.py +973 -0
  158. sqlalchemy/orm/query.py +3528 -0
  159. sqlalchemy/orm/relationships.py +3570 -0
  160. sqlalchemy/orm/scoping.py +2232 -0
  161. sqlalchemy/orm/session.py +5403 -0
  162. sqlalchemy/orm/state.py +1175 -0
  163. sqlalchemy/orm/state_changes.py +196 -0
  164. sqlalchemy/orm/strategies.py +3492 -0
  165. sqlalchemy/orm/strategy_options.py +2562 -0
  166. sqlalchemy/orm/sync.py +164 -0
  167. sqlalchemy/orm/unitofwork.py +798 -0
  168. sqlalchemy/orm/util.py +2438 -0
  169. sqlalchemy/orm/writeonly.py +694 -0
  170. sqlalchemy/pool/__init__.py +41 -0
  171. sqlalchemy/pool/base.py +1522 -0
  172. sqlalchemy/pool/events.py +375 -0
  173. sqlalchemy/pool/impl.py +582 -0
  174. sqlalchemy/py.typed +0 -0
  175. sqlalchemy/schema.py +74 -0
  176. sqlalchemy/sql/__init__.py +156 -0
  177. sqlalchemy/sql/_annotated_cols.py +397 -0
  178. sqlalchemy/sql/_dml_constructors.py +132 -0
  179. sqlalchemy/sql/_elements_constructors.py +2164 -0
  180. sqlalchemy/sql/_orm_types.py +20 -0
  181. sqlalchemy/sql/_selectable_constructors.py +840 -0
  182. sqlalchemy/sql/_typing.py +487 -0
  183. sqlalchemy/sql/_util_cy.cp313t-win_arm64.pyd +0 -0
  184. sqlalchemy/sql/_util_cy.py +127 -0
  185. sqlalchemy/sql/annotation.py +590 -0
  186. sqlalchemy/sql/base.py +2699 -0
  187. sqlalchemy/sql/cache_key.py +1066 -0
  188. sqlalchemy/sql/coercions.py +1373 -0
  189. sqlalchemy/sql/compiler.py +8327 -0
  190. sqlalchemy/sql/crud.py +1815 -0
  191. sqlalchemy/sql/ddl.py +1928 -0
  192. sqlalchemy/sql/default_comparator.py +654 -0
  193. sqlalchemy/sql/dml.py +1977 -0
  194. sqlalchemy/sql/elements.py +6033 -0
  195. sqlalchemy/sql/events.py +458 -0
  196. sqlalchemy/sql/expression.py +172 -0
  197. sqlalchemy/sql/functions.py +2305 -0
  198. sqlalchemy/sql/lambdas.py +1443 -0
  199. sqlalchemy/sql/naming.py +209 -0
  200. sqlalchemy/sql/operators.py +2897 -0
  201. sqlalchemy/sql/roles.py +332 -0
  202. sqlalchemy/sql/schema.py +6703 -0
  203. sqlalchemy/sql/selectable.py +7553 -0
  204. sqlalchemy/sql/sqltypes.py +4093 -0
  205. sqlalchemy/sql/traversals.py +1042 -0
  206. sqlalchemy/sql/type_api.py +2446 -0
  207. sqlalchemy/sql/util.py +1495 -0
  208. sqlalchemy/sql/visitors.py +1157 -0
  209. sqlalchemy/testing/__init__.py +96 -0
  210. sqlalchemy/testing/assertions.py +1007 -0
  211. sqlalchemy/testing/assertsql.py +519 -0
  212. sqlalchemy/testing/asyncio.py +128 -0
  213. sqlalchemy/testing/config.py +440 -0
  214. sqlalchemy/testing/engines.py +483 -0
  215. sqlalchemy/testing/entities.py +117 -0
  216. sqlalchemy/testing/exclusions.py +476 -0
  217. sqlalchemy/testing/fixtures/__init__.py +30 -0
  218. sqlalchemy/testing/fixtures/base.py +384 -0
  219. sqlalchemy/testing/fixtures/mypy.py +247 -0
  220. sqlalchemy/testing/fixtures/orm.py +227 -0
  221. sqlalchemy/testing/fixtures/sql.py +538 -0
  222. sqlalchemy/testing/pickleable.py +155 -0
  223. sqlalchemy/testing/plugin/__init__.py +6 -0
  224. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  225. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  226. sqlalchemy/testing/plugin/pytestplugin.py +892 -0
  227. sqlalchemy/testing/profiling.py +329 -0
  228. sqlalchemy/testing/provision.py +613 -0
  229. sqlalchemy/testing/requirements.py +1978 -0
  230. sqlalchemy/testing/schema.py +198 -0
  231. sqlalchemy/testing/suite/__init__.py +19 -0
  232. sqlalchemy/testing/suite/test_cte.py +237 -0
  233. sqlalchemy/testing/suite/test_ddl.py +420 -0
  234. sqlalchemy/testing/suite/test_dialect.py +776 -0
  235. sqlalchemy/testing/suite/test_insert.py +630 -0
  236. sqlalchemy/testing/suite/test_reflection.py +3557 -0
  237. sqlalchemy/testing/suite/test_results.py +660 -0
  238. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  239. sqlalchemy/testing/suite/test_select.py +2112 -0
  240. sqlalchemy/testing/suite/test_sequence.py +317 -0
  241. sqlalchemy/testing/suite/test_table_via_select.py +686 -0
  242. sqlalchemy/testing/suite/test_types.py +2271 -0
  243. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  244. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  245. sqlalchemy/testing/util.py +535 -0
  246. sqlalchemy/testing/warnings.py +52 -0
  247. sqlalchemy/types.py +76 -0
  248. sqlalchemy/util/__init__.py +158 -0
  249. sqlalchemy/util/_collections.py +688 -0
  250. sqlalchemy/util/_collections_cy.cp313t-win_arm64.pyd +0 -0
  251. sqlalchemy/util/_collections_cy.pxd +8 -0
  252. sqlalchemy/util/_collections_cy.py +516 -0
  253. sqlalchemy/util/_has_cython.py +46 -0
  254. sqlalchemy/util/_immutabledict_cy.cp313t-win_arm64.pyd +0 -0
  255. sqlalchemy/util/_immutabledict_cy.py +240 -0
  256. sqlalchemy/util/compat.py +299 -0
  257. sqlalchemy/util/concurrency.py +322 -0
  258. sqlalchemy/util/cython.py +79 -0
  259. sqlalchemy/util/deprecations.py +401 -0
  260. sqlalchemy/util/langhelpers.py +2320 -0
  261. sqlalchemy/util/preloaded.py +152 -0
  262. sqlalchemy/util/queue.py +304 -0
  263. sqlalchemy/util/tool_support.py +201 -0
  264. sqlalchemy/util/topological.py +120 -0
  265. sqlalchemy/util/typing.py +711 -0
  266. sqlalchemy-2.1.0b2.dist-info/METADATA +269 -0
  267. sqlalchemy-2.1.0b2.dist-info/RECORD +270 -0
  268. sqlalchemy-2.1.0b2.dist-info/WHEEL +5 -0
  269. sqlalchemy-2.1.0b2.dist-info/licenses/LICENSE +19 -0
  270. sqlalchemy-2.1.0b2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,174 @@
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
+ from __future__ import annotations
32
+
33
+ from typing import Any
34
+ from typing import Callable
35
+ from typing import Dict
36
+ from typing import Generic
37
+ from typing import Literal
38
+ from typing import Optional
39
+ from typing import overload
40
+ from typing import Protocol
41
+ from typing import Type
42
+ from typing import TypeVar
43
+ from typing import Union
44
+
45
+ from . import exc
46
+
47
+ _T = TypeVar("_T", bound=Any)
48
+ _TCov = TypeVar("_TCov", bound=Any, covariant=True)
49
+ _F = TypeVar("_F", bound=Callable[..., Any])
50
+
51
+ _IN = TypeVar("_IN", bound=Any)
52
+
53
+ _registrars: Dict[type, Union[Literal[True], Callable[[Any], Any]]] = {}
54
+
55
+
56
+ class Inspectable(Generic[_T]):
57
+ """define a class as inspectable.
58
+
59
+ This allows typing to set up a linkage between an object that
60
+ can be inspected and the type of inspection it returns.
61
+
62
+ Unfortunately we cannot at the moment get all classes that are
63
+ returned by inspection to suit this interface as we get into
64
+ MRO issues.
65
+
66
+ """
67
+
68
+ __slots__ = ()
69
+
70
+
71
+ class _InspectableTypeProtocol(Protocol[_TCov]):
72
+ """a protocol defining a method that's used when a type (ie the class
73
+ itself) is passed to inspect().
74
+
75
+ """
76
+
77
+ def _sa_inspect_type(self) -> _TCov: ...
78
+
79
+
80
+ class _InspectableProtocol(Protocol[_TCov]):
81
+ """a protocol defining a method that's used when an instance is
82
+ passed to inspect().
83
+
84
+ """
85
+
86
+ def _sa_inspect_instance(self) -> _TCov: ...
87
+
88
+
89
+ @overload
90
+ def inspect(
91
+ subject: Type[_InspectableTypeProtocol[_IN]], raiseerr: bool = True
92
+ ) -> _IN: ...
93
+
94
+
95
+ @overload
96
+ def inspect(
97
+ subject: _InspectableProtocol[_IN], raiseerr: bool = True
98
+ ) -> _IN: ...
99
+
100
+
101
+ @overload
102
+ def inspect(subject: Inspectable[_IN], raiseerr: bool = True) -> _IN: ...
103
+
104
+
105
+ @overload
106
+ def inspect(subject: Any, raiseerr: Literal[False] = ...) -> Optional[Any]: ...
107
+
108
+
109
+ @overload
110
+ def inspect(subject: Any, raiseerr: bool = True) -> Any: ...
111
+
112
+
113
+ def inspect(subject: Any, raiseerr: bool = True) -> Any:
114
+ """Produce an inspection object for the given target.
115
+
116
+ The returned value in some cases may be the
117
+ same object as the one given, such as if a
118
+ :class:`_orm.Mapper` object is passed. In other
119
+ cases, it will be an instance of the registered
120
+ inspection type for the given object, such as
121
+ if an :class:`_engine.Engine` is passed, an
122
+ :class:`_reflection.Inspector` object is returned.
123
+
124
+ :param subject: the subject to be inspected.
125
+ :param raiseerr: When ``True``, if the given subject
126
+ does not
127
+ correspond to a known SQLAlchemy inspected type,
128
+ :class:`sqlalchemy.exc.NoInspectionAvailable`
129
+ is raised. If ``False``, ``None`` is returned.
130
+
131
+ """
132
+ type_ = type(subject)
133
+ for cls in type_.__mro__:
134
+ if cls in _registrars:
135
+ reg = _registrars.get(cls, None)
136
+ if reg is None:
137
+ continue
138
+ elif reg is True:
139
+ return subject
140
+ ret = reg(subject)
141
+ if ret is not None:
142
+ return ret
143
+ else:
144
+ reg = ret = None
145
+
146
+ if raiseerr and (reg is None or ret is None):
147
+ raise exc.NoInspectionAvailable(
148
+ "No inspection system is "
149
+ "available for object of type %s" % type_
150
+ )
151
+ return ret
152
+
153
+
154
+ def _inspects(
155
+ *types: Type[Any],
156
+ ) -> Callable[[_F], _F]:
157
+ def decorate(fn_or_cls: _F) -> _F:
158
+ for type_ in types:
159
+ if type_ in _registrars:
160
+ raise AssertionError("Type %s is already registered" % type_)
161
+ _registrars[type_] = fn_or_cls
162
+ return fn_or_cls
163
+
164
+ return decorate
165
+
166
+
167
+ _TT = TypeVar("_TT", bound="Type[Any]")
168
+
169
+
170
+ def _self_inspects(cls: _TT) -> _TT:
171
+ if cls in _registrars:
172
+ raise AssertionError("Type %s is already registered" % cls)
173
+ _registrars[cls] = True
174
+ return cls
sqlalchemy/log.py ADDED
@@ -0,0 +1,283 @@
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
+ from __future__ import annotations
21
+
22
+ import logging
23
+ import sys
24
+ from typing import Any
25
+ from typing import Literal
26
+ from typing import Optional
27
+ from typing import overload
28
+ from typing import Set
29
+ from typing import Type
30
+ from typing import TypeVar
31
+ from typing import Union
32
+
33
+ from .util import py311
34
+
35
+
36
+ STACKLEVEL = True
37
+ # needed as of py3.11.0b1
38
+ # #8019
39
+ STACKLEVEL_OFFSET = 2 if py311 else 1
40
+
41
+ _IT = TypeVar("_IT", bound="Identified")
42
+
43
+ _EchoFlagType = Union[None, bool, Literal["debug"]]
44
+
45
+ # set initial level to WARN. This so that
46
+ # log statements don't occur in the absence of explicit
47
+ # logging being enabled for 'sqlalchemy'.
48
+ rootlogger = logging.getLogger("sqlalchemy")
49
+ if rootlogger.level == logging.NOTSET:
50
+ rootlogger.setLevel(logging.WARN)
51
+
52
+
53
+ def _add_default_handler(logger: logging.Logger) -> None:
54
+ handler = logging.StreamHandler(sys.stdout)
55
+ handler.setFormatter(
56
+ logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s")
57
+ )
58
+ logger.addHandler(handler)
59
+
60
+
61
+ _logged_classes: Set[Type[Identified]] = set()
62
+
63
+
64
+ def _qual_logger_name_for_cls(cls: Type[Identified]) -> str:
65
+ return (
66
+ getattr(cls, "_sqla_logger_namespace", None)
67
+ or cls.__module__ + "." + cls.__name__
68
+ )
69
+
70
+
71
+ def class_logger(cls: Type[_IT]) -> Type[_IT]:
72
+ logger = logging.getLogger(_qual_logger_name_for_cls(cls))
73
+ cls._should_log_debug = lambda self: logger.isEnabledFor( # type: ignore[method-assign] # noqa: E501
74
+ logging.DEBUG
75
+ )
76
+ cls._should_log_info = lambda self: logger.isEnabledFor( # type: ignore[method-assign] # noqa: E501
77
+ logging.INFO
78
+ )
79
+ cls.logger = logger
80
+ _logged_classes.add(cls)
81
+ return cls
82
+
83
+
84
+ _IdentifiedLoggerType = Union[logging.Logger, "InstanceLogger"]
85
+
86
+
87
+ class Identified:
88
+ __slots__ = ()
89
+
90
+ logging_name: Optional[str] = None
91
+
92
+ logger: _IdentifiedLoggerType
93
+
94
+ _echo: _EchoFlagType
95
+
96
+ def _should_log_debug(self) -> bool:
97
+ return self.logger.isEnabledFor(logging.DEBUG)
98
+
99
+ def _should_log_info(self) -> bool:
100
+ return self.logger.isEnabledFor(logging.INFO)
101
+
102
+
103
+ class InstanceLogger:
104
+ """A logger adapter (wrapper) for :class:`.Identified` subclasses.
105
+
106
+ This allows multiple instances (e.g. Engine or Pool instances)
107
+ to share a logger, but have its verbosity controlled on a
108
+ per-instance basis.
109
+
110
+ The basic functionality is to return a logging level
111
+ which is based on an instance's echo setting.
112
+
113
+ Default implementation is:
114
+
115
+ 'debug' -> logging.DEBUG
116
+ True -> logging.INFO
117
+ False -> Effective level of underlying logger (
118
+ logging.WARNING by default)
119
+ None -> same as False
120
+ """
121
+
122
+ # Map echo settings to logger levels
123
+ _echo_map = {
124
+ None: logging.NOTSET,
125
+ False: logging.NOTSET,
126
+ True: logging.INFO,
127
+ "debug": logging.DEBUG,
128
+ }
129
+
130
+ _echo: _EchoFlagType
131
+
132
+ __slots__ = ("echo", "logger")
133
+
134
+ def __init__(self, echo: _EchoFlagType, name: str):
135
+ self.echo = echo
136
+ self.logger = logging.getLogger(name)
137
+
138
+ # if echo flag is enabled and no handlers,
139
+ # add a handler to the list
140
+ if self._echo_map[echo] <= logging.INFO and not self.logger.handlers:
141
+ _add_default_handler(self.logger)
142
+
143
+ #
144
+ # Boilerplate convenience methods
145
+ #
146
+ def debug(self, msg: str, *args: Any, **kwargs: Any) -> None:
147
+ """Delegate a debug call to the underlying logger."""
148
+
149
+ self.log(logging.DEBUG, msg, *args, **kwargs)
150
+
151
+ def info(self, msg: str, *args: Any, **kwargs: Any) -> None:
152
+ """Delegate an info call to the underlying logger."""
153
+
154
+ self.log(logging.INFO, msg, *args, **kwargs)
155
+
156
+ def warning(self, msg: str, *args: Any, **kwargs: Any) -> None:
157
+ """Delegate a warning call to the underlying logger."""
158
+
159
+ self.log(logging.WARNING, msg, *args, **kwargs)
160
+
161
+ warn = warning
162
+
163
+ def error(self, msg: str, *args: Any, **kwargs: Any) -> None:
164
+ """
165
+ Delegate an error call to the underlying logger.
166
+ """
167
+ self.log(logging.ERROR, msg, *args, **kwargs)
168
+
169
+ def exception(self, msg: str, *args: Any, **kwargs: Any) -> None:
170
+ """Delegate an exception call to the underlying logger."""
171
+
172
+ kwargs["exc_info"] = 1
173
+ self.log(logging.ERROR, msg, *args, **kwargs)
174
+
175
+ def critical(self, msg: str, *args: Any, **kwargs: Any) -> None:
176
+ """Delegate a critical call to the underlying logger."""
177
+
178
+ self.log(logging.CRITICAL, msg, *args, **kwargs)
179
+
180
+ def log(self, level: int, msg: str, *args: Any, **kwargs: Any) -> None:
181
+ """Delegate a log call to the underlying logger.
182
+
183
+ The level here is determined by the echo
184
+ flag as well as that of the underlying logger, and
185
+ logger._log() is called directly.
186
+
187
+ """
188
+
189
+ # inline the logic from isEnabledFor(),
190
+ # getEffectiveLevel(), to avoid overhead.
191
+
192
+ if self.logger.manager.disable >= level:
193
+ return
194
+
195
+ selected_level = self._echo_map[self.echo]
196
+ if selected_level == logging.NOTSET:
197
+ selected_level = self.logger.getEffectiveLevel()
198
+
199
+ if level >= selected_level:
200
+ if STACKLEVEL:
201
+ kwargs["stacklevel"] = (
202
+ kwargs.get("stacklevel", 1) + STACKLEVEL_OFFSET
203
+ )
204
+
205
+ self.logger._log(level, msg, args, **kwargs)
206
+
207
+ def isEnabledFor(self, level: int) -> bool:
208
+ """Is this logger enabled for level 'level'?"""
209
+
210
+ if self.logger.manager.disable >= level:
211
+ return False
212
+ return level >= self.getEffectiveLevel()
213
+
214
+ def getEffectiveLevel(self) -> int:
215
+ """What's the effective level for this logger?"""
216
+
217
+ level = self._echo_map[self.echo]
218
+ if level == logging.NOTSET:
219
+ level = self.logger.getEffectiveLevel()
220
+ return level
221
+
222
+
223
+ def instance_logger(
224
+ instance: Identified, echoflag: _EchoFlagType = None
225
+ ) -> None:
226
+ """create a logger for an instance that implements :class:`.Identified`."""
227
+
228
+ if instance.logging_name:
229
+ name = "%s.%s" % (
230
+ _qual_logger_name_for_cls(instance.__class__),
231
+ instance.logging_name,
232
+ )
233
+ else:
234
+ name = _qual_logger_name_for_cls(instance.__class__)
235
+
236
+ instance._echo = echoflag # type: ignore
237
+
238
+ logger: Union[logging.Logger, InstanceLogger]
239
+
240
+ if echoflag in (False, None):
241
+ # if no echo setting or False, return a Logger directly,
242
+ # avoiding overhead of filtering
243
+ logger = logging.getLogger(name)
244
+ else:
245
+ # if a specified echo flag, return an EchoLogger,
246
+ # which checks the flag, overrides normal log
247
+ # levels by calling logger._log()
248
+ logger = InstanceLogger(echoflag, name)
249
+
250
+ instance.logger = logger # type: ignore
251
+
252
+
253
+ class echo_property:
254
+ __doc__ = """\
255
+ When ``True``, enable log output for this element.
256
+
257
+ This has the effect of setting the Python logging level for the namespace
258
+ of this element's class and object reference. A value of boolean ``True``
259
+ indicates that the loglevel ``logging.INFO`` will be set for the logger,
260
+ whereas the string value ``debug`` will set the loglevel to
261
+ ``logging.DEBUG``.
262
+ """
263
+
264
+ @overload
265
+ def __get__(
266
+ self, instance: Literal[None], owner: Type[Identified]
267
+ ) -> echo_property: ...
268
+
269
+ @overload
270
+ def __get__(
271
+ self, instance: Identified, owner: Type[Identified]
272
+ ) -> _EchoFlagType: ...
273
+
274
+ def __get__(
275
+ self, instance: Optional[Identified], owner: Type[Identified]
276
+ ) -> Union[echo_property, _EchoFlagType]:
277
+ if instance is None:
278
+ return self
279
+ else:
280
+ return instance._echo
281
+
282
+ def __set__(self, instance: Identified, value: _EchoFlagType) -> None:
283
+ 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())