SQLAlchemy 2.0.36__cp313-cp313-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.
- SQLAlchemy-2.0.36.dist-info/LICENSE +19 -0
- SQLAlchemy-2.0.36.dist-info/METADATA +243 -0
- SQLAlchemy-2.0.36.dist-info/RECORD +273 -0
- SQLAlchemy-2.0.36.dist-info/WHEEL +5 -0
- SQLAlchemy-2.0.36.dist-info/top_level.txt +1 -0
- sqlalchemy/__init__.py +294 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +174 -0
- sqlalchemy/connectors/asyncio.py +213 -0
- sqlalchemy/connectors/pyodbc.py +249 -0
- sqlalchemy/cyextension/__init__.py +6 -0
- sqlalchemy/cyextension/collections.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/collections.pyx +409 -0
- sqlalchemy/cyextension/immutabledict.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/immutabledict.pxd +8 -0
- sqlalchemy/cyextension/immutabledict.pyx +133 -0
- sqlalchemy/cyextension/processors.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/processors.pyx +68 -0
- sqlalchemy/cyextension/resultproxy.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/resultproxy.pyx +102 -0
- sqlalchemy/cyextension/util.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/util.pyx +91 -0
- sqlalchemy/dialects/__init__.py +61 -0
- sqlalchemy/dialects/_typing.py +25 -0
- sqlalchemy/dialects/mssql/__init__.py +88 -0
- sqlalchemy/dialects/mssql/aioodbc.py +64 -0
- sqlalchemy/dialects/mssql/base.py +4010 -0
- sqlalchemy/dialects/mssql/information_schema.py +254 -0
- sqlalchemy/dialects/mssql/json.py +133 -0
- sqlalchemy/dialects/mssql/provision.py +162 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +745 -0
- sqlalchemy/dialects/mysql/__init__.py +101 -0
- sqlalchemy/dialects/mysql/aiomysql.py +333 -0
- sqlalchemy/dialects/mysql/asyncmy.py +337 -0
- sqlalchemy/dialects/mysql/base.py +3494 -0
- sqlalchemy/dialects/mysql/cymysql.py +84 -0
- sqlalchemy/dialects/mysql/dml.py +219 -0
- sqlalchemy/dialects/mysql/enumerated.py +244 -0
- sqlalchemy/dialects/mysql/expression.py +141 -0
- sqlalchemy/dialects/mysql/json.py +81 -0
- sqlalchemy/dialects/mysql/mariadb.py +32 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +277 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +180 -0
- sqlalchemy/dialects/mysql/mysqldb.py +303 -0
- sqlalchemy/dialects/mysql/provision.py +110 -0
- sqlalchemy/dialects/mysql/pymysql.py +137 -0
- sqlalchemy/dialects/mysql/pyodbc.py +138 -0
- sqlalchemy/dialects/mysql/reflection.py +677 -0
- sqlalchemy/dialects/mysql/reserved_words.py +571 -0
- sqlalchemy/dialects/mysql/types.py +774 -0
- sqlalchemy/dialects/oracle/__init__.py +67 -0
- sqlalchemy/dialects/oracle/base.py +3271 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1483 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/oracledb.py +431 -0
- sqlalchemy/dialects/oracle/provision.py +220 -0
- sqlalchemy/dialects/oracle/types.py +287 -0
- sqlalchemy/dialects/postgresql/__init__.py +167 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +187 -0
- sqlalchemy/dialects/postgresql/array.py +425 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1274 -0
- sqlalchemy/dialects/postgresql/base.py +5008 -0
- sqlalchemy/dialects/postgresql/dml.py +310 -0
- sqlalchemy/dialects/postgresql/ext.py +496 -0
- sqlalchemy/dialects/postgresql/hstore.py +397 -0
- sqlalchemy/dialects/postgresql/json.py +333 -0
- sqlalchemy/dialects/postgresql/named_types.py +509 -0
- sqlalchemy/dialects/postgresql/operators.py +129 -0
- sqlalchemy/dialects/postgresql/pg8000.py +662 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +300 -0
- sqlalchemy/dialects/postgresql/provision.py +175 -0
- sqlalchemy/dialects/postgresql/psycopg.py +772 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +886 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1029 -0
- sqlalchemy/dialects/postgresql/types.py +303 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +396 -0
- sqlalchemy/dialects/sqlite/base.py +2805 -0
- sqlalchemy/dialects/sqlite/dml.py +240 -0
- sqlalchemy/dialects/sqlite/json.py +92 -0
- sqlalchemy/dialects/sqlite/provision.py +198 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +155 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_py_processors.py +136 -0
- sqlalchemy/engine/_py_row.py +128 -0
- sqlalchemy/engine/_py_util.py +74 -0
- sqlalchemy/engine/base.py +3375 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +875 -0
- sqlalchemy/engine/cursor.py +2181 -0
- sqlalchemy/engine/default.py +2365 -0
- sqlalchemy/engine/events.py +951 -0
- sqlalchemy/engine/interfaces.py +3403 -0
- sqlalchemy/engine/mock.py +131 -0
- sqlalchemy/engine/processors.py +61 -0
- sqlalchemy/engine/reflection.py +2098 -0
- sqlalchemy/engine/result.py +2382 -0
- sqlalchemy/engine/row.py +401 -0
- sqlalchemy/engine/strategies.py +19 -0
- sqlalchemy/engine/url.py +910 -0
- sqlalchemy/engine/util.py +167 -0
- sqlalchemy/event/__init__.py +25 -0
- sqlalchemy/event/api.py +225 -0
- sqlalchemy/event/attr.py +655 -0
- sqlalchemy/event/base.py +470 -0
- sqlalchemy/event/legacy.py +246 -0
- sqlalchemy/event/registry.py +386 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +830 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2013 -0
- sqlalchemy/ext/asyncio/__init__.py +25 -0
- sqlalchemy/ext/asyncio/base.py +279 -0
- sqlalchemy/ext/asyncio/engine.py +1466 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +961 -0
- sqlalchemy/ext/asyncio/scoping.py +1614 -0
- sqlalchemy/ext/asyncio/session.py +1936 -0
- sqlalchemy/ext/automap.py +1691 -0
- sqlalchemy/ext/baked.py +574 -0
- sqlalchemy/ext/compiler.py +570 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +548 -0
- sqlalchemy/ext/horizontal_shard.py +481 -0
- sqlalchemy/ext/hybrid.py +1514 -0
- sqlalchemy/ext/indexable.py +341 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1073 -0
- sqlalchemy/ext/mypy/__init__.py +6 -0
- sqlalchemy/ext/mypy/apply.py +320 -0
- sqlalchemy/ext/mypy/decl_class.py +515 -0
- sqlalchemy/ext/mypy/infer.py +590 -0
- sqlalchemy/ext/mypy/names.py +335 -0
- sqlalchemy/ext/mypy/plugin.py +303 -0
- sqlalchemy/ext/mypy/util.py +357 -0
- sqlalchemy/ext/orderinglist.py +416 -0
- sqlalchemy/ext/serializer.py +181 -0
- sqlalchemy/future/__init__.py +16 -0
- sqlalchemy/future/engine.py +15 -0
- sqlalchemy/inspection.py +174 -0
- sqlalchemy/log.py +288 -0
- sqlalchemy/orm/__init__.py +170 -0
- sqlalchemy/orm/_orm_constructors.py +2571 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2835 -0
- sqlalchemy/orm/base.py +973 -0
- sqlalchemy/orm/bulk_persistence.py +2123 -0
- sqlalchemy/orm/clsregistry.py +571 -0
- sqlalchemy/orm/collections.py +1620 -0
- sqlalchemy/orm/context.py +3268 -0
- sqlalchemy/orm/decl_api.py +1883 -0
- sqlalchemy/orm/decl_base.py +2190 -0
- sqlalchemy/orm/dependency.py +1304 -0
- sqlalchemy/orm/descriptor_props.py +1076 -0
- sqlalchemy/orm/dynamic.py +300 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3261 -0
- sqlalchemy/orm/exc.py +228 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +754 -0
- sqlalchemy/orm/interfaces.py +1474 -0
- sqlalchemy/orm/loading.py +1682 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4432 -0
- sqlalchemy/orm/path_registry.py +811 -0
- sqlalchemy/orm/persistence.py +1782 -0
- sqlalchemy/orm/properties.py +886 -0
- sqlalchemy/orm/query.py +3396 -0
- sqlalchemy/orm/relationships.py +3500 -0
- sqlalchemy/orm/scoping.py +2165 -0
- sqlalchemy/orm/session.py +5301 -0
- sqlalchemy/orm/state.py +1143 -0
- sqlalchemy/orm/state_changes.py +198 -0
- sqlalchemy/orm/strategies.py +3473 -0
- sqlalchemy/orm/strategy_options.py +2569 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +796 -0
- sqlalchemy/orm/util.py +2424 -0
- sqlalchemy/orm/writeonly.py +678 -0
- sqlalchemy/pool/__init__.py +44 -0
- sqlalchemy/pool/base.py +1515 -0
- sqlalchemy/pool/events.py +370 -0
- sqlalchemy/pool/impl.py +581 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +70 -0
- sqlalchemy/sql/__init__.py +145 -0
- sqlalchemy/sql/_dml_constructors.py +140 -0
- sqlalchemy/sql/_elements_constructors.py +1850 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_py_util.py +75 -0
- sqlalchemy/sql/_selectable_constructors.py +635 -0
- sqlalchemy/sql/_typing.py +460 -0
- sqlalchemy/sql/annotation.py +585 -0
- sqlalchemy/sql/base.py +2185 -0
- sqlalchemy/sql/cache_key.py +1057 -0
- sqlalchemy/sql/coercions.py +1405 -0
- sqlalchemy/sql/compiler.py +7818 -0
- sqlalchemy/sql/crud.py +1669 -0
- sqlalchemy/sql/ddl.py +1378 -0
- sqlalchemy/sql/default_comparator.py +552 -0
- sqlalchemy/sql/dml.py +1817 -0
- sqlalchemy/sql/elements.py +5499 -0
- sqlalchemy/sql/events.py +455 -0
- sqlalchemy/sql/expression.py +162 -0
- sqlalchemy/sql/functions.py +2055 -0
- sqlalchemy/sql/lambdas.py +1449 -0
- sqlalchemy/sql/naming.py +212 -0
- sqlalchemy/sql/operators.py +2579 -0
- sqlalchemy/sql/roles.py +323 -0
- sqlalchemy/sql/schema.py +6158 -0
- sqlalchemy/sql/selectable.py +7004 -0
- sqlalchemy/sql/sqltypes.py +3827 -0
- sqlalchemy/sql/traversals.py +1024 -0
- sqlalchemy/sql/type_api.py +2339 -0
- sqlalchemy/sql/util.py +1486 -0
- sqlalchemy/sql/visitors.py +1165 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +989 -0
- sqlalchemy/testing/assertsql.py +516 -0
- sqlalchemy/testing/asyncio.py +135 -0
- sqlalchemy/testing/config.py +427 -0
- sqlalchemy/testing/engines.py +472 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +435 -0
- sqlalchemy/testing/fixtures/__init__.py +28 -0
- sqlalchemy/testing/fixtures/base.py +366 -0
- sqlalchemy/testing/fixtures/mypy.py +312 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +503 -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 +779 -0
- sqlalchemy/testing/plugin/pytestplugin.py +868 -0
- sqlalchemy/testing/profiling.py +324 -0
- sqlalchemy/testing/provision.py +496 -0
- sqlalchemy/testing/requirements.py +1818 -0
- sqlalchemy/testing/schema.py +224 -0
- sqlalchemy/testing/suite/__init__.py +19 -0
- sqlalchemy/testing/suite/test_cte.py +211 -0
- sqlalchemy/testing/suite/test_ddl.py +389 -0
- sqlalchemy/testing/suite/test_deprecations.py +153 -0
- sqlalchemy/testing/suite/test_dialect.py +740 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3225 -0
- sqlalchemy/testing/suite/test_results.py +502 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +1999 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_types.py +2141 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +537 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +76 -0
- sqlalchemy/util/__init__.py +160 -0
- sqlalchemy/util/_collections.py +715 -0
- sqlalchemy/util/_concurrency_py3k.py +288 -0
- sqlalchemy/util/_has_cy.py +40 -0
- sqlalchemy/util/_py_collections.py +541 -0
- sqlalchemy/util/compat.py +301 -0
- sqlalchemy/util/concurrency.py +108 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2218 -0
- sqlalchemy/util/preloaded.py +150 -0
- sqlalchemy/util/queue.py +322 -0
- sqlalchemy/util/tool_support.py +201 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +629 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# cyextension/immutabledict.pyx
|
|
2
|
+
# Copyright (C) 2005-2024 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
|
+
from cpython.dict cimport PyDict_New, PyDict_Update, PyDict_Size
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _readonly_fn(obj):
|
|
11
|
+
raise TypeError(
|
|
12
|
+
"%s object is immutable and/or readonly" % obj.__class__.__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _immutable_fn(obj):
|
|
16
|
+
raise TypeError(
|
|
17
|
+
"%s object is immutable" % obj.__class__.__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ReadOnlyContainer:
|
|
21
|
+
|
|
22
|
+
__slots__ = ()
|
|
23
|
+
|
|
24
|
+
def _readonly(self, *a,**kw):
|
|
25
|
+
_readonly_fn(self)
|
|
26
|
+
|
|
27
|
+
__delitem__ = __setitem__ = __setattr__ = _readonly
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ImmutableDictBase(dict):
|
|
31
|
+
def _immutable(self, *a,**kw):
|
|
32
|
+
_immutable_fn(self)
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def __class_getitem__(cls, key):
|
|
36
|
+
return cls
|
|
37
|
+
|
|
38
|
+
__delitem__ = __setitem__ = __setattr__ = _immutable
|
|
39
|
+
clear = pop = popitem = setdefault = update = _immutable
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
cdef class immutabledict(dict):
|
|
43
|
+
def __repr__(self):
|
|
44
|
+
return f"immutabledict({dict.__repr__(self)})"
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def __class_getitem__(cls, key):
|
|
48
|
+
return cls
|
|
49
|
+
|
|
50
|
+
def union(self, *args, **kw):
|
|
51
|
+
cdef dict to_merge = None
|
|
52
|
+
cdef immutabledict result
|
|
53
|
+
cdef Py_ssize_t args_len = len(args)
|
|
54
|
+
if args_len > 1:
|
|
55
|
+
raise TypeError(
|
|
56
|
+
f'union expected at most 1 argument, got {args_len}'
|
|
57
|
+
)
|
|
58
|
+
if args_len == 1:
|
|
59
|
+
attribute = args[0]
|
|
60
|
+
if isinstance(attribute, dict):
|
|
61
|
+
to_merge = <dict> attribute
|
|
62
|
+
if to_merge is None:
|
|
63
|
+
to_merge = dict(*args, **kw)
|
|
64
|
+
|
|
65
|
+
if PyDict_Size(to_merge) == 0:
|
|
66
|
+
return self
|
|
67
|
+
|
|
68
|
+
# new + update is faster than immutabledict(self)
|
|
69
|
+
result = immutabledict()
|
|
70
|
+
PyDict_Update(result, self)
|
|
71
|
+
PyDict_Update(result, to_merge)
|
|
72
|
+
return result
|
|
73
|
+
|
|
74
|
+
def merge_with(self, *other):
|
|
75
|
+
cdef immutabledict result = None
|
|
76
|
+
cdef object d
|
|
77
|
+
cdef bint update = False
|
|
78
|
+
if not other:
|
|
79
|
+
return self
|
|
80
|
+
for d in other:
|
|
81
|
+
if d:
|
|
82
|
+
if update == False:
|
|
83
|
+
update = True
|
|
84
|
+
# new + update is faster than immutabledict(self)
|
|
85
|
+
result = immutabledict()
|
|
86
|
+
PyDict_Update(result, self)
|
|
87
|
+
PyDict_Update(
|
|
88
|
+
result, <dict>(d if isinstance(d, dict) else dict(d))
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return self if update == False else result
|
|
92
|
+
|
|
93
|
+
def copy(self):
|
|
94
|
+
return self
|
|
95
|
+
|
|
96
|
+
def __reduce__(self):
|
|
97
|
+
return immutabledict, (dict(self), )
|
|
98
|
+
|
|
99
|
+
def __delitem__(self, k):
|
|
100
|
+
_immutable_fn(self)
|
|
101
|
+
|
|
102
|
+
def __setitem__(self, k, v):
|
|
103
|
+
_immutable_fn(self)
|
|
104
|
+
|
|
105
|
+
def __setattr__(self, k, v):
|
|
106
|
+
_immutable_fn(self)
|
|
107
|
+
|
|
108
|
+
def clear(self, *args, **kw):
|
|
109
|
+
_immutable_fn(self)
|
|
110
|
+
|
|
111
|
+
def pop(self, *args, **kw):
|
|
112
|
+
_immutable_fn(self)
|
|
113
|
+
|
|
114
|
+
def popitem(self, *args, **kw):
|
|
115
|
+
_immutable_fn(self)
|
|
116
|
+
|
|
117
|
+
def setdefault(self, *args, **kw):
|
|
118
|
+
_immutable_fn(self)
|
|
119
|
+
|
|
120
|
+
def update(self, *args, **kw):
|
|
121
|
+
_immutable_fn(self)
|
|
122
|
+
|
|
123
|
+
# PEP 584
|
|
124
|
+
def __ior__(self, other):
|
|
125
|
+
_immutable_fn(self)
|
|
126
|
+
|
|
127
|
+
def __or__(self, other):
|
|
128
|
+
return immutabledict(dict.__or__(self, other))
|
|
129
|
+
|
|
130
|
+
def __ror__(self, other):
|
|
131
|
+
# NOTE: this is used only in cython 3.x;
|
|
132
|
+
# version 0.x will call __or__ with args inversed
|
|
133
|
+
return immutabledict(dict.__ror__(self, other))
|
|
Binary file
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# cyextension/processors.pyx
|
|
2
|
+
# Copyright (C) 2005-2024 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
|
+
import datetime
|
|
8
|
+
from datetime import datetime as datetime_cls
|
|
9
|
+
from datetime import time as time_cls
|
|
10
|
+
from datetime import date as date_cls
|
|
11
|
+
import re
|
|
12
|
+
|
|
13
|
+
from cpython.object cimport PyObject_Str
|
|
14
|
+
from cpython.unicode cimport PyUnicode_AsASCIIString, PyUnicode_Check, PyUnicode_Decode
|
|
15
|
+
from libc.stdio cimport sscanf
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def int_to_boolean(value):
|
|
19
|
+
if value is None:
|
|
20
|
+
return None
|
|
21
|
+
return True if value else False
|
|
22
|
+
|
|
23
|
+
def to_str(value):
|
|
24
|
+
return PyObject_Str(value) if value is not None else None
|
|
25
|
+
|
|
26
|
+
def to_float(value):
|
|
27
|
+
return float(value) if value is not None else None
|
|
28
|
+
|
|
29
|
+
cdef inline bytes to_bytes(object value, str type_name):
|
|
30
|
+
try:
|
|
31
|
+
return PyUnicode_AsASCIIString(value)
|
|
32
|
+
except Exception as e:
|
|
33
|
+
raise ValueError(
|
|
34
|
+
f"Couldn't parse {type_name} string '{value!r}' "
|
|
35
|
+
"- value is not a string."
|
|
36
|
+
) from e
|
|
37
|
+
|
|
38
|
+
def str_to_datetime(value):
|
|
39
|
+
if value is not None:
|
|
40
|
+
value = datetime_cls.fromisoformat(value)
|
|
41
|
+
return value
|
|
42
|
+
|
|
43
|
+
def str_to_time(value):
|
|
44
|
+
if value is not None:
|
|
45
|
+
value = time_cls.fromisoformat(value)
|
|
46
|
+
return value
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def str_to_date(value):
|
|
50
|
+
if value is not None:
|
|
51
|
+
value = date_cls.fromisoformat(value)
|
|
52
|
+
return value
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
cdef class DecimalResultProcessor:
|
|
57
|
+
cdef object type_
|
|
58
|
+
cdef str format_
|
|
59
|
+
|
|
60
|
+
def __cinit__(self, type_, format_):
|
|
61
|
+
self.type_ = type_
|
|
62
|
+
self.format_ = format_
|
|
63
|
+
|
|
64
|
+
def process(self, object value):
|
|
65
|
+
if value is None:
|
|
66
|
+
return None
|
|
67
|
+
else:
|
|
68
|
+
return self.type_(self.format_ % value)
|
|
Binary file
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# cyextension/resultproxy.pyx
|
|
2
|
+
# Copyright (C) 2005-2024 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
|
+
import operator
|
|
8
|
+
|
|
9
|
+
cdef class BaseRow:
|
|
10
|
+
cdef readonly object _parent
|
|
11
|
+
cdef readonly dict _key_to_index
|
|
12
|
+
cdef readonly tuple _data
|
|
13
|
+
|
|
14
|
+
def __init__(self, object parent, object processors, dict key_to_index, object data):
|
|
15
|
+
"""Row objects are constructed by CursorResult objects."""
|
|
16
|
+
|
|
17
|
+
self._parent = parent
|
|
18
|
+
|
|
19
|
+
self._key_to_index = key_to_index
|
|
20
|
+
|
|
21
|
+
if processors:
|
|
22
|
+
self._data = _apply_processors(processors, data)
|
|
23
|
+
else:
|
|
24
|
+
self._data = tuple(data)
|
|
25
|
+
|
|
26
|
+
def __reduce__(self):
|
|
27
|
+
return (
|
|
28
|
+
rowproxy_reconstructor,
|
|
29
|
+
(self.__class__, self.__getstate__()),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def __getstate__(self):
|
|
33
|
+
return {"_parent": self._parent, "_data": self._data}
|
|
34
|
+
|
|
35
|
+
def __setstate__(self, dict state):
|
|
36
|
+
parent = state["_parent"]
|
|
37
|
+
self._parent = parent
|
|
38
|
+
self._data = state["_data"]
|
|
39
|
+
self._key_to_index = parent._key_to_index
|
|
40
|
+
|
|
41
|
+
def _values_impl(self):
|
|
42
|
+
return list(self)
|
|
43
|
+
|
|
44
|
+
def __iter__(self):
|
|
45
|
+
return iter(self._data)
|
|
46
|
+
|
|
47
|
+
def __len__(self):
|
|
48
|
+
return len(self._data)
|
|
49
|
+
|
|
50
|
+
def __hash__(self):
|
|
51
|
+
return hash(self._data)
|
|
52
|
+
|
|
53
|
+
def __getitem__(self, index):
|
|
54
|
+
return self._data[index]
|
|
55
|
+
|
|
56
|
+
def _get_by_key_impl_mapping(self, key):
|
|
57
|
+
return self._get_by_key_impl(key, 0)
|
|
58
|
+
|
|
59
|
+
cdef _get_by_key_impl(self, object key, int attr_err):
|
|
60
|
+
index = self._key_to_index.get(key)
|
|
61
|
+
if index is not None:
|
|
62
|
+
return self._data[<int>index]
|
|
63
|
+
self._parent._key_not_found(key, attr_err != 0)
|
|
64
|
+
|
|
65
|
+
def __getattr__(self, name):
|
|
66
|
+
return self._get_by_key_impl(name, 1)
|
|
67
|
+
|
|
68
|
+
def _to_tuple_instance(self):
|
|
69
|
+
return self._data
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
cdef tuple _apply_processors(proc, data):
|
|
73
|
+
res = []
|
|
74
|
+
for i in range(len(proc)):
|
|
75
|
+
p = proc[i]
|
|
76
|
+
if p is None:
|
|
77
|
+
res.append(data[i])
|
|
78
|
+
else:
|
|
79
|
+
res.append(p(data[i]))
|
|
80
|
+
return tuple(res)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def rowproxy_reconstructor(cls, state):
|
|
84
|
+
obj = cls.__new__(cls)
|
|
85
|
+
obj.__setstate__(state)
|
|
86
|
+
return obj
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
cdef int is_contiguous(tuple indexes):
|
|
90
|
+
cdef int i
|
|
91
|
+
for i in range(1, len(indexes)):
|
|
92
|
+
if indexes[i-1] != indexes[i] -1:
|
|
93
|
+
return 0
|
|
94
|
+
return 1
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def tuplegetter(*indexes):
|
|
98
|
+
if len(indexes) == 1 or is_contiguous(indexes) != 0:
|
|
99
|
+
# slice form is faster but returns a list if input is list
|
|
100
|
+
return operator.itemgetter(slice(indexes[0], indexes[-1] + 1))
|
|
101
|
+
else:
|
|
102
|
+
return operator.itemgetter(*indexes)
|
|
Binary file
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# cyextension/util.pyx
|
|
2
|
+
# Copyright (C) 2005-2024 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
|
+
from collections.abc import Mapping
|
|
8
|
+
|
|
9
|
+
from sqlalchemy import exc
|
|
10
|
+
|
|
11
|
+
cdef tuple _Empty_Tuple = ()
|
|
12
|
+
|
|
13
|
+
cdef inline bint _mapping_or_tuple(object value):
|
|
14
|
+
return isinstance(value, dict) or isinstance(value, tuple) or isinstance(value, Mapping)
|
|
15
|
+
|
|
16
|
+
cdef inline bint _check_item(object params) except 0:
|
|
17
|
+
cdef object item
|
|
18
|
+
cdef bint ret = 1
|
|
19
|
+
if params:
|
|
20
|
+
item = params[0]
|
|
21
|
+
if not _mapping_or_tuple(item):
|
|
22
|
+
ret = 0
|
|
23
|
+
raise exc.ArgumentError(
|
|
24
|
+
"List argument must consist only of tuples or dictionaries"
|
|
25
|
+
)
|
|
26
|
+
return ret
|
|
27
|
+
|
|
28
|
+
def _distill_params_20(object params):
|
|
29
|
+
if params is None:
|
|
30
|
+
return _Empty_Tuple
|
|
31
|
+
elif isinstance(params, list) or isinstance(params, tuple):
|
|
32
|
+
_check_item(params)
|
|
33
|
+
return params
|
|
34
|
+
elif isinstance(params, dict) or isinstance(params, Mapping):
|
|
35
|
+
return [params]
|
|
36
|
+
else:
|
|
37
|
+
raise exc.ArgumentError("mapping or list expected for parameters")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _distill_raw_params(object params):
|
|
41
|
+
if params is None:
|
|
42
|
+
return _Empty_Tuple
|
|
43
|
+
elif isinstance(params, list):
|
|
44
|
+
_check_item(params)
|
|
45
|
+
return params
|
|
46
|
+
elif _mapping_or_tuple(params):
|
|
47
|
+
return [params]
|
|
48
|
+
else:
|
|
49
|
+
raise exc.ArgumentError("mapping or sequence expected for parameters")
|
|
50
|
+
|
|
51
|
+
cdef class prefix_anon_map(dict):
|
|
52
|
+
def __missing__(self, str key):
|
|
53
|
+
cdef str derived
|
|
54
|
+
cdef int anonymous_counter
|
|
55
|
+
cdef dict self_dict = self
|
|
56
|
+
|
|
57
|
+
derived = key.split(" ", 1)[1]
|
|
58
|
+
|
|
59
|
+
anonymous_counter = self_dict.get(derived, 1)
|
|
60
|
+
self_dict[derived] = anonymous_counter + 1
|
|
61
|
+
value = f"{derived}_{anonymous_counter}"
|
|
62
|
+
self_dict[key] = value
|
|
63
|
+
return value
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
cdef class cache_anon_map(dict):
|
|
67
|
+
cdef int _index
|
|
68
|
+
|
|
69
|
+
def __init__(self):
|
|
70
|
+
self._index = 0
|
|
71
|
+
|
|
72
|
+
def get_anon(self, obj):
|
|
73
|
+
cdef long long idself
|
|
74
|
+
cdef str id_
|
|
75
|
+
cdef dict self_dict = self
|
|
76
|
+
|
|
77
|
+
idself = id(obj)
|
|
78
|
+
if idself in self_dict:
|
|
79
|
+
return self_dict[idself], True
|
|
80
|
+
else:
|
|
81
|
+
id_ = self.__missing__(idself)
|
|
82
|
+
return id_, False
|
|
83
|
+
|
|
84
|
+
def __missing__(self, key):
|
|
85
|
+
cdef str val
|
|
86
|
+
cdef dict self_dict = self
|
|
87
|
+
|
|
88
|
+
self_dict[key] = val = str(self._index)
|
|
89
|
+
self._index += 1
|
|
90
|
+
return val
|
|
91
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# dialects/__init__.py
|
|
2
|
+
# Copyright (C) 2005-2024 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
|
+
from typing import Callable
|
|
11
|
+
from typing import Optional
|
|
12
|
+
from typing import Type
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
from .. import util
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from ..engine.interfaces import Dialect
|
|
19
|
+
|
|
20
|
+
__all__ = ("mssql", "mysql", "oracle", "postgresql", "sqlite")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _auto_fn(name: str) -> Optional[Callable[[], Type[Dialect]]]:
|
|
24
|
+
"""default dialect importer.
|
|
25
|
+
|
|
26
|
+
plugs into the :class:`.PluginLoader`
|
|
27
|
+
as a first-hit system.
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
if "." in name:
|
|
31
|
+
dialect, driver = name.split(".")
|
|
32
|
+
else:
|
|
33
|
+
dialect = name
|
|
34
|
+
driver = "base"
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
if dialect == "mariadb":
|
|
38
|
+
# it's "OK" for us to hardcode here since _auto_fn is already
|
|
39
|
+
# hardcoded. if mysql / mariadb etc were third party dialects
|
|
40
|
+
# they would just publish all the entrypoints, which would actually
|
|
41
|
+
# look much nicer.
|
|
42
|
+
module = __import__(
|
|
43
|
+
"sqlalchemy.dialects.mysql.mariadb"
|
|
44
|
+
).dialects.mysql.mariadb
|
|
45
|
+
return module.loader(driver) # type: ignore
|
|
46
|
+
else:
|
|
47
|
+
module = __import__("sqlalchemy.dialects.%s" % (dialect,)).dialects
|
|
48
|
+
module = getattr(module, dialect)
|
|
49
|
+
except ImportError:
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
if hasattr(module, driver):
|
|
53
|
+
module = getattr(module, driver)
|
|
54
|
+
return lambda: module.dialect
|
|
55
|
+
else:
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
registry = util.PluginLoader("sqlalchemy.dialects", auto_fn=_auto_fn)
|
|
60
|
+
|
|
61
|
+
plugins = util.PluginLoader("sqlalchemy.plugins")
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# dialects/_typing.py
|
|
2
|
+
# Copyright (C) 2005-2024 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
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
from typing import Iterable
|
|
11
|
+
from typing import Mapping
|
|
12
|
+
from typing import Optional
|
|
13
|
+
from typing import Union
|
|
14
|
+
|
|
15
|
+
from ..sql._typing import _DDLColumnArgument
|
|
16
|
+
from ..sql.elements import DQLDMLClauseElement
|
|
17
|
+
from ..sql.schema import ColumnCollectionConstraint
|
|
18
|
+
from ..sql.schema import Index
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
_OnConflictConstraintT = Union[str, ColumnCollectionConstraint, Index, None]
|
|
22
|
+
_OnConflictIndexElementsT = Optional[Iterable[_DDLColumnArgument]]
|
|
23
|
+
_OnConflictIndexWhereT = Optional[DQLDMLClauseElement]
|
|
24
|
+
_OnConflictSetT = Optional[Mapping[Any, Any]]
|
|
25
|
+
_OnConflictWhereT = Union[DQLDMLClauseElement, str, None]
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# dialects/mssql/__init__.py
|
|
2
|
+
# Copyright (C) 2005-2024 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: ignore-errors
|
|
8
|
+
|
|
9
|
+
from . import aioodbc # noqa
|
|
10
|
+
from . import base # noqa
|
|
11
|
+
from . import pymssql # noqa
|
|
12
|
+
from . import pyodbc # noqa
|
|
13
|
+
from .base import BIGINT
|
|
14
|
+
from .base import BINARY
|
|
15
|
+
from .base import BIT
|
|
16
|
+
from .base import CHAR
|
|
17
|
+
from .base import DATE
|
|
18
|
+
from .base import DATETIME
|
|
19
|
+
from .base import DATETIME2
|
|
20
|
+
from .base import DATETIMEOFFSET
|
|
21
|
+
from .base import DECIMAL
|
|
22
|
+
from .base import DOUBLE_PRECISION
|
|
23
|
+
from .base import FLOAT
|
|
24
|
+
from .base import IMAGE
|
|
25
|
+
from .base import INTEGER
|
|
26
|
+
from .base import JSON
|
|
27
|
+
from .base import MONEY
|
|
28
|
+
from .base import NCHAR
|
|
29
|
+
from .base import NTEXT
|
|
30
|
+
from .base import NUMERIC
|
|
31
|
+
from .base import NVARCHAR
|
|
32
|
+
from .base import REAL
|
|
33
|
+
from .base import ROWVERSION
|
|
34
|
+
from .base import SMALLDATETIME
|
|
35
|
+
from .base import SMALLINT
|
|
36
|
+
from .base import SMALLMONEY
|
|
37
|
+
from .base import SQL_VARIANT
|
|
38
|
+
from .base import TEXT
|
|
39
|
+
from .base import TIME
|
|
40
|
+
from .base import TIMESTAMP
|
|
41
|
+
from .base import TINYINT
|
|
42
|
+
from .base import UNIQUEIDENTIFIER
|
|
43
|
+
from .base import VARBINARY
|
|
44
|
+
from .base import VARCHAR
|
|
45
|
+
from .base import XML
|
|
46
|
+
from ...sql import try_cast
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
base.dialect = dialect = pyodbc.dialect
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
__all__ = (
|
|
53
|
+
"JSON",
|
|
54
|
+
"INTEGER",
|
|
55
|
+
"BIGINT",
|
|
56
|
+
"SMALLINT",
|
|
57
|
+
"TINYINT",
|
|
58
|
+
"VARCHAR",
|
|
59
|
+
"NVARCHAR",
|
|
60
|
+
"CHAR",
|
|
61
|
+
"NCHAR",
|
|
62
|
+
"TEXT",
|
|
63
|
+
"NTEXT",
|
|
64
|
+
"DECIMAL",
|
|
65
|
+
"NUMERIC",
|
|
66
|
+
"FLOAT",
|
|
67
|
+
"DATETIME",
|
|
68
|
+
"DATETIME2",
|
|
69
|
+
"DATETIMEOFFSET",
|
|
70
|
+
"DATE",
|
|
71
|
+
"DOUBLE_PRECISION",
|
|
72
|
+
"TIME",
|
|
73
|
+
"SMALLDATETIME",
|
|
74
|
+
"BINARY",
|
|
75
|
+
"VARBINARY",
|
|
76
|
+
"BIT",
|
|
77
|
+
"REAL",
|
|
78
|
+
"IMAGE",
|
|
79
|
+
"TIMESTAMP",
|
|
80
|
+
"ROWVERSION",
|
|
81
|
+
"MONEY",
|
|
82
|
+
"SMALLMONEY",
|
|
83
|
+
"UNIQUEIDENTIFIER",
|
|
84
|
+
"SQL_VARIANT",
|
|
85
|
+
"XML",
|
|
86
|
+
"dialect",
|
|
87
|
+
"try_cast",
|
|
88
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# dialects/mssql/aioodbc.py
|
|
2
|
+
# Copyright (C) 2005-2024 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: ignore-errors
|
|
8
|
+
r"""
|
|
9
|
+
.. dialect:: mssql+aioodbc
|
|
10
|
+
:name: aioodbc
|
|
11
|
+
:dbapi: aioodbc
|
|
12
|
+
:connectstring: mssql+aioodbc://<username>:<password>@<dsnname>
|
|
13
|
+
:url: https://pypi.org/project/aioodbc/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Support for the SQL Server database in asyncio style, using the aioodbc
|
|
17
|
+
driver which itself is a thread-wrapper around pyodbc.
|
|
18
|
+
|
|
19
|
+
.. versionadded:: 2.0.23 Added the mssql+aioodbc dialect which builds
|
|
20
|
+
on top of the pyodbc and general aio* dialect architecture.
|
|
21
|
+
|
|
22
|
+
Using a special asyncio mediation layer, the aioodbc dialect is usable
|
|
23
|
+
as the backend for the :ref:`SQLAlchemy asyncio <asyncio_toplevel>`
|
|
24
|
+
extension package.
|
|
25
|
+
|
|
26
|
+
Most behaviors and caveats for this driver are the same as that of the
|
|
27
|
+
pyodbc dialect used on SQL Server; see :ref:`mssql_pyodbc` for general
|
|
28
|
+
background.
|
|
29
|
+
|
|
30
|
+
This dialect should normally be used only with the
|
|
31
|
+
:func:`_asyncio.create_async_engine` engine creation function; connection
|
|
32
|
+
styles are otherwise equivalent to those documented in the pyodbc section::
|
|
33
|
+
|
|
34
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
35
|
+
engine = create_async_engine(
|
|
36
|
+
"mssql+aioodbc://scott:tiger@mssql2017:1433/test?"
|
|
37
|
+
"driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
from __future__ import annotations
|
|
45
|
+
|
|
46
|
+
from .pyodbc import MSDialect_pyodbc
|
|
47
|
+
from .pyodbc import MSExecutionContext_pyodbc
|
|
48
|
+
from ...connectors.aioodbc import aiodbcConnector
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class MSExecutionContext_aioodbc(MSExecutionContext_pyodbc):
|
|
52
|
+
def create_server_side_cursor(self):
|
|
53
|
+
return self._dbapi_connection.cursor(server_side=True)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class MSDialectAsync_aioodbc(aiodbcConnector, MSDialect_pyodbc):
|
|
57
|
+
driver = "aioodbc"
|
|
58
|
+
|
|
59
|
+
supports_statement_cache = True
|
|
60
|
+
|
|
61
|
+
execution_ctx_cls = MSExecutionContext_aioodbc
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
dialect = MSDialectAsync_aioodbc
|