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.
- sqlalchemy/__init__.py +298 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +171 -0
- sqlalchemy/connectors/asyncio.py +476 -0
- sqlalchemy/connectors/pyodbc.py +250 -0
- sqlalchemy/dialects/__init__.py +62 -0
- sqlalchemy/dialects/_typing.py +30 -0
- sqlalchemy/dialects/mssql/__init__.py +89 -0
- sqlalchemy/dialects/mssql/aioodbc.py +63 -0
- sqlalchemy/dialects/mssql/base.py +4166 -0
- sqlalchemy/dialects/mssql/information_schema.py +285 -0
- sqlalchemy/dialects/mssql/json.py +140 -0
- sqlalchemy/dialects/mssql/mssqlpython.py +220 -0
- sqlalchemy/dialects/mssql/provision.py +196 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +698 -0
- sqlalchemy/dialects/mysql/__init__.py +106 -0
- sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
- sqlalchemy/dialects/mysql/aiomysql.py +226 -0
- sqlalchemy/dialects/mysql/asyncmy.py +214 -0
- sqlalchemy/dialects/mysql/base.py +3877 -0
- sqlalchemy/dialects/mysql/cymysql.py +106 -0
- sqlalchemy/dialects/mysql/dml.py +279 -0
- sqlalchemy/dialects/mysql/enumerated.py +277 -0
- sqlalchemy/dialects/mysql/expression.py +146 -0
- sqlalchemy/dialects/mysql/json.py +92 -0
- sqlalchemy/dialects/mysql/mariadb.py +67 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +330 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +296 -0
- sqlalchemy/dialects/mysql/mysqldb.py +312 -0
- sqlalchemy/dialects/mysql/provision.py +153 -0
- sqlalchemy/dialects/mysql/pymysql.py +157 -0
- sqlalchemy/dialects/mysql/pyodbc.py +156 -0
- sqlalchemy/dialects/mysql/reflection.py +724 -0
- sqlalchemy/dialects/mysql/reserved_words.py +570 -0
- sqlalchemy/dialects/mysql/types.py +845 -0
- sqlalchemy/dialects/oracle/__init__.py +85 -0
- sqlalchemy/dialects/oracle/base.py +3977 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1601 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/json.py +158 -0
- sqlalchemy/dialects/oracle/oracledb.py +909 -0
- sqlalchemy/dialects/oracle/provision.py +288 -0
- sqlalchemy/dialects/oracle/types.py +367 -0
- sqlalchemy/dialects/oracle/vector.py +368 -0
- sqlalchemy/dialects/postgresql/__init__.py +171 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +229 -0
- sqlalchemy/dialects/postgresql/array.py +534 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1323 -0
- sqlalchemy/dialects/postgresql/base.py +5789 -0
- sqlalchemy/dialects/postgresql/bitstring.py +327 -0
- sqlalchemy/dialects/postgresql/dml.py +360 -0
- sqlalchemy/dialects/postgresql/ext.py +593 -0
- sqlalchemy/dialects/postgresql/hstore.py +423 -0
- sqlalchemy/dialects/postgresql/json.py +408 -0
- sqlalchemy/dialects/postgresql/named_types.py +521 -0
- sqlalchemy/dialects/postgresql/operators.py +130 -0
- sqlalchemy/dialects/postgresql/pg8000.py +670 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +344 -0
- sqlalchemy/dialects/postgresql/provision.py +184 -0
- sqlalchemy/dialects/postgresql/psycopg.py +799 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1002 -0
- sqlalchemy/dialects/postgresql/types.py +388 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +321 -0
- sqlalchemy/dialects/sqlite/base.py +3063 -0
- sqlalchemy/dialects/sqlite/dml.py +279 -0
- sqlalchemy/dialects/sqlite/json.py +100 -0
- sqlalchemy/dialects/sqlite/provision.py +229 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +161 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +754 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_processors_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_processors_cy.py +92 -0
- sqlalchemy/engine/_result_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_result_cy.py +633 -0
- sqlalchemy/engine/_row_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_row_cy.py +232 -0
- sqlalchemy/engine/_util_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_util_cy.py +136 -0
- sqlalchemy/engine/base.py +3354 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +877 -0
- sqlalchemy/engine/cursor.py +2421 -0
- sqlalchemy/engine/default.py +2402 -0
- sqlalchemy/engine/events.py +965 -0
- sqlalchemy/engine/interfaces.py +3495 -0
- sqlalchemy/engine/mock.py +134 -0
- sqlalchemy/engine/processors.py +82 -0
- sqlalchemy/engine/reflection.py +2100 -0
- sqlalchemy/engine/result.py +1966 -0
- sqlalchemy/engine/row.py +397 -0
- sqlalchemy/engine/strategies.py +16 -0
- sqlalchemy/engine/url.py +922 -0
- sqlalchemy/engine/util.py +156 -0
- sqlalchemy/event/__init__.py +26 -0
- sqlalchemy/event/api.py +220 -0
- sqlalchemy/event/attr.py +674 -0
- sqlalchemy/event/base.py +472 -0
- sqlalchemy/event/legacy.py +258 -0
- sqlalchemy/event/registry.py +390 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +922 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2072 -0
- sqlalchemy/ext/asyncio/__init__.py +29 -0
- sqlalchemy/ext/asyncio/base.py +281 -0
- sqlalchemy/ext/asyncio/engine.py +1487 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +994 -0
- sqlalchemy/ext/asyncio/scoping.py +1679 -0
- sqlalchemy/ext/asyncio/session.py +2007 -0
- sqlalchemy/ext/automap.py +1701 -0
- sqlalchemy/ext/baked.py +559 -0
- sqlalchemy/ext/compiler.py +600 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +560 -0
- sqlalchemy/ext/horizontal_shard.py +481 -0
- sqlalchemy/ext/hybrid.py +1877 -0
- sqlalchemy/ext/indexable.py +364 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1081 -0
- sqlalchemy/ext/orderinglist.py +439 -0
- sqlalchemy/ext/serializer.py +185 -0
- sqlalchemy/future/__init__.py +16 -0
- sqlalchemy/future/engine.py +15 -0
- sqlalchemy/inspection.py +174 -0
- sqlalchemy/log.py +283 -0
- sqlalchemy/orm/__init__.py +176 -0
- sqlalchemy/orm/_orm_constructors.py +2694 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2868 -0
- sqlalchemy/orm/base.py +976 -0
- sqlalchemy/orm/bulk_persistence.py +2152 -0
- sqlalchemy/orm/clsregistry.py +582 -0
- sqlalchemy/orm/collections.py +1568 -0
- sqlalchemy/orm/context.py +3471 -0
- sqlalchemy/orm/decl_api.py +2280 -0
- sqlalchemy/orm/decl_base.py +2309 -0
- sqlalchemy/orm/dependency.py +1306 -0
- sqlalchemy/orm/descriptor_props.py +1183 -0
- sqlalchemy/orm/dynamic.py +307 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3386 -0
- sqlalchemy/orm/exc.py +237 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +746 -0
- sqlalchemy/orm/interfaces.py +1589 -0
- sqlalchemy/orm/loading.py +1684 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4411 -0
- sqlalchemy/orm/path_registry.py +829 -0
- sqlalchemy/orm/persistence.py +1789 -0
- sqlalchemy/orm/properties.py +973 -0
- sqlalchemy/orm/query.py +3528 -0
- sqlalchemy/orm/relationships.py +3570 -0
- sqlalchemy/orm/scoping.py +2232 -0
- sqlalchemy/orm/session.py +5403 -0
- sqlalchemy/orm/state.py +1175 -0
- sqlalchemy/orm/state_changes.py +196 -0
- sqlalchemy/orm/strategies.py +3492 -0
- sqlalchemy/orm/strategy_options.py +2562 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +798 -0
- sqlalchemy/orm/util.py +2438 -0
- sqlalchemy/orm/writeonly.py +694 -0
- sqlalchemy/pool/__init__.py +41 -0
- sqlalchemy/pool/base.py +1522 -0
- sqlalchemy/pool/events.py +375 -0
- sqlalchemy/pool/impl.py +582 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +74 -0
- sqlalchemy/sql/__init__.py +156 -0
- sqlalchemy/sql/_annotated_cols.py +397 -0
- sqlalchemy/sql/_dml_constructors.py +132 -0
- sqlalchemy/sql/_elements_constructors.py +2164 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_selectable_constructors.py +840 -0
- sqlalchemy/sql/_typing.py +487 -0
- sqlalchemy/sql/_util_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/sql/_util_cy.py +127 -0
- sqlalchemy/sql/annotation.py +590 -0
- sqlalchemy/sql/base.py +2699 -0
- sqlalchemy/sql/cache_key.py +1066 -0
- sqlalchemy/sql/coercions.py +1373 -0
- sqlalchemy/sql/compiler.py +8327 -0
- sqlalchemy/sql/crud.py +1815 -0
- sqlalchemy/sql/ddl.py +1928 -0
- sqlalchemy/sql/default_comparator.py +654 -0
- sqlalchemy/sql/dml.py +1977 -0
- sqlalchemy/sql/elements.py +6033 -0
- sqlalchemy/sql/events.py +458 -0
- sqlalchemy/sql/expression.py +172 -0
- sqlalchemy/sql/functions.py +2305 -0
- sqlalchemy/sql/lambdas.py +1443 -0
- sqlalchemy/sql/naming.py +209 -0
- sqlalchemy/sql/operators.py +2897 -0
- sqlalchemy/sql/roles.py +332 -0
- sqlalchemy/sql/schema.py +6703 -0
- sqlalchemy/sql/selectable.py +7553 -0
- sqlalchemy/sql/sqltypes.py +4093 -0
- sqlalchemy/sql/traversals.py +1042 -0
- sqlalchemy/sql/type_api.py +2446 -0
- sqlalchemy/sql/util.py +1495 -0
- sqlalchemy/sql/visitors.py +1157 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +1007 -0
- sqlalchemy/testing/assertsql.py +519 -0
- sqlalchemy/testing/asyncio.py +128 -0
- sqlalchemy/testing/config.py +440 -0
- sqlalchemy/testing/engines.py +483 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +476 -0
- sqlalchemy/testing/fixtures/__init__.py +30 -0
- sqlalchemy/testing/fixtures/base.py +384 -0
- sqlalchemy/testing/fixtures/mypy.py +247 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +538 -0
- sqlalchemy/testing/pickleable.py +155 -0
- sqlalchemy/testing/plugin/__init__.py +6 -0
- sqlalchemy/testing/plugin/bootstrap.py +51 -0
- sqlalchemy/testing/plugin/plugin_base.py +828 -0
- sqlalchemy/testing/plugin/pytestplugin.py +892 -0
- sqlalchemy/testing/profiling.py +329 -0
- sqlalchemy/testing/provision.py +613 -0
- sqlalchemy/testing/requirements.py +1978 -0
- sqlalchemy/testing/schema.py +198 -0
- sqlalchemy/testing/suite/__init__.py +19 -0
- sqlalchemy/testing/suite/test_cte.py +237 -0
- sqlalchemy/testing/suite/test_ddl.py +420 -0
- sqlalchemy/testing/suite/test_dialect.py +776 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3557 -0
- sqlalchemy/testing/suite/test_results.py +660 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +2112 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_table_via_select.py +686 -0
- sqlalchemy/testing/suite/test_types.py +2271 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +535 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +76 -0
- sqlalchemy/util/__init__.py +158 -0
- sqlalchemy/util/_collections.py +688 -0
- sqlalchemy/util/_collections_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/util/_collections_cy.pxd +8 -0
- sqlalchemy/util/_collections_cy.py +516 -0
- sqlalchemy/util/_has_cython.py +46 -0
- sqlalchemy/util/_immutabledict_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/util/_immutabledict_cy.py +240 -0
- sqlalchemy/util/compat.py +299 -0
- sqlalchemy/util/concurrency.py +322 -0
- sqlalchemy/util/cython.py +79 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2320 -0
- sqlalchemy/util/preloaded.py +152 -0
- sqlalchemy/util/queue.py +304 -0
- sqlalchemy/util/tool_support.py +201 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +711 -0
- sqlalchemy-2.1.0b2.dist-info/METADATA +269 -0
- sqlalchemy-2.1.0b2.dist-info/RECORD +270 -0
- sqlalchemy-2.1.0b2.dist-info/WHEEL +5 -0
- sqlalchemy-2.1.0b2.dist-info/licenses/LICENSE +19 -0
- sqlalchemy-2.1.0b2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# util/_immutabledict_cy.py
|
|
2
|
+
# Copyright (C) 2010-2026 the SQLAlchemy authors and contributors
|
|
3
|
+
# <see AUTHORS file>
|
|
4
|
+
#
|
|
5
|
+
# This module is part of SQLAlchemy and is released under
|
|
6
|
+
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
|
7
|
+
# mypy: disable-error-code="misc, arg-type, type-arg, untyped-decorator"
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
from typing import Dict
|
|
12
|
+
from typing import Hashable
|
|
13
|
+
from typing import Literal
|
|
14
|
+
from typing import Mapping
|
|
15
|
+
from typing import NoReturn
|
|
16
|
+
from typing import Optional
|
|
17
|
+
from typing import TypeVar
|
|
18
|
+
|
|
19
|
+
from .typing import Self
|
|
20
|
+
|
|
21
|
+
# START GENERATED CYTHON IMPORT
|
|
22
|
+
# This section is automatically generated by the script tools/cython_imports.py
|
|
23
|
+
try:
|
|
24
|
+
# NOTE: the cython compiler needs this "import cython" in the file, it
|
|
25
|
+
# can't be only "from sqlalchemy.util import cython" with the fallback
|
|
26
|
+
# in that module
|
|
27
|
+
import cython
|
|
28
|
+
except ModuleNotFoundError:
|
|
29
|
+
from sqlalchemy.util import cython
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _is_compiled() -> bool:
|
|
33
|
+
"""Utility function to indicate if this module is compiled or not."""
|
|
34
|
+
return cython.compiled # type: ignore[no-any-return,unused-ignore]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# END GENERATED CYTHON IMPORT
|
|
38
|
+
|
|
39
|
+
if cython.compiled:
|
|
40
|
+
from cython.cimports.cpython.dict import PyDict_Update
|
|
41
|
+
else:
|
|
42
|
+
PyDict_Update = dict.update
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _immutable_fn(obj: object) -> NoReturn:
|
|
46
|
+
raise TypeError(f"{obj.__class__.__name__} object is immutable")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class ReadOnlyContainer:
|
|
50
|
+
__slots__ = ()
|
|
51
|
+
|
|
52
|
+
def _readonly(self) -> NoReturn:
|
|
53
|
+
raise TypeError(
|
|
54
|
+
f"{self.__class__.__name__} object is immutable and/or readonly"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def __delitem__(self, key: Any) -> NoReturn:
|
|
58
|
+
self._readonly()
|
|
59
|
+
|
|
60
|
+
def __setitem__(self, key: Any, value: Any) -> NoReturn:
|
|
61
|
+
self._readonly()
|
|
62
|
+
|
|
63
|
+
def __setattr__(self, key: Any, value: Any) -> NoReturn:
|
|
64
|
+
self._readonly()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
_KT = TypeVar("_KT", bound=Hashable)
|
|
68
|
+
_VT = TypeVar("_VT", bound=Any)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@cython.cclass
|
|
72
|
+
class ImmutableDictBase(Dict[_KT, _VT]):
|
|
73
|
+
# NOTE: this method is required in 3.9 and speeds up the use case
|
|
74
|
+
# ImmutableDictBase[str,int](a_dict) significantly
|
|
75
|
+
@classmethod
|
|
76
|
+
def __class_getitem__( # type: ignore[override]
|
|
77
|
+
cls, key: Any
|
|
78
|
+
) -> type[Self]:
|
|
79
|
+
return cls
|
|
80
|
+
|
|
81
|
+
def __delitem__(self, key: Any) -> NoReturn:
|
|
82
|
+
_immutable_fn(self)
|
|
83
|
+
|
|
84
|
+
def __setitem__(self, key: Any, value: Any) -> NoReturn:
|
|
85
|
+
_immutable_fn(self)
|
|
86
|
+
|
|
87
|
+
def __setattr__(self, key: Any, value: Any) -> NoReturn:
|
|
88
|
+
_immutable_fn(self)
|
|
89
|
+
|
|
90
|
+
def clear(self) -> NoReturn:
|
|
91
|
+
_immutable_fn(self)
|
|
92
|
+
|
|
93
|
+
def pop(self, key: Any, default: Optional[Any] = None) -> NoReturn:
|
|
94
|
+
_immutable_fn(self)
|
|
95
|
+
|
|
96
|
+
def popitem(self) -> NoReturn:
|
|
97
|
+
_immutable_fn(self)
|
|
98
|
+
|
|
99
|
+
def setdefault(self, key: Any, default: Optional[Any] = None) -> NoReturn:
|
|
100
|
+
_immutable_fn(self)
|
|
101
|
+
|
|
102
|
+
def update(self, *arg: Any, **kw: Any) -> NoReturn:
|
|
103
|
+
_immutable_fn(self)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# NOTE: can't extend from ImmutableDictBase[_KT, _VT] due to a compiler
|
|
107
|
+
# crash in doing so. Extending from ImmutableDictBase is ok, but requires
|
|
108
|
+
# a type checking section and other workaround for the crash
|
|
109
|
+
@cython.cclass
|
|
110
|
+
class immutabledict(Dict[_KT, _VT]):
|
|
111
|
+
"""An immutable version of a dict."""
|
|
112
|
+
|
|
113
|
+
# ImmutableDictBase start
|
|
114
|
+
@classmethod
|
|
115
|
+
def __class_getitem__( # type: ignore[override]
|
|
116
|
+
cls, key: Any
|
|
117
|
+
) -> type[Self]:
|
|
118
|
+
return cls
|
|
119
|
+
|
|
120
|
+
def __delitem__(self, key: Any) -> NoReturn:
|
|
121
|
+
_immutable_fn(self)
|
|
122
|
+
|
|
123
|
+
def __setitem__(self, key: Any, value: Any) -> NoReturn:
|
|
124
|
+
_immutable_fn(self)
|
|
125
|
+
|
|
126
|
+
def __setattr__(self, key: Any, value: Any) -> NoReturn:
|
|
127
|
+
_immutable_fn(self)
|
|
128
|
+
|
|
129
|
+
def clear(self) -> NoReturn:
|
|
130
|
+
_immutable_fn(self)
|
|
131
|
+
|
|
132
|
+
def pop(self, key: Any, default: Optional[Any] = None) -> NoReturn:
|
|
133
|
+
_immutable_fn(self)
|
|
134
|
+
|
|
135
|
+
def popitem(self) -> NoReturn:
|
|
136
|
+
_immutable_fn(self)
|
|
137
|
+
|
|
138
|
+
def setdefault(self, key: Any, default: Optional[Any] = None) -> NoReturn:
|
|
139
|
+
_immutable_fn(self)
|
|
140
|
+
|
|
141
|
+
def update(self, *arg: Any, **kw: Any) -> NoReturn:
|
|
142
|
+
_immutable_fn(self)
|
|
143
|
+
|
|
144
|
+
# ImmutableDictBase end
|
|
145
|
+
|
|
146
|
+
def __repr__(self) -> str:
|
|
147
|
+
return f"immutabledict({dict.__repr__(self)})"
|
|
148
|
+
|
|
149
|
+
@cython.annotation_typing(False) # avoid cython crash from generic return
|
|
150
|
+
def union(
|
|
151
|
+
self, *dicts: Optional[Mapping[_KT, _VT]]
|
|
152
|
+
) -> immutabledict[_KT, _VT]:
|
|
153
|
+
return self._union_other(dicts) # type: ignore[no-any-return]
|
|
154
|
+
|
|
155
|
+
@cython.annotation_typing(False) # avoid cython crash from generic return
|
|
156
|
+
def merge_with(
|
|
157
|
+
self, *dicts: Optional[Mapping[_KT, _VT]]
|
|
158
|
+
) -> immutabledict[_KT, _VT]:
|
|
159
|
+
# this is an alias of union
|
|
160
|
+
return self._union_other(dicts) # type: ignore[no-any-return]
|
|
161
|
+
|
|
162
|
+
@cython.cfunc
|
|
163
|
+
@cython.inline
|
|
164
|
+
def _union_other(self, others: tuple) -> immutabledict:
|
|
165
|
+
size = len(others)
|
|
166
|
+
if size == 0:
|
|
167
|
+
return self
|
|
168
|
+
|
|
169
|
+
# only_one == immutabledict : we found exactly one immutabledict that
|
|
170
|
+
# has contents; no other dict / immutabledict has any contents
|
|
171
|
+
#
|
|
172
|
+
# only_one is None : we found more than one dict / immutabledict that
|
|
173
|
+
# has contents
|
|
174
|
+
#
|
|
175
|
+
# only_one is False : we've found nothing that is not an empty
|
|
176
|
+
# immutabledict
|
|
177
|
+
only_one: immutabledict | None | Literal[False]
|
|
178
|
+
|
|
179
|
+
if self:
|
|
180
|
+
self_is_empty = False
|
|
181
|
+
only_one = self
|
|
182
|
+
else:
|
|
183
|
+
only_one = False
|
|
184
|
+
self_is_empty = True
|
|
185
|
+
|
|
186
|
+
for i in range(size):
|
|
187
|
+
d = others[i]
|
|
188
|
+
if not d:
|
|
189
|
+
continue
|
|
190
|
+
|
|
191
|
+
if only_one is False and isinstance(d, immutabledict):
|
|
192
|
+
only_one = d
|
|
193
|
+
else:
|
|
194
|
+
only_one = None
|
|
195
|
+
break
|
|
196
|
+
|
|
197
|
+
if only_one is False:
|
|
198
|
+
return self
|
|
199
|
+
elif only_one is not None:
|
|
200
|
+
return only_one
|
|
201
|
+
|
|
202
|
+
result: immutabledict = immutabledict()
|
|
203
|
+
if not self_is_empty:
|
|
204
|
+
PyDict_Update(result, self)
|
|
205
|
+
|
|
206
|
+
for i in range(size):
|
|
207
|
+
d = others[i]
|
|
208
|
+
if not d:
|
|
209
|
+
continue
|
|
210
|
+
if isinstance(d, dict):
|
|
211
|
+
# c version of PyDict_Update supports only dicts
|
|
212
|
+
PyDict_Update(result, d)
|
|
213
|
+
else:
|
|
214
|
+
dict.update(result, d)
|
|
215
|
+
|
|
216
|
+
return result
|
|
217
|
+
|
|
218
|
+
def copy(self) -> Self:
|
|
219
|
+
return self
|
|
220
|
+
|
|
221
|
+
def __reduce__(self) -> Any:
|
|
222
|
+
return immutabledict, (dict(self),)
|
|
223
|
+
|
|
224
|
+
# PEP 584
|
|
225
|
+
def __ior__(self, __value: Any, /) -> NoReturn:
|
|
226
|
+
_immutable_fn(self)
|
|
227
|
+
|
|
228
|
+
def __or__( # type: ignore[override]
|
|
229
|
+
self, __value: Mapping[_KT, _VT], /
|
|
230
|
+
) -> immutabledict[_KT, _VT]:
|
|
231
|
+
return immutabledict(
|
|
232
|
+
dict.__or__(self, __value), # type: ignore[call-overload,operator,unused-ignore] # noqa: E501
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def __ror__( # type: ignore[override]
|
|
236
|
+
self, __value: Mapping[_KT, _VT], /
|
|
237
|
+
) -> immutabledict[_KT, _VT]:
|
|
238
|
+
return immutabledict(
|
|
239
|
+
dict.__ror__(self, __value), # type: ignore[call-overload,operator,unused-ignore] # noqa: E501
|
|
240
|
+
)
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# util/compat.py
|
|
2
|
+
# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
|
|
3
|
+
# <see AUTHORS file>
|
|
4
|
+
#
|
|
5
|
+
# This module is part of SQLAlchemy and is released under
|
|
6
|
+
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
|
7
|
+
# mypy: allow-untyped-defs, allow-untyped-calls
|
|
8
|
+
|
|
9
|
+
"""Handle Python version/platform incompatibilities."""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import base64
|
|
14
|
+
import dataclasses
|
|
15
|
+
import hashlib
|
|
16
|
+
from importlib import metadata as importlib_metadata
|
|
17
|
+
import inspect
|
|
18
|
+
import operator
|
|
19
|
+
import platform
|
|
20
|
+
import sys
|
|
21
|
+
import sysconfig
|
|
22
|
+
import typing
|
|
23
|
+
from typing import Any
|
|
24
|
+
from typing import Callable
|
|
25
|
+
from typing import Dict
|
|
26
|
+
from typing import Iterable
|
|
27
|
+
from typing import List
|
|
28
|
+
from typing import Mapping
|
|
29
|
+
from typing import Optional
|
|
30
|
+
from typing import Sequence
|
|
31
|
+
from typing import Set
|
|
32
|
+
from typing import Tuple
|
|
33
|
+
from typing import Type
|
|
34
|
+
|
|
35
|
+
py314b1 = sys.version_info >= (3, 14, 0, "beta", 1)
|
|
36
|
+
py314 = sys.version_info >= (3, 14)
|
|
37
|
+
py313 = sys.version_info >= (3, 13)
|
|
38
|
+
py312 = sys.version_info >= (3, 12)
|
|
39
|
+
py311 = sys.version_info >= (3, 11)
|
|
40
|
+
pypy = platform.python_implementation() == "PyPy"
|
|
41
|
+
cpython = platform.python_implementation() == "CPython"
|
|
42
|
+
freethreading = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))
|
|
43
|
+
|
|
44
|
+
win32 = sys.platform.startswith("win")
|
|
45
|
+
osx = sys.platform.startswith("darwin")
|
|
46
|
+
arm = "aarch" in platform.machine().lower()
|
|
47
|
+
is64bit = sys.maxsize > 2**32
|
|
48
|
+
|
|
49
|
+
has_refcount_gc = bool(cpython)
|
|
50
|
+
|
|
51
|
+
dottedgetter = operator.attrgetter
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# use sys.version_info to enable mypy version narrowing
|
|
55
|
+
if sys.version_info >= (3, 14):
|
|
56
|
+
|
|
57
|
+
import annotationlib
|
|
58
|
+
from string.templatelib import Template as Template
|
|
59
|
+
|
|
60
|
+
def get_annotations(obj: Any) -> Mapping[str, Any]:
|
|
61
|
+
return annotationlib.get_annotations(
|
|
62
|
+
obj, format=annotationlib.Format.FORWARDREF
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
else:
|
|
66
|
+
|
|
67
|
+
def get_annotations(obj: Any) -> Mapping[str, Any]:
|
|
68
|
+
return inspect.get_annotations(obj)
|
|
69
|
+
|
|
70
|
+
class Template:
|
|
71
|
+
"""Minimal Template for Python < 3.14 (test usage only)."""
|
|
72
|
+
|
|
73
|
+
def __init__(self, *parts: Any):
|
|
74
|
+
self._parts = parts
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def strings(self) -> Tuple[str, ...]:
|
|
78
|
+
return tuple(p for p in self._parts if isinstance(p, str))
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def interpolations(self) -> Tuple[Any, ...]:
|
|
82
|
+
return tuple(p for p in self._parts if not isinstance(p, str))
|
|
83
|
+
|
|
84
|
+
def __iter__(self) -> Any:
|
|
85
|
+
return iter(self._parts)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class FullArgSpec(typing.NamedTuple):
|
|
89
|
+
args: List[str]
|
|
90
|
+
varargs: Optional[str]
|
|
91
|
+
varkw: Optional[str]
|
|
92
|
+
defaults: Optional[Tuple[Any, ...]]
|
|
93
|
+
kwonlyargs: List[str]
|
|
94
|
+
kwonlydefaults: Optional[Dict[str, Any]]
|
|
95
|
+
annotations: Mapping[str, Any]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def inspect_getfullargspec(func: Callable[..., Any]) -> FullArgSpec:
|
|
99
|
+
"""Fully vendored version of getfullargspec from Python 3.3."""
|
|
100
|
+
|
|
101
|
+
if inspect.ismethod(func):
|
|
102
|
+
func = func.__func__
|
|
103
|
+
if not inspect.isfunction(func):
|
|
104
|
+
raise TypeError(f"{func!r} is not a Python function")
|
|
105
|
+
|
|
106
|
+
co = func.__code__
|
|
107
|
+
if not inspect.iscode(co):
|
|
108
|
+
raise TypeError(f"{co!r} is not a code object")
|
|
109
|
+
|
|
110
|
+
nargs = co.co_argcount
|
|
111
|
+
names = co.co_varnames
|
|
112
|
+
nkwargs = co.co_kwonlyargcount
|
|
113
|
+
args = list(names[:nargs])
|
|
114
|
+
kwonlyargs = list(names[nargs : nargs + nkwargs])
|
|
115
|
+
|
|
116
|
+
nargs += nkwargs
|
|
117
|
+
varargs = None
|
|
118
|
+
if co.co_flags & inspect.CO_VARARGS:
|
|
119
|
+
varargs = co.co_varnames[nargs]
|
|
120
|
+
nargs = nargs + 1
|
|
121
|
+
varkw = None
|
|
122
|
+
if co.co_flags & inspect.CO_VARKEYWORDS:
|
|
123
|
+
varkw = co.co_varnames[nargs]
|
|
124
|
+
|
|
125
|
+
return FullArgSpec(
|
|
126
|
+
args,
|
|
127
|
+
varargs,
|
|
128
|
+
varkw,
|
|
129
|
+
func.__defaults__,
|
|
130
|
+
kwonlyargs,
|
|
131
|
+
func.__kwdefaults__,
|
|
132
|
+
get_annotations(func),
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# python stubs don't have a public type for this. not worth
|
|
137
|
+
# making a protocol
|
|
138
|
+
def md5_not_for_security() -> Any:
|
|
139
|
+
return hashlib.md5(usedforsecurity=False)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def importlib_metadata_get(group):
|
|
143
|
+
ep = importlib_metadata.entry_points()
|
|
144
|
+
if typing.TYPE_CHECKING or hasattr(ep, "select"):
|
|
145
|
+
return ep.select(group=group)
|
|
146
|
+
else:
|
|
147
|
+
return ep.get(group, ())
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def b(s):
|
|
151
|
+
return s.encode("latin-1")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def b64decode(x: str) -> bytes:
|
|
155
|
+
return base64.b64decode(x.encode("ascii"))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def b64encode(x: bytes) -> str:
|
|
159
|
+
return base64.b64encode(x).decode("ascii")
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def decode_backslashreplace(text: bytes, encoding: str) -> str:
|
|
163
|
+
return text.decode(encoding, errors="backslashreplace")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def cmp(a, b):
|
|
167
|
+
return (a > b) - (a < b)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _formatannotation(annotation, base_module=None):
|
|
171
|
+
"""vendored from python 3.7"""
|
|
172
|
+
|
|
173
|
+
if isinstance(annotation, str):
|
|
174
|
+
return annotation
|
|
175
|
+
|
|
176
|
+
if getattr(annotation, "__module__", None) == "typing":
|
|
177
|
+
return repr(annotation).replace("typing.", "").replace("~", "")
|
|
178
|
+
if isinstance(annotation, type):
|
|
179
|
+
if annotation.__module__ in ("builtins", base_module):
|
|
180
|
+
return repr(annotation.__qualname__)
|
|
181
|
+
return annotation.__module__ + "." + annotation.__qualname__
|
|
182
|
+
elif isinstance(annotation, typing.TypeVar):
|
|
183
|
+
return repr(annotation).replace("~", "")
|
|
184
|
+
return repr(annotation).replace("~", "")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def inspect_formatargspec(
|
|
188
|
+
args: List[str],
|
|
189
|
+
varargs: Optional[str] = None,
|
|
190
|
+
varkw: Optional[str] = None,
|
|
191
|
+
defaults: Optional[Sequence[Any]] = None,
|
|
192
|
+
kwonlyargs: Optional[Sequence[str]] = (),
|
|
193
|
+
kwonlydefaults: Optional[Mapping[str, Any]] = {},
|
|
194
|
+
annotations: Mapping[str, Any] = {},
|
|
195
|
+
formatarg: Callable[[str], str] = str,
|
|
196
|
+
formatvarargs: Callable[[str], str] = lambda name: "*" + name,
|
|
197
|
+
formatvarkw: Callable[[str], str] = lambda name: "**" + name,
|
|
198
|
+
formatvalue: Callable[[Any], str] = lambda value: "=" + repr(value),
|
|
199
|
+
formatreturns: Callable[[Any], str] = lambda text: " -> " + str(text),
|
|
200
|
+
formatannotation: Callable[[Any], str] = _formatannotation,
|
|
201
|
+
) -> str:
|
|
202
|
+
"""Copy formatargspec from python 3.7 standard library.
|
|
203
|
+
|
|
204
|
+
Python 3 has deprecated formatargspec and requested that Signature
|
|
205
|
+
be used instead, however this requires a full reimplementation
|
|
206
|
+
of formatargspec() in terms of creating Parameter objects and such.
|
|
207
|
+
Instead of introducing all the object-creation overhead and having
|
|
208
|
+
to reinvent from scratch, just copy their compatibility routine.
|
|
209
|
+
|
|
210
|
+
Ultimately we would need to rewrite our "decorator" routine completely
|
|
211
|
+
which is not really worth it right now, until all Python 2.x support
|
|
212
|
+
is dropped.
|
|
213
|
+
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
kwonlydefaults = kwonlydefaults or {}
|
|
217
|
+
annotations = annotations or {}
|
|
218
|
+
|
|
219
|
+
def formatargandannotation(arg):
|
|
220
|
+
result = formatarg(arg)
|
|
221
|
+
if arg in annotations:
|
|
222
|
+
result += ": " + formatannotation(annotations[arg])
|
|
223
|
+
return result
|
|
224
|
+
|
|
225
|
+
specs = []
|
|
226
|
+
if defaults:
|
|
227
|
+
firstdefault = len(args) - len(defaults)
|
|
228
|
+
else:
|
|
229
|
+
firstdefault = -1
|
|
230
|
+
|
|
231
|
+
for i, arg in enumerate(args):
|
|
232
|
+
spec = formatargandannotation(arg)
|
|
233
|
+
if defaults and i >= firstdefault:
|
|
234
|
+
spec = spec + formatvalue(defaults[i - firstdefault])
|
|
235
|
+
specs.append(spec)
|
|
236
|
+
|
|
237
|
+
if varargs is not None:
|
|
238
|
+
specs.append(formatvarargs(formatargandannotation(varargs)))
|
|
239
|
+
else:
|
|
240
|
+
if kwonlyargs:
|
|
241
|
+
specs.append("*")
|
|
242
|
+
|
|
243
|
+
if kwonlyargs:
|
|
244
|
+
for kwonlyarg in kwonlyargs:
|
|
245
|
+
spec = formatargandannotation(kwonlyarg)
|
|
246
|
+
if kwonlydefaults and kwonlyarg in kwonlydefaults:
|
|
247
|
+
spec += formatvalue(kwonlydefaults[kwonlyarg])
|
|
248
|
+
specs.append(spec)
|
|
249
|
+
|
|
250
|
+
if varkw is not None:
|
|
251
|
+
specs.append(formatvarkw(formatargandannotation(varkw)))
|
|
252
|
+
|
|
253
|
+
result = "(" + ", ".join(specs) + ")"
|
|
254
|
+
if "return" in annotations:
|
|
255
|
+
result += formatreturns(formatannotation(annotations["return"]))
|
|
256
|
+
return result
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def dataclass_fields(cls: Type[Any]) -> Iterable[dataclasses.Field[Any]]:
|
|
260
|
+
"""Return a sequence of all dataclasses.Field objects associated
|
|
261
|
+
with a class as an already processed dataclass.
|
|
262
|
+
|
|
263
|
+
The class must **already be a dataclass** for Field objects to be returned.
|
|
264
|
+
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
if dataclasses.is_dataclass(cls):
|
|
268
|
+
return dataclasses.fields(cls)
|
|
269
|
+
else:
|
|
270
|
+
return []
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def local_dataclass_fields(cls: Type[Any]) -> Iterable[dataclasses.Field[Any]]:
|
|
274
|
+
"""Return a sequence of all dataclasses.Field objects associated with
|
|
275
|
+
an already processed dataclass, excluding those that originate from a
|
|
276
|
+
superclass.
|
|
277
|
+
|
|
278
|
+
The class must **already be a dataclass** for Field objects to be returned.
|
|
279
|
+
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
if dataclasses.is_dataclass(cls):
|
|
283
|
+
super_fields: Set[dataclasses.Field[Any]] = set()
|
|
284
|
+
for sup in cls.__bases__:
|
|
285
|
+
super_fields.update(dataclass_fields(sup))
|
|
286
|
+
return [f for f in dataclasses.fields(cls) if f not in super_fields]
|
|
287
|
+
else:
|
|
288
|
+
return []
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
if freethreading:
|
|
292
|
+
import threading
|
|
293
|
+
|
|
294
|
+
mini_gil = threading.RLock()
|
|
295
|
+
"""provide a threading.RLock() under python freethreading only"""
|
|
296
|
+
else:
|
|
297
|
+
import contextlib
|
|
298
|
+
|
|
299
|
+
mini_gil = contextlib.nullcontext() # type: ignore[assignment]
|