SQLAlchemy 2.0.47__cp313-cp313t-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. sqlalchemy/__init__.py +283 -0
  2. sqlalchemy/connectors/__init__.py +18 -0
  3. sqlalchemy/connectors/aioodbc.py +184 -0
  4. sqlalchemy/connectors/asyncio.py +429 -0
  5. sqlalchemy/connectors/pyodbc.py +250 -0
  6. sqlalchemy/cyextension/__init__.py +6 -0
  7. sqlalchemy/cyextension/collections.cp313t-win_amd64.pyd +0 -0
  8. sqlalchemy/cyextension/collections.pyx +409 -0
  9. sqlalchemy/cyextension/immutabledict.cp313t-win_amd64.pyd +0 -0
  10. sqlalchemy/cyextension/immutabledict.pxd +8 -0
  11. sqlalchemy/cyextension/immutabledict.pyx +133 -0
  12. sqlalchemy/cyextension/processors.cp313t-win_amd64.pyd +0 -0
  13. sqlalchemy/cyextension/processors.pyx +68 -0
  14. sqlalchemy/cyextension/resultproxy.cp313t-win_amd64.pyd +0 -0
  15. sqlalchemy/cyextension/resultproxy.pyx +102 -0
  16. sqlalchemy/cyextension/util.cp313t-win_amd64.pyd +0 -0
  17. sqlalchemy/cyextension/util.pyx +90 -0
  18. sqlalchemy/dialects/__init__.py +62 -0
  19. sqlalchemy/dialects/_typing.py +30 -0
  20. sqlalchemy/dialects/mssql/__init__.py +88 -0
  21. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  22. sqlalchemy/dialects/mssql/base.py +4093 -0
  23. sqlalchemy/dialects/mssql/information_schema.py +285 -0
  24. sqlalchemy/dialects/mssql/json.py +129 -0
  25. sqlalchemy/dialects/mssql/provision.py +185 -0
  26. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  27. sqlalchemy/dialects/mssql/pyodbc.py +760 -0
  28. sqlalchemy/dialects/mysql/__init__.py +104 -0
  29. sqlalchemy/dialects/mysql/aiomysql.py +250 -0
  30. sqlalchemy/dialects/mysql/asyncmy.py +231 -0
  31. sqlalchemy/dialects/mysql/base.py +3949 -0
  32. sqlalchemy/dialects/mysql/cymysql.py +106 -0
  33. sqlalchemy/dialects/mysql/dml.py +225 -0
  34. sqlalchemy/dialects/mysql/enumerated.py +282 -0
  35. sqlalchemy/dialects/mysql/expression.py +146 -0
  36. sqlalchemy/dialects/mysql/json.py +91 -0
  37. sqlalchemy/dialects/mysql/mariadb.py +72 -0
  38. sqlalchemy/dialects/mysql/mariadbconnector.py +322 -0
  39. sqlalchemy/dialects/mysql/mysqlconnector.py +302 -0
  40. sqlalchemy/dialects/mysql/mysqldb.py +314 -0
  41. sqlalchemy/dialects/mysql/provision.py +153 -0
  42. sqlalchemy/dialects/mysql/pymysql.py +158 -0
  43. sqlalchemy/dialects/mysql/pyodbc.py +157 -0
  44. sqlalchemy/dialects/mysql/reflection.py +727 -0
  45. sqlalchemy/dialects/mysql/reserved_words.py +570 -0
  46. sqlalchemy/dialects/mysql/types.py +835 -0
  47. sqlalchemy/dialects/oracle/__init__.py +81 -0
  48. sqlalchemy/dialects/oracle/base.py +3802 -0
  49. sqlalchemy/dialects/oracle/cx_oracle.py +1555 -0
  50. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  51. sqlalchemy/dialects/oracle/oracledb.py +941 -0
  52. sqlalchemy/dialects/oracle/provision.py +297 -0
  53. sqlalchemy/dialects/oracle/types.py +316 -0
  54. sqlalchemy/dialects/oracle/vector.py +365 -0
  55. sqlalchemy/dialects/postgresql/__init__.py +167 -0
  56. sqlalchemy/dialects/postgresql/_psycopg_common.py +189 -0
  57. sqlalchemy/dialects/postgresql/array.py +519 -0
  58. sqlalchemy/dialects/postgresql/asyncpg.py +1284 -0
  59. sqlalchemy/dialects/postgresql/base.py +5378 -0
  60. sqlalchemy/dialects/postgresql/dml.py +339 -0
  61. sqlalchemy/dialects/postgresql/ext.py +540 -0
  62. sqlalchemy/dialects/postgresql/hstore.py +406 -0
  63. sqlalchemy/dialects/postgresql/json.py +404 -0
  64. sqlalchemy/dialects/postgresql/named_types.py +524 -0
  65. sqlalchemy/dialects/postgresql/operators.py +129 -0
  66. sqlalchemy/dialects/postgresql/pg8000.py +669 -0
  67. sqlalchemy/dialects/postgresql/pg_catalog.py +326 -0
  68. sqlalchemy/dialects/postgresql/provision.py +183 -0
  69. sqlalchemy/dialects/postgresql/psycopg.py +862 -0
  70. sqlalchemy/dialects/postgresql/psycopg2.py +892 -0
  71. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  72. sqlalchemy/dialects/postgresql/ranges.py +1031 -0
  73. sqlalchemy/dialects/postgresql/types.py +313 -0
  74. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  75. sqlalchemy/dialects/sqlite/aiosqlite.py +482 -0
  76. sqlalchemy/dialects/sqlite/base.py +3056 -0
  77. sqlalchemy/dialects/sqlite/dml.py +263 -0
  78. sqlalchemy/dialects/sqlite/json.py +92 -0
  79. sqlalchemy/dialects/sqlite/provision.py +229 -0
  80. sqlalchemy/dialects/sqlite/pysqlcipher.py +157 -0
  81. sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
  82. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  83. sqlalchemy/engine/__init__.py +62 -0
  84. sqlalchemy/engine/_py_processors.py +136 -0
  85. sqlalchemy/engine/_py_row.py +128 -0
  86. sqlalchemy/engine/_py_util.py +74 -0
  87. sqlalchemy/engine/base.py +3390 -0
  88. sqlalchemy/engine/characteristics.py +155 -0
  89. sqlalchemy/engine/create.py +893 -0
  90. sqlalchemy/engine/cursor.py +2298 -0
  91. sqlalchemy/engine/default.py +2394 -0
  92. sqlalchemy/engine/events.py +965 -0
  93. sqlalchemy/engine/interfaces.py +3471 -0
  94. sqlalchemy/engine/mock.py +134 -0
  95. sqlalchemy/engine/processors.py +61 -0
  96. sqlalchemy/engine/reflection.py +2102 -0
  97. sqlalchemy/engine/result.py +2399 -0
  98. sqlalchemy/engine/row.py +400 -0
  99. sqlalchemy/engine/strategies.py +16 -0
  100. sqlalchemy/engine/url.py +924 -0
  101. sqlalchemy/engine/util.py +167 -0
  102. sqlalchemy/event/__init__.py +26 -0
  103. sqlalchemy/event/api.py +220 -0
  104. sqlalchemy/event/attr.py +676 -0
  105. sqlalchemy/event/base.py +472 -0
  106. sqlalchemy/event/legacy.py +258 -0
  107. sqlalchemy/event/registry.py +390 -0
  108. sqlalchemy/events.py +17 -0
  109. sqlalchemy/exc.py +832 -0
  110. sqlalchemy/ext/__init__.py +11 -0
  111. sqlalchemy/ext/associationproxy.py +2027 -0
  112. sqlalchemy/ext/asyncio/__init__.py +25 -0
  113. sqlalchemy/ext/asyncio/base.py +281 -0
  114. sqlalchemy/ext/asyncio/engine.py +1471 -0
  115. sqlalchemy/ext/asyncio/exc.py +21 -0
  116. sqlalchemy/ext/asyncio/result.py +965 -0
  117. sqlalchemy/ext/asyncio/scoping.py +1599 -0
  118. sqlalchemy/ext/asyncio/session.py +1947 -0
  119. sqlalchemy/ext/automap.py +1701 -0
  120. sqlalchemy/ext/baked.py +570 -0
  121. sqlalchemy/ext/compiler.py +600 -0
  122. sqlalchemy/ext/declarative/__init__.py +65 -0
  123. sqlalchemy/ext/declarative/extensions.py +564 -0
  124. sqlalchemy/ext/horizontal_shard.py +478 -0
  125. sqlalchemy/ext/hybrid.py +1535 -0
  126. sqlalchemy/ext/indexable.py +364 -0
  127. sqlalchemy/ext/instrumentation.py +450 -0
  128. sqlalchemy/ext/mutable.py +1085 -0
  129. sqlalchemy/ext/mypy/__init__.py +6 -0
  130. sqlalchemy/ext/mypy/apply.py +324 -0
  131. sqlalchemy/ext/mypy/decl_class.py +515 -0
  132. sqlalchemy/ext/mypy/infer.py +590 -0
  133. sqlalchemy/ext/mypy/names.py +335 -0
  134. sqlalchemy/ext/mypy/plugin.py +303 -0
  135. sqlalchemy/ext/mypy/util.py +357 -0
  136. sqlalchemy/ext/orderinglist.py +439 -0
  137. sqlalchemy/ext/serializer.py +185 -0
  138. sqlalchemy/future/__init__.py +16 -0
  139. sqlalchemy/future/engine.py +15 -0
  140. sqlalchemy/inspection.py +174 -0
  141. sqlalchemy/log.py +288 -0
  142. sqlalchemy/orm/__init__.py +171 -0
  143. sqlalchemy/orm/_orm_constructors.py +2661 -0
  144. sqlalchemy/orm/_typing.py +179 -0
  145. sqlalchemy/orm/attributes.py +2845 -0
  146. sqlalchemy/orm/base.py +971 -0
  147. sqlalchemy/orm/bulk_persistence.py +2135 -0
  148. sqlalchemy/orm/clsregistry.py +571 -0
  149. sqlalchemy/orm/collections.py +1627 -0
  150. sqlalchemy/orm/context.py +3334 -0
  151. sqlalchemy/orm/decl_api.py +2004 -0
  152. sqlalchemy/orm/decl_base.py +2192 -0
  153. sqlalchemy/orm/dependency.py +1302 -0
  154. sqlalchemy/orm/descriptor_props.py +1092 -0
  155. sqlalchemy/orm/dynamic.py +300 -0
  156. sqlalchemy/orm/evaluator.py +379 -0
  157. sqlalchemy/orm/events.py +3252 -0
  158. sqlalchemy/orm/exc.py +237 -0
  159. sqlalchemy/orm/identity.py +302 -0
  160. sqlalchemy/orm/instrumentation.py +754 -0
  161. sqlalchemy/orm/interfaces.py +1496 -0
  162. sqlalchemy/orm/loading.py +1686 -0
  163. sqlalchemy/orm/mapped_collection.py +557 -0
  164. sqlalchemy/orm/mapper.py +4444 -0
  165. sqlalchemy/orm/path_registry.py +809 -0
  166. sqlalchemy/orm/persistence.py +1788 -0
  167. sqlalchemy/orm/properties.py +935 -0
  168. sqlalchemy/orm/query.py +3459 -0
  169. sqlalchemy/orm/relationships.py +3508 -0
  170. sqlalchemy/orm/scoping.py +2148 -0
  171. sqlalchemy/orm/session.py +5280 -0
  172. sqlalchemy/orm/state.py +1168 -0
  173. sqlalchemy/orm/state_changes.py +196 -0
  174. sqlalchemy/orm/strategies.py +3470 -0
  175. sqlalchemy/orm/strategy_options.py +2568 -0
  176. sqlalchemy/orm/sync.py +164 -0
  177. sqlalchemy/orm/unitofwork.py +796 -0
  178. sqlalchemy/orm/util.py +2403 -0
  179. sqlalchemy/orm/writeonly.py +674 -0
  180. sqlalchemy/pool/__init__.py +44 -0
  181. sqlalchemy/pool/base.py +1524 -0
  182. sqlalchemy/pool/events.py +375 -0
  183. sqlalchemy/pool/impl.py +588 -0
  184. sqlalchemy/py.typed +0 -0
  185. sqlalchemy/schema.py +69 -0
  186. sqlalchemy/sql/__init__.py +145 -0
  187. sqlalchemy/sql/_dml_constructors.py +132 -0
  188. sqlalchemy/sql/_elements_constructors.py +1872 -0
  189. sqlalchemy/sql/_orm_types.py +20 -0
  190. sqlalchemy/sql/_py_util.py +75 -0
  191. sqlalchemy/sql/_selectable_constructors.py +763 -0
  192. sqlalchemy/sql/_typing.py +482 -0
  193. sqlalchemy/sql/annotation.py +587 -0
  194. sqlalchemy/sql/base.py +2293 -0
  195. sqlalchemy/sql/cache_key.py +1057 -0
  196. sqlalchemy/sql/coercions.py +1404 -0
  197. sqlalchemy/sql/compiler.py +8081 -0
  198. sqlalchemy/sql/crud.py +1752 -0
  199. sqlalchemy/sql/ddl.py +1444 -0
  200. sqlalchemy/sql/default_comparator.py +551 -0
  201. sqlalchemy/sql/dml.py +1850 -0
  202. sqlalchemy/sql/elements.py +5589 -0
  203. sqlalchemy/sql/events.py +458 -0
  204. sqlalchemy/sql/expression.py +159 -0
  205. sqlalchemy/sql/functions.py +2158 -0
  206. sqlalchemy/sql/lambdas.py +1442 -0
  207. sqlalchemy/sql/naming.py +209 -0
  208. sqlalchemy/sql/operators.py +2623 -0
  209. sqlalchemy/sql/roles.py +323 -0
  210. sqlalchemy/sql/schema.py +6222 -0
  211. sqlalchemy/sql/selectable.py +7265 -0
  212. sqlalchemy/sql/sqltypes.py +3930 -0
  213. sqlalchemy/sql/traversals.py +1024 -0
  214. sqlalchemy/sql/type_api.py +2368 -0
  215. sqlalchemy/sql/util.py +1485 -0
  216. sqlalchemy/sql/visitors.py +1164 -0
  217. sqlalchemy/testing/__init__.py +96 -0
  218. sqlalchemy/testing/assertions.py +994 -0
  219. sqlalchemy/testing/assertsql.py +520 -0
  220. sqlalchemy/testing/asyncio.py +135 -0
  221. sqlalchemy/testing/config.py +434 -0
  222. sqlalchemy/testing/engines.py +483 -0
  223. sqlalchemy/testing/entities.py +117 -0
  224. sqlalchemy/testing/exclusions.py +476 -0
  225. sqlalchemy/testing/fixtures/__init__.py +28 -0
  226. sqlalchemy/testing/fixtures/base.py +384 -0
  227. sqlalchemy/testing/fixtures/mypy.py +332 -0
  228. sqlalchemy/testing/fixtures/orm.py +227 -0
  229. sqlalchemy/testing/fixtures/sql.py +482 -0
  230. sqlalchemy/testing/pickleable.py +155 -0
  231. sqlalchemy/testing/plugin/__init__.py +6 -0
  232. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  233. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  234. sqlalchemy/testing/plugin/pytestplugin.py +892 -0
  235. sqlalchemy/testing/profiling.py +329 -0
  236. sqlalchemy/testing/provision.py +603 -0
  237. sqlalchemy/testing/requirements.py +1945 -0
  238. sqlalchemy/testing/schema.py +198 -0
  239. sqlalchemy/testing/suite/__init__.py +19 -0
  240. sqlalchemy/testing/suite/test_cte.py +237 -0
  241. sqlalchemy/testing/suite/test_ddl.py +389 -0
  242. sqlalchemy/testing/suite/test_deprecations.py +153 -0
  243. sqlalchemy/testing/suite/test_dialect.py +776 -0
  244. sqlalchemy/testing/suite/test_insert.py +630 -0
  245. sqlalchemy/testing/suite/test_reflection.py +3557 -0
  246. sqlalchemy/testing/suite/test_results.py +504 -0
  247. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  248. sqlalchemy/testing/suite/test_select.py +2010 -0
  249. sqlalchemy/testing/suite/test_sequence.py +317 -0
  250. sqlalchemy/testing/suite/test_types.py +2147 -0
  251. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  252. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  253. sqlalchemy/testing/util.py +535 -0
  254. sqlalchemy/testing/warnings.py +52 -0
  255. sqlalchemy/types.py +74 -0
  256. sqlalchemy/util/__init__.py +162 -0
  257. sqlalchemy/util/_collections.py +712 -0
  258. sqlalchemy/util/_concurrency_py3k.py +288 -0
  259. sqlalchemy/util/_has_cy.py +40 -0
  260. sqlalchemy/util/_py_collections.py +541 -0
  261. sqlalchemy/util/compat.py +421 -0
  262. sqlalchemy/util/concurrency.py +110 -0
  263. sqlalchemy/util/deprecations.py +401 -0
  264. sqlalchemy/util/langhelpers.py +2203 -0
  265. sqlalchemy/util/preloaded.py +150 -0
  266. sqlalchemy/util/queue.py +322 -0
  267. sqlalchemy/util/tool_support.py +201 -0
  268. sqlalchemy/util/topological.py +120 -0
  269. sqlalchemy/util/typing.py +734 -0
  270. sqlalchemy-2.0.47.dist-info/METADATA +243 -0
  271. sqlalchemy-2.0.47.dist-info/RECORD +274 -0
  272. sqlalchemy-2.0.47.dist-info/WHEEL +5 -0
  273. sqlalchemy-2.0.47.dist-info/licenses/LICENSE +19 -0
  274. sqlalchemy-2.0.47.dist-info/top_level.txt +1 -0
@@ -0,0 +1,357 @@
1
+ # ext/mypy/util.py
2
+ # Copyright (C) 2021-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
+ from __future__ import annotations
9
+
10
+ import re
11
+ from typing import Any
12
+ from typing import Iterable
13
+ from typing import Iterator
14
+ from typing import List
15
+ from typing import Optional
16
+ from typing import overload
17
+ from typing import Tuple
18
+ from typing import Type as TypingType
19
+ from typing import TypeVar
20
+ from typing import Union
21
+
22
+ from mypy import version
23
+ from mypy.messages import format_type as _mypy_format_type
24
+ from mypy.nodes import CallExpr
25
+ from mypy.nodes import ClassDef
26
+ from mypy.nodes import CLASSDEF_NO_INFO
27
+ from mypy.nodes import Context
28
+ from mypy.nodes import Expression
29
+ from mypy.nodes import FuncDef
30
+ from mypy.nodes import IfStmt
31
+ from mypy.nodes import JsonDict
32
+ from mypy.nodes import MemberExpr
33
+ from mypy.nodes import NameExpr
34
+ from mypy.nodes import Statement
35
+ from mypy.nodes import SymbolTableNode
36
+ from mypy.nodes import TypeAlias
37
+ from mypy.nodes import TypeInfo
38
+ from mypy.options import Options
39
+ from mypy.plugin import ClassDefContext
40
+ from mypy.plugin import DynamicClassDefContext
41
+ from mypy.plugin import SemanticAnalyzerPluginInterface
42
+ from mypy.plugins.common import deserialize_and_fixup_type
43
+ from mypy.typeops import map_type_from_supertype
44
+ from mypy.types import CallableType
45
+ from mypy.types import get_proper_type
46
+ from mypy.types import Instance
47
+ from mypy.types import NoneType
48
+ from mypy.types import Type
49
+ from mypy.types import TypeVarType
50
+ from mypy.types import UnboundType
51
+ from mypy.types import UnionType
52
+
53
+ _vers = tuple(
54
+ [int(x) for x in version.__version__.split(".") if re.match(r"^\d+$", x)]
55
+ )
56
+ mypy_14 = _vers >= (1, 4)
57
+
58
+
59
+ _TArgType = TypeVar("_TArgType", bound=Union[CallExpr, NameExpr])
60
+
61
+
62
+ class SQLAlchemyAttribute:
63
+ def __init__(
64
+ self,
65
+ name: str,
66
+ line: int,
67
+ column: int,
68
+ typ: Optional[Type],
69
+ info: TypeInfo,
70
+ ) -> None:
71
+ self.name = name
72
+ self.line = line
73
+ self.column = column
74
+ self.type = typ
75
+ self.info = info
76
+
77
+ def serialize(self) -> JsonDict:
78
+ assert self.type
79
+ return {
80
+ "name": self.name,
81
+ "line": self.line,
82
+ "column": self.column,
83
+ "type": serialize_type(self.type),
84
+ }
85
+
86
+ def expand_typevar_from_subtype(self, sub_type: TypeInfo) -> None:
87
+ """Expands type vars in the context of a subtype when an attribute is
88
+ inherited from a generic super type.
89
+ """
90
+ if not isinstance(self.type, TypeVarType):
91
+ return
92
+
93
+ self.type = map_type_from_supertype(self.type, sub_type, self.info)
94
+
95
+ @classmethod
96
+ def deserialize(
97
+ cls,
98
+ info: TypeInfo,
99
+ data: JsonDict,
100
+ api: SemanticAnalyzerPluginInterface,
101
+ ) -> SQLAlchemyAttribute:
102
+ data = data.copy()
103
+ typ = deserialize_and_fixup_type(data.pop("type"), api)
104
+ return cls(typ=typ, info=info, **data)
105
+
106
+
107
+ def name_is_dunder(name: str) -> bool:
108
+ return bool(re.match(r"^__.+?__$", name))
109
+
110
+
111
+ def _set_info_metadata(info: TypeInfo, key: str, data: Any) -> None:
112
+ info.metadata.setdefault("sqlalchemy", {})[key] = data
113
+
114
+
115
+ def _get_info_metadata(info: TypeInfo, key: str) -> Optional[Any]:
116
+ return info.metadata.get("sqlalchemy", {}).get(key, None)
117
+
118
+
119
+ def _get_info_mro_metadata(info: TypeInfo, key: str) -> Optional[Any]:
120
+ if info.mro:
121
+ for base in info.mro:
122
+ metadata = _get_info_metadata(base, key)
123
+ if metadata is not None:
124
+ return metadata
125
+ return None
126
+
127
+
128
+ def establish_as_sqlalchemy(info: TypeInfo) -> None:
129
+ info.metadata.setdefault("sqlalchemy", {})
130
+
131
+
132
+ def set_is_base(info: TypeInfo) -> None:
133
+ _set_info_metadata(info, "is_base", True)
134
+
135
+
136
+ def get_is_base(info: TypeInfo) -> bool:
137
+ is_base = _get_info_metadata(info, "is_base")
138
+ return is_base is True
139
+
140
+
141
+ def has_declarative_base(info: TypeInfo) -> bool:
142
+ is_base = _get_info_mro_metadata(info, "is_base")
143
+ return is_base is True
144
+
145
+
146
+ def set_has_table(info: TypeInfo) -> None:
147
+ _set_info_metadata(info, "has_table", True)
148
+
149
+
150
+ def get_has_table(info: TypeInfo) -> bool:
151
+ is_base = _get_info_metadata(info, "has_table")
152
+ return is_base is True
153
+
154
+
155
+ def get_mapped_attributes(
156
+ info: TypeInfo, api: SemanticAnalyzerPluginInterface
157
+ ) -> Optional[List[SQLAlchemyAttribute]]:
158
+ mapped_attributes: Optional[List[JsonDict]] = _get_info_metadata(
159
+ info, "mapped_attributes"
160
+ )
161
+ if mapped_attributes is None:
162
+ return None
163
+
164
+ attributes: List[SQLAlchemyAttribute] = []
165
+
166
+ for data in mapped_attributes:
167
+ attr = SQLAlchemyAttribute.deserialize(info, data, api)
168
+ attr.expand_typevar_from_subtype(info)
169
+ attributes.append(attr)
170
+
171
+ return attributes
172
+
173
+
174
+ def format_type(typ_: Type, options: Options) -> str:
175
+ if mypy_14:
176
+ return _mypy_format_type(typ_, options)
177
+ else:
178
+ return _mypy_format_type(typ_) # type: ignore
179
+
180
+
181
+ def set_mapped_attributes(
182
+ info: TypeInfo, attributes: List[SQLAlchemyAttribute]
183
+ ) -> None:
184
+ _set_info_metadata(
185
+ info,
186
+ "mapped_attributes",
187
+ [attribute.serialize() for attribute in attributes],
188
+ )
189
+
190
+
191
+ def fail(api: SemanticAnalyzerPluginInterface, msg: str, ctx: Context) -> None:
192
+ msg = "[SQLAlchemy Mypy plugin] %s" % msg
193
+ return api.fail(msg, ctx)
194
+
195
+
196
+ def add_global(
197
+ ctx: Union[ClassDefContext, DynamicClassDefContext],
198
+ module: str,
199
+ symbol_name: str,
200
+ asname: str,
201
+ ) -> None:
202
+ module_globals = ctx.api.modules[ctx.api.cur_mod_id].names
203
+
204
+ if asname not in module_globals:
205
+ lookup_sym: SymbolTableNode = ctx.api.modules[module].names[
206
+ symbol_name
207
+ ]
208
+
209
+ module_globals[asname] = lookup_sym
210
+
211
+
212
+ @overload
213
+ def get_callexpr_kwarg(
214
+ callexpr: CallExpr, name: str, *, expr_types: None = ...
215
+ ) -> Optional[Union[CallExpr, NameExpr]]: ...
216
+
217
+
218
+ @overload
219
+ def get_callexpr_kwarg(
220
+ callexpr: CallExpr,
221
+ name: str,
222
+ *,
223
+ expr_types: Tuple[TypingType[_TArgType], ...],
224
+ ) -> Optional[_TArgType]: ...
225
+
226
+
227
+ def get_callexpr_kwarg(
228
+ callexpr: CallExpr,
229
+ name: str,
230
+ *,
231
+ expr_types: Optional[Tuple[TypingType[Any], ...]] = None,
232
+ ) -> Optional[Any]:
233
+ try:
234
+ arg_idx = callexpr.arg_names.index(name)
235
+ except ValueError:
236
+ return None
237
+
238
+ kwarg = callexpr.args[arg_idx]
239
+ if isinstance(
240
+ kwarg, expr_types if expr_types is not None else (NameExpr, CallExpr)
241
+ ):
242
+ return kwarg
243
+
244
+ return None
245
+
246
+
247
+ def flatten_typechecking(stmts: Iterable[Statement]) -> Iterator[Statement]:
248
+ for stmt in stmts:
249
+ if (
250
+ isinstance(stmt, IfStmt)
251
+ and isinstance(stmt.expr[0], NameExpr)
252
+ and stmt.expr[0].fullname == "typing.TYPE_CHECKING"
253
+ ):
254
+ yield from stmt.body[0].body
255
+ else:
256
+ yield stmt
257
+
258
+
259
+ def type_for_callee(callee: Expression) -> Optional[Union[Instance, TypeInfo]]:
260
+ if isinstance(callee, (MemberExpr, NameExpr)):
261
+ if isinstance(callee.node, FuncDef):
262
+ if callee.node.type and isinstance(callee.node.type, CallableType):
263
+ ret_type = get_proper_type(callee.node.type.ret_type)
264
+
265
+ if isinstance(ret_type, Instance):
266
+ return ret_type
267
+
268
+ return None
269
+ elif isinstance(callee.node, TypeAlias):
270
+ target_type = get_proper_type(callee.node.target)
271
+ if isinstance(target_type, Instance):
272
+ return target_type
273
+ elif isinstance(callee.node, TypeInfo):
274
+ return callee.node
275
+ return None
276
+
277
+
278
+ def unbound_to_instance(
279
+ api: SemanticAnalyzerPluginInterface, typ: Type
280
+ ) -> Type:
281
+ """Take the UnboundType that we seem to get as the ret_type from a FuncDef
282
+ and convert it into an Instance/TypeInfo kind of structure that seems
283
+ to work as the left-hand type of an AssignmentStatement.
284
+
285
+ """
286
+
287
+ if not isinstance(typ, UnboundType):
288
+ return typ
289
+
290
+ # TODO: figure out a more robust way to check this. The node is some
291
+ # kind of _SpecialForm, there's a typing.Optional that's _SpecialForm,
292
+ # but I can't figure out how to get them to match up
293
+ if typ.name == "Optional":
294
+ # convert from "Optional?" to the more familiar
295
+ # UnionType[..., NoneType()]
296
+ return unbound_to_instance(
297
+ api,
298
+ UnionType(
299
+ [unbound_to_instance(api, typ_arg) for typ_arg in typ.args]
300
+ + [NoneType()]
301
+ ),
302
+ )
303
+
304
+ node = api.lookup_qualified(typ.name, typ)
305
+
306
+ if (
307
+ node is not None
308
+ and isinstance(node, SymbolTableNode)
309
+ and isinstance(node.node, TypeInfo)
310
+ ):
311
+ bound_type = node.node
312
+
313
+ return Instance(
314
+ bound_type,
315
+ [
316
+ (
317
+ unbound_to_instance(api, arg)
318
+ if isinstance(arg, UnboundType)
319
+ else arg
320
+ )
321
+ for arg in typ.args
322
+ ],
323
+ )
324
+ else:
325
+ return typ
326
+
327
+
328
+ def info_for_cls(
329
+ cls: ClassDef, api: SemanticAnalyzerPluginInterface
330
+ ) -> Optional[TypeInfo]:
331
+ if cls.info is CLASSDEF_NO_INFO:
332
+ sym = api.lookup_qualified(cls.name, cls)
333
+ if sym is None:
334
+ return None
335
+ assert sym and isinstance(sym.node, TypeInfo)
336
+ return sym.node
337
+
338
+ return cls.info
339
+
340
+
341
+ def serialize_type(typ: Type) -> Union[str, JsonDict]:
342
+ try:
343
+ return typ.serialize()
344
+ except Exception:
345
+ pass
346
+ if hasattr(typ, "args"):
347
+ typ.args = tuple(
348
+ (
349
+ a.resolve_string_annotation()
350
+ if hasattr(a, "resolve_string_annotation")
351
+ else a
352
+ )
353
+ for a in typ.args
354
+ )
355
+ elif hasattr(typ, "resolve_string_annotation"):
356
+ typ = typ.resolve_string_annotation()
357
+ return typ.serialize()