SQLAlchemy 2.1.3__py3-none-any.whl → 2.1.4__py3-none-any.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 +1 -1
- sqlalchemy/dialects/mssql/base.py +7 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +6 -2
- sqlalchemy/dialects/postgresql/named_types.py +16 -0
- sqlalchemy/engine/_result_cy.py +37 -36
- sqlalchemy/engine/base.py +27 -24
- sqlalchemy/engine/characteristics.py +1 -1
- sqlalchemy/engine/default.py +9 -6
- sqlalchemy/ext/mutable.py +11 -0
- sqlalchemy/orm/decl_base.py +4 -2
- sqlalchemy/sql/compiler.py +15 -2
- sqlalchemy/sql/dml.py +8 -0
- sqlalchemy/sql/sqltypes.py +1 -0
- sqlalchemy/testing/plugin/pytestplugin.py +28 -1
- sqlalchemy/testing/profiling.py +23 -0
- sqlalchemy/testing/requirements.py +5 -0
- sqlalchemy/testing/suite/test_select.py +6 -0
- sqlalchemy/testing/suite/test_types.py +75 -0
- {sqlalchemy-2.1.3.dist-info → sqlalchemy-2.1.4.dist-info}/METADATA +1 -1
- {sqlalchemy-2.1.3.dist-info → sqlalchemy-2.1.4.dist-info}/RECORD +24 -24
- {sqlalchemy-2.1.3.dist-info → sqlalchemy-2.1.4.dist-info}/WHEEL +0 -0
- {sqlalchemy-2.1.3.dist-info → sqlalchemy-2.1.4.dist-info}/licenses/AUTHORS +0 -0
- {sqlalchemy-2.1.3.dist-info → sqlalchemy-2.1.4.dist-info}/licenses/LICENSE +0 -0
- {sqlalchemy-2.1.3.dist-info → sqlalchemy-2.1.4.dist-info}/top_level.txt +0 -0
sqlalchemy/__init__.py
CHANGED
|
@@ -2098,6 +2098,13 @@ class MSSQLCompiler(compiler.SQLCompiler):
|
|
|
2098
2098
|
self.process(binary.right, **kw),
|
|
2099
2099
|
)
|
|
2100
2100
|
|
|
2101
|
+
def visit_truediv_binary(self, binary, operator, **kw):
|
|
2102
|
+
return (
|
|
2103
|
+
self.process(binary.left, **kw)
|
|
2104
|
+
+ " / "
|
|
2105
|
+
+ f"({self.process(binary.right, **kw)} + 0.0)"
|
|
2106
|
+
)
|
|
2107
|
+
|
|
2101
2108
|
def visit_true(self, expr, **kw):
|
|
2102
2109
|
return "1"
|
|
2103
2110
|
|
|
@@ -886,14 +886,18 @@ class AsyncAdapt_asyncpg_connection(
|
|
|
886
886
|
|
|
887
887
|
assert self._transaction is None
|
|
888
888
|
try:
|
|
889
|
-
|
|
889
|
+
transaction = self._connection.transaction(
|
|
890
890
|
isolation=self.isolation_level,
|
|
891
891
|
readonly=self.readonly,
|
|
892
892
|
deferrable=self.deferrable,
|
|
893
893
|
)
|
|
894
|
-
await
|
|
894
|
+
await transaction.start()
|
|
895
895
|
except Exception as error:
|
|
896
896
|
self._handle_exception(error)
|
|
897
|
+
else:
|
|
898
|
+
# only track the transaction once BEGIN has succeeded; a
|
|
899
|
+
# transaction that failed to start has nothing to roll back
|
|
900
|
+
self._transaction = transaction
|
|
897
901
|
|
|
898
902
|
async def _call_and_discard(self, fn: Callable[[], Awaitable[Any]]):
|
|
899
903
|
try:
|
|
@@ -339,6 +339,9 @@ class ENUM(NamedType, type_api.NativeForEmulated, sqltypes.Enum):
|
|
|
339
339
|
kw.setdefault("_create_events", False)
|
|
340
340
|
kw.setdefault("values_callable", impl.values_callable)
|
|
341
341
|
kw.setdefault("omit_aliases", impl._omit_aliases)
|
|
342
|
+
kw.setdefault("sort_key_function", impl._sort_key_function)
|
|
343
|
+
kw.setdefault("create_constraint", impl.create_constraint)
|
|
344
|
+
kw.setdefault("length", impl.length)
|
|
342
345
|
kw.setdefault("_adapted_from", impl)
|
|
343
346
|
|
|
344
347
|
return cls(**kw)
|
|
@@ -514,6 +517,19 @@ class DOMAIN(NamedType, sqltypes.SchemaType):
|
|
|
514
517
|
def __test_init__(cls):
|
|
515
518
|
return cls("name", sqltypes.Integer)
|
|
516
519
|
|
|
520
|
+
def adapt(self, cls, **kw):
|
|
521
|
+
# the DOMAIN-specific arguments are keyword-only, which are not
|
|
522
|
+
# picked up by util.constructor_copy(); pass them explicitly so
|
|
523
|
+
# that copy(), to_metadata() and dialect adaptation retain them
|
|
524
|
+
kw.setdefault("collation", self.collation)
|
|
525
|
+
kw.setdefault("collation_schema", self.collation_schema)
|
|
526
|
+
kw.setdefault("default", self.default)
|
|
527
|
+
kw.setdefault("constraint_name", self.constraint_name)
|
|
528
|
+
kw.setdefault("not_null", self.not_null)
|
|
529
|
+
kw.setdefault("check", self.check)
|
|
530
|
+
kw.setdefault("create_type", self.create_type)
|
|
531
|
+
return super().adapt(cls, **kw)
|
|
532
|
+
|
|
517
533
|
|
|
518
534
|
class CreateEnumType(schema._CreateDropBase):
|
|
519
535
|
__visit_name__ = "create_enum_type"
|
sqlalchemy/engine/_result_cy.py
CHANGED
|
@@ -91,6 +91,37 @@ class _NoRow(Enum):
|
|
|
91
91
|
_NO_ROW = _NoRow._NO_ROW
|
|
92
92
|
|
|
93
93
|
|
|
94
|
+
def _list_map(
|
|
95
|
+
fn: Callable[[Any], _T], /
|
|
96
|
+
) -> Callable[[Sequence[Any]], list[_T]]:
|
|
97
|
+
"""Return a callable that applies ``fn`` to each element of a sequence,
|
|
98
|
+
returning a list.
|
|
99
|
+
|
|
100
|
+
This function serves to prevent a reference cycle between ``fn`` and
|
|
101
|
+
the closure scope of the function that defines it, when compiled with
|
|
102
|
+
Cython.
|
|
103
|
+
|
|
104
|
+
"""
|
|
105
|
+
if cython.compiled:
|
|
106
|
+
|
|
107
|
+
def list_map(rows: Sequence[Any], /) -> list[_T]:
|
|
108
|
+
size: cython.Py_hash_t = len(rows)
|
|
109
|
+
i: cython.Py_ssize_t
|
|
110
|
+
result: list = PyList_New(size)
|
|
111
|
+
for i in range(size):
|
|
112
|
+
row: object = fn(rows[i])
|
|
113
|
+
Py_INCREF(row)
|
|
114
|
+
PyList_SET_ITEM(result, i, row)
|
|
115
|
+
return result
|
|
116
|
+
|
|
117
|
+
else:
|
|
118
|
+
|
|
119
|
+
def list_map(rows: Sequence[Any], /) -> list[_T]:
|
|
120
|
+
return [fn(row) for row in rows]
|
|
121
|
+
|
|
122
|
+
return list_map
|
|
123
|
+
|
|
124
|
+
|
|
94
125
|
class BaseResultInternal(Generic[_R]):
|
|
95
126
|
__slots__ = ()
|
|
96
127
|
|
|
@@ -245,22 +276,7 @@ class BaseResultInternal(Generic[_R]):
|
|
|
245
276
|
row = log_row(row)
|
|
246
277
|
return row
|
|
247
278
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
def many_rows(rows: Sequence[Any], /) -> list[Any]:
|
|
251
|
-
size: cython.Py_hash_t = len(rows)
|
|
252
|
-
i: cython.Py_ssize_t
|
|
253
|
-
result: list = PyList_New(size)
|
|
254
|
-
for i in range(size):
|
|
255
|
-
row: object = single_row(rows[i])
|
|
256
|
-
Py_INCREF(row)
|
|
257
|
-
PyList_SET_ITEM(result, i, row)
|
|
258
|
-
return result
|
|
259
|
-
|
|
260
|
-
else:
|
|
261
|
-
|
|
262
|
-
def many_rows(rows: Sequence[Any], /) -> list[Any]:
|
|
263
|
-
return [single_row(row) for row in rows]
|
|
279
|
+
many_rows = _list_map(single_row)
|
|
264
280
|
|
|
265
281
|
if flag == _FLAG_SCALAR_TO_TUPLE or has_log_row:
|
|
266
282
|
# scalar-source rows have no tuple form; row logging requires
|
|
@@ -279,27 +295,12 @@ class BaseResultInternal(Generic[_R]):
|
|
|
279
295
|
input_row = tuple(input_row)
|
|
280
296
|
return input_row
|
|
281
297
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
def interim_rows(rows: Sequence[Any], /) -> Sequence[Any]:
|
|
285
|
-
size: cython.Py_hash_t = len(rows)
|
|
286
|
-
i: cython.Py_ssize_t
|
|
287
|
-
result: list = PyList_New(size)
|
|
288
|
-
for i in range(size):
|
|
289
|
-
row: object = single_interim_row(rows[i])
|
|
290
|
-
Py_INCREF(row)
|
|
291
|
-
PyList_SET_ITEM(result, i, row)
|
|
292
|
-
return result
|
|
293
|
-
|
|
294
|
-
else:
|
|
295
|
-
|
|
296
|
-
def interim_rows(rows: Sequence[Any], /) -> Sequence[Any]:
|
|
297
|
-
return [single_interim_row(row) for row in rows]
|
|
298
|
+
interim_rows = _list_map(single_interim_row)
|
|
298
299
|
|
|
299
300
|
return single_row, many_rows, interim_rows # type: ignore[return-value] # noqa: E501
|
|
300
301
|
|
|
301
302
|
@HasMemoized_ro_memoized_attribute
|
|
302
|
-
def _iterator_getter(self) -> Callable[[], Iterator[_R]]:
|
|
303
|
+
def _iterator_getter(self) -> Callable[[Self], Iterator[_R]]:
|
|
303
304
|
make_row = self._row_getter[0]
|
|
304
305
|
|
|
305
306
|
post_creational_filter = self._post_creational_filter
|
|
@@ -308,7 +309,7 @@ class BaseResultInternal(Generic[_R]):
|
|
|
308
309
|
uniques: set
|
|
309
310
|
uniques, strategy = self._unique_strategy
|
|
310
311
|
|
|
311
|
-
def iterrows() -> Iterator[_R]:
|
|
312
|
+
def iterrows(self: Self) -> Iterator[_R]:
|
|
312
313
|
for raw_row in self._fetchiter_impl():
|
|
313
314
|
row = (
|
|
314
315
|
make_row(raw_row) if make_row is not None else raw_row
|
|
@@ -323,7 +324,7 @@ class BaseResultInternal(Generic[_R]):
|
|
|
323
324
|
|
|
324
325
|
else:
|
|
325
326
|
|
|
326
|
-
def iterrows() -> Iterator[_R]:
|
|
327
|
+
def iterrows(self: Self) -> Iterator[_R]:
|
|
327
328
|
for raw_row in self._fetchiter_impl():
|
|
328
329
|
row = (
|
|
329
330
|
make_row(raw_row) if make_row is not None else raw_row
|
|
@@ -617,7 +618,7 @@ class BaseResultInternal(Generic[_R]):
|
|
|
617
618
|
return row # type: ignore[return-value]
|
|
618
619
|
|
|
619
620
|
def _iter_impl(self) -> Iterator[_R]:
|
|
620
|
-
return self._iterator_getter()
|
|
621
|
+
return self._iterator_getter(self)
|
|
621
622
|
|
|
622
623
|
def _next_impl(self) -> _R:
|
|
623
624
|
row = self._onerow_getter(self)
|
sqlalchemy/engine/base.py
CHANGED
|
@@ -1257,30 +1257,33 @@ class Connection(ConnectionEventsTarget, inspection.Inspectable["Inspector"]):
|
|
|
1257
1257
|
|
|
1258
1258
|
"""
|
|
1259
1259
|
|
|
1260
|
-
if
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1260
|
+
# if the rollback here raises, skip_reset stays False and the pool
|
|
1261
|
+
# does its own reset of the connection, invalidating it if that
|
|
1262
|
+
# fails also. see #13657
|
|
1263
|
+
skip_reset = False
|
|
1264
|
+
try:
|
|
1265
|
+
if self._transaction:
|
|
1266
|
+
self._transaction.close()
|
|
1267
|
+
skip_reset = True
|
|
1268
|
+
finally:
|
|
1269
|
+
if self._dbapi_connection is not None:
|
|
1270
|
+
conn = self._dbapi_connection
|
|
1271
|
+
|
|
1272
|
+
# as we just closed the transaction, close the connection
|
|
1273
|
+
# pool connection without doing an additional reset
|
|
1274
|
+
if skip_reset:
|
|
1275
|
+
cast("_ConnectionFairy", conn)._close_special(
|
|
1276
|
+
transaction_reset=True
|
|
1277
|
+
)
|
|
1278
|
+
else:
|
|
1279
|
+
conn.close()
|
|
1280
|
+
|
|
1281
|
+
# There is a slight chance that conn.close() may have
|
|
1282
|
+
# triggered an invalidation here in which case
|
|
1283
|
+
# _dbapi_connection would already be None, however usually
|
|
1284
|
+
# it will be non-None here and in a "closed" state.
|
|
1285
|
+
self._dbapi_connection = None
|
|
1286
|
+
self.__can_reconnect = False
|
|
1284
1287
|
|
|
1285
1288
|
# special case to handle mypy issue:
|
|
1286
1289
|
# https://github.com/python/mypy/issues/20651
|
|
@@ -142,7 +142,7 @@ class LoggingTokenCharacteristic(ConnectionCharacteristic):
|
|
|
142
142
|
if value:
|
|
143
143
|
conn._message_formatter = lambda msg: "[%s] %s" % (value, msg)
|
|
144
144
|
else:
|
|
145
|
-
|
|
145
|
+
conn._message_formatter = None
|
|
146
146
|
|
|
147
147
|
def get_characteristic(
|
|
148
148
|
self, dialect: Dialect, dbapi_conn: DBAPIConnection
|
sqlalchemy/engine/default.py
CHANGED
|
@@ -2137,6 +2137,15 @@ class DefaultExecutionContext(ExecutionContext):
|
|
|
2137
2137
|
):
|
|
2138
2138
|
self._setup_out_parameters(result)
|
|
2139
2139
|
|
|
2140
|
+
if not result._soft_closed and not result._metadata.returns_rows:
|
|
2141
|
+
# no results, get rowcount (which requires open cursor on
|
|
2142
|
+
# some drivers) and release the cursor. this applies to all
|
|
2143
|
+
# statements that don't return rows, including DML, text(),
|
|
2144
|
+
# DDL and SAVEPOINT
|
|
2145
|
+
if self._rowcount is None:
|
|
2146
|
+
self._rowcount = self.cursor.rowcount
|
|
2147
|
+
result._soft_close()
|
|
2148
|
+
|
|
2140
2149
|
self._soft_closed = result._soft_closed
|
|
2141
2150
|
|
|
2142
2151
|
if yp:
|
|
@@ -2272,12 +2281,6 @@ class DefaultExecutionContext(ExecutionContext):
|
|
|
2272
2281
|
# the rows have all been fetched however.
|
|
2273
2282
|
assert result._metadata.returns_rows
|
|
2274
2283
|
|
|
2275
|
-
elif not result._metadata.returns_rows:
|
|
2276
|
-
# no results, get rowcount
|
|
2277
|
-
# (which requires open cursor on some drivers)
|
|
2278
|
-
if self._rowcount is None:
|
|
2279
|
-
self._rowcount = self.cursor.rowcount
|
|
2280
|
-
result._soft_close()
|
|
2281
2284
|
elif self.isupdate or self.isdelete:
|
|
2282
2285
|
if self._rowcount is None:
|
|
2283
2286
|
self._rowcount = self.cursor.rowcount
|
sqlalchemy/ext/mutable.py
CHANGED
|
@@ -840,6 +840,12 @@ class MutableDict(Mutable, Dict[_KT, _VT]):
|
|
|
840
840
|
dict.update(self, *a, **kw)
|
|
841
841
|
self.changed()
|
|
842
842
|
|
|
843
|
+
def __ior__( # type: ignore[override,misc]
|
|
844
|
+
self, other: Any
|
|
845
|
+
) -> MutableDict[_KT, _VT]:
|
|
846
|
+
self.update(other)
|
|
847
|
+
return self
|
|
848
|
+
|
|
843
849
|
if TYPE_CHECKING:
|
|
844
850
|
|
|
845
851
|
@overload
|
|
@@ -949,6 +955,11 @@ class MutableList(Mutable, List[_T]):
|
|
|
949
955
|
self.extend(x)
|
|
950
956
|
return self
|
|
951
957
|
|
|
958
|
+
def __imul__(self, n: SupportsIndex) -> MutableList[_T]:
|
|
959
|
+
list.__imul__(self, n)
|
|
960
|
+
self.changed()
|
|
961
|
+
return self
|
|
962
|
+
|
|
952
963
|
def insert(self, i: SupportsIndex, x: _T) -> None:
|
|
953
964
|
list.insert(self, i, x)
|
|
954
965
|
self.changed()
|
sqlalchemy/orm/decl_base.py
CHANGED
|
@@ -67,6 +67,7 @@ from ..sql import expression
|
|
|
67
67
|
from ..sql._annotated_cols import TypedColumns
|
|
68
68
|
from ..sql.base import _NoArg
|
|
69
69
|
from ..sql.schema import Column
|
|
70
|
+
from ..sql.schema import MetaData
|
|
70
71
|
from ..sql.schema import Table
|
|
71
72
|
from ..util import topological
|
|
72
73
|
from ..util.typing import _AnnotationScanType
|
|
@@ -80,7 +81,6 @@ if TYPE_CHECKING:
|
|
|
80
81
|
from .decl_api import declared_attr
|
|
81
82
|
from .instrumentation import ClassManager
|
|
82
83
|
from ..sql.elements import NamedColumn
|
|
83
|
-
from ..sql.schema import MetaData
|
|
84
84
|
from ..sql.selectable import FromClause
|
|
85
85
|
|
|
86
86
|
_T = TypeVar("_T", bound=Any)
|
|
@@ -1525,7 +1525,9 @@ class _DeclarativeMapperConfig(_MapperConfig, _ClassScanAbstractConfig):
|
|
|
1525
1525
|
value = SynonymProperty(value.key)
|
|
1526
1526
|
setattr(cls, k, value)
|
|
1527
1527
|
|
|
1528
|
-
if k
|
|
1528
|
+
if k == "registry" or (
|
|
1529
|
+
k == "metadata" and not isinstance(value, MetaData)
|
|
1530
|
+
):
|
|
1529
1531
|
noun = {
|
|
1530
1532
|
"metadata": "MetaData instance",
|
|
1531
1533
|
"registry": "Declarative class registry",
|
sqlalchemy/sql/compiler.py
CHANGED
|
@@ -3136,12 +3136,20 @@ class SQLCompiler(Compiled):
|
|
|
3136
3136
|
self.process(element.aggregate_order_by, **kw),
|
|
3137
3137
|
)
|
|
3138
3138
|
|
|
3139
|
-
def visit_aggregate_strings_func(
|
|
3139
|
+
def visit_aggregate_strings_func(
|
|
3140
|
+
self, fn, *, use_function_name=None, **kw
|
|
3141
|
+
):
|
|
3140
3142
|
# aggreagate_order_by attribute is present if visit_function
|
|
3141
3143
|
# gave us a Function with aggregate_orderby_inline() as the inner
|
|
3142
3144
|
# contents
|
|
3143
3145
|
order_by = getattr(fn.clauses, "aggregate_order_by", None)
|
|
3144
3146
|
|
|
3147
|
+
if use_function_name is None:
|
|
3148
|
+
raise exc.CompileError(
|
|
3149
|
+
"%s dialect does not support the aggregate_strings function"
|
|
3150
|
+
% self.dialect.name
|
|
3151
|
+
)
|
|
3152
|
+
|
|
3145
3153
|
literal_exec = dict(kw)
|
|
3146
3154
|
literal_exec["literal_execute"] = True
|
|
3147
3155
|
|
|
@@ -3338,7 +3346,7 @@ class SQLCompiler(Compiled):
|
|
|
3338
3346
|
util.warn(
|
|
3339
3347
|
"Column-expression-level unary distinct() "
|
|
3340
3348
|
"should not be used outside of an aggregate "
|
|
3341
|
-
"function. For general 'SELECT DISTINCT' support"
|
|
3349
|
+
"function. For general 'SELECT DISTINCT' support "
|
|
3342
3350
|
"use select().distinct()."
|
|
3343
3351
|
)
|
|
3344
3352
|
|
|
@@ -7092,6 +7100,11 @@ class StrSQLCompiler(SQLCompiler):
|
|
|
7092
7100
|
def get_from_hint_text(self, table, text):
|
|
7093
7101
|
return "[%s]" % text
|
|
7094
7102
|
|
|
7103
|
+
def visit_aggregate_strings_func(self, fn, **kw):
|
|
7104
|
+
return super().visit_aggregate_strings_func(
|
|
7105
|
+
fn, use_function_name=fn.name, **kw
|
|
7106
|
+
)
|
|
7107
|
+
|
|
7095
7108
|
def visit_regexp_match_op_binary(self, binary, operator, **kw):
|
|
7096
7109
|
return self._generate_generic_binary(binary, " <regexp> ", **kw)
|
|
7097
7110
|
|
sqlalchemy/sql/dml.py
CHANGED
|
@@ -1263,6 +1263,10 @@ class Insert(ValuesBase, HasSyntaxExtensions[Literal["post_values"]]):
|
|
|
1263
1263
|
"_return_defaults_columns",
|
|
1264
1264
|
InternalTraversal.dp_clauseelement_tuple,
|
|
1265
1265
|
),
|
|
1266
|
+
(
|
|
1267
|
+
"_supplemental_returning",
|
|
1268
|
+
InternalTraversal.dp_clauseelement_tuple,
|
|
1269
|
+
),
|
|
1266
1270
|
("_sort_by_parameter_order", InternalTraversal.dp_boolean),
|
|
1267
1271
|
]
|
|
1268
1272
|
+ HasPrefixes._has_prefixes_traverse_internals
|
|
@@ -1663,6 +1667,10 @@ class Update(
|
|
|
1663
1667
|
"_return_defaults_columns",
|
|
1664
1668
|
InternalTraversal.dp_clauseelement_tuple,
|
|
1665
1669
|
),
|
|
1670
|
+
(
|
|
1671
|
+
"_supplemental_returning",
|
|
1672
|
+
InternalTraversal.dp_clauseelement_tuple,
|
|
1673
|
+
),
|
|
1666
1674
|
]
|
|
1667
1675
|
+ HasPrefixes._has_prefixes_traverse_internals
|
|
1668
1676
|
+ DialectKWArgs._dialect_kwargs_traverse_internals
|
sqlalchemy/sql/sqltypes.py
CHANGED
|
@@ -1939,6 +1939,7 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
|
|
|
1939
1939
|
kw.setdefault("create_constraint", self.create_constraint)
|
|
1940
1940
|
kw.setdefault("length", self.length)
|
|
1941
1941
|
kw.setdefault("omit_aliases", self._omit_aliases)
|
|
1942
|
+
kw.setdefault("sort_key_function", self._sort_key_function)
|
|
1942
1943
|
return kw
|
|
1943
1944
|
|
|
1944
1945
|
def adapt_to_emulated(self, impltype, **kw):
|
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
import argparse
|
|
12
12
|
import collections
|
|
13
13
|
from functools import update_wrapper
|
|
14
|
+
import hashlib
|
|
14
15
|
import inspect
|
|
15
16
|
import itertools
|
|
16
17
|
import operator
|
|
@@ -545,6 +546,31 @@ def pytest_runtest_call(item):
|
|
|
545
546
|
_current_report = None
|
|
546
547
|
|
|
547
548
|
|
|
549
|
+
_MAX_PARAM_ID_LEN = 60
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
def _shorten_param_id(ident):
|
|
553
|
+
"""shorten a very long parameter id for console / junit output.
|
|
554
|
+
|
|
555
|
+
keeps the leading portion of the string and appends a short digest of
|
|
556
|
+
the full value, so that ids remain stable and distinct.
|
|
557
|
+
|
|
558
|
+
"""
|
|
559
|
+
if len(ident) <= _MAX_PARAM_ID_LEN:
|
|
560
|
+
return ident
|
|
561
|
+
digest = hashlib.md5(
|
|
562
|
+
ident.encode("utf-8"), usedforsecurity=False
|
|
563
|
+
).hexdigest()[:8]
|
|
564
|
+
return f"{ident[:_MAX_PARAM_ID_LEN - 12]}...{digest}"
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def pytest_make_parametrize_id(config, val, argname):
|
|
568
|
+
if isinstance(val, str) and len(val) > _MAX_PARAM_ID_LEN:
|
|
569
|
+
return _shorten_param_id(val.encode("unicode_escape").decode("ascii"))
|
|
570
|
+
else:
|
|
571
|
+
return None
|
|
572
|
+
|
|
573
|
+
|
|
548
574
|
def pytest_runtest_logreport(report):
|
|
549
575
|
global _current_report
|
|
550
576
|
if report.when == "call":
|
|
@@ -768,7 +794,8 @@ class PytestFixtureFunctions(plugin_base.FixtureFunctions):
|
|
|
768
794
|
parameters,
|
|
769
795
|
param_exclusions,
|
|
770
796
|
"-".join(
|
|
771
|
-
comb_fn(getter(arg))
|
|
797
|
+
_shorten_param_id(comb_fn(getter(arg)))
|
|
798
|
+
for getter, comb_fn in fns
|
|
772
799
|
),
|
|
773
800
|
)
|
|
774
801
|
)
|
sqlalchemy/testing/profiling.py
CHANGED
|
@@ -119,7 +119,9 @@ class ProfileStatsFile:
|
|
|
119
119
|
def platform_key(self) -> PlatformKey:
|
|
120
120
|
db = config.db
|
|
121
121
|
assert db is not None, "no database configured"
|
|
122
|
+
return self.platform_key_for(db)
|
|
122
123
|
|
|
124
|
+
def platform_key_for(self, db: Any) -> PlatformKey:
|
|
123
125
|
dbapi_flags = []
|
|
124
126
|
if db.dialect.is_async:
|
|
125
127
|
dbapi_flags.append("async")
|
|
@@ -144,6 +146,27 @@ class ProfileStatsFile:
|
|
|
144
146
|
cextensions=has_compiled_ext(),
|
|
145
147
|
)
|
|
146
148
|
|
|
149
|
+
def has_platform(self, db: Any) -> bool:
|
|
150
|
+
"""Return True if profiling tests should run against the given
|
|
151
|
+
engine.
|
|
152
|
+
|
|
153
|
+
This is the case when the profile file has counts for at least
|
|
154
|
+
one test on the engine's platform, or when profiles are being
|
|
155
|
+
written. Used to keep profiling test classes from being generated
|
|
156
|
+
at all for drivers / interpreters that would only have each
|
|
157
|
+
test skip from within :func:`.count_functions`, after the class
|
|
158
|
+
has already run its fixture setup.
|
|
159
|
+
|
|
160
|
+
"""
|
|
161
|
+
if self.write:
|
|
162
|
+
return True
|
|
163
|
+
|
|
164
|
+
platform_key = self.platform_key_for(db)
|
|
165
|
+
return any(
|
|
166
|
+
platform_key in self.profiles.platforms_for(test_key)
|
|
167
|
+
for test_key in self.profiles.test_keys()
|
|
168
|
+
)
|
|
169
|
+
|
|
147
170
|
def has_stats(self) -> bool:
|
|
148
171
|
return (
|
|
149
172
|
self.profiles.counts_for(_current_test, self.platform_key)
|
|
@@ -1271,6 +1271,11 @@ class SuiteRequirements(Requirements):
|
|
|
1271
1271
|
to represent very large values."""
|
|
1272
1272
|
return exclusions.open()
|
|
1273
1273
|
|
|
1274
|
+
@property
|
|
1275
|
+
def float_cast(self):
|
|
1276
|
+
"""target backend supports CAST to a FLOAT type"""
|
|
1277
|
+
return exclusions.open()
|
|
1278
|
+
|
|
1274
1279
|
@property
|
|
1275
1280
|
def precision_numerics_many_significant_digits(self):
|
|
1276
1281
|
"""target backend supports values with many digits on both sides,
|
|
@@ -1646,6 +1646,12 @@ class LikeFunctionsTest(fixtures.TablesTest):
|
|
|
1646
1646
|
|
|
1647
1647
|
|
|
1648
1648
|
class ComputedColumnTest(fixtures.TablesTest):
|
|
1649
|
+
"""This test uses Computed without specifying the persisted mode.
|
|
1650
|
+
On some postgresql version the compiler may raise a warning.
|
|
1651
|
+
Use `warns_if` in the computed_columns requirement to catch the warning
|
|
1652
|
+
conditionally on the postgresql version.
|
|
1653
|
+
"""
|
|
1654
|
+
|
|
1649
1655
|
__sparse_driver_backend__ = True
|
|
1650
1656
|
__requires__ = ("computed_columns",)
|
|
1651
1657
|
|
|
@@ -34,6 +34,7 @@ from ... import Date
|
|
|
34
34
|
from ... import DateTime
|
|
35
35
|
from ... import Enum
|
|
36
36
|
from ... import Float
|
|
37
|
+
from ... import func
|
|
37
38
|
from ... import Integer
|
|
38
39
|
from ... import Interval
|
|
39
40
|
from ... import JSON
|
|
@@ -1120,6 +1121,80 @@ class TrueDivTest(fixtures.TestBase):
|
|
|
1120
1121
|
1,
|
|
1121
1122
|
)
|
|
1122
1123
|
|
|
1124
|
+
@testing.combinations(
|
|
1125
|
+
("typed", lambda divisor: divisor),
|
|
1126
|
+
("untyped_function", lambda divisor: func.nullif(divisor, 0)),
|
|
1127
|
+
id_="ia",
|
|
1128
|
+
argnames="wrap_divisor",
|
|
1129
|
+
)
|
|
1130
|
+
@testing.combinations(
|
|
1131
|
+
(
|
|
1132
|
+
"float",
|
|
1133
|
+
"7.0",
|
|
1134
|
+
"3.5",
|
|
1135
|
+
Float(),
|
|
1136
|
+
"2",
|
|
1137
|
+
testing.requires.float_cast,
|
|
1138
|
+
),
|
|
1139
|
+
("numeric_whole_number", "1", "2.00", Numeric(10, 2), "0.5"),
|
|
1140
|
+
(
|
|
1141
|
+
"numeric_many_decimals",
|
|
1142
|
+
"5.02797279921331664759",
|
|
1143
|
+
"0.71828182845904523537",
|
|
1144
|
+
Numeric(22, 20),
|
|
1145
|
+
"7",
|
|
1146
|
+
(
|
|
1147
|
+
testing.requires.precision_numerics_many_significant_digits
|
|
1148
|
+
).as_skips(),
|
|
1149
|
+
),
|
|
1150
|
+
(
|
|
1151
|
+
"numeric_tiny_divisor",
|
|
1152
|
+
"0.00000000000049382716",
|
|
1153
|
+
"0.00000000000012345679",
|
|
1154
|
+
Numeric(38, 20),
|
|
1155
|
+
"4",
|
|
1156
|
+
),
|
|
1157
|
+
(
|
|
1158
|
+
"numeric_38_digit_divisor",
|
|
1159
|
+
"30000000000000000000000000000000000000",
|
|
1160
|
+
"10000000000000000000000000000000000000",
|
|
1161
|
+
Numeric(38, 0),
|
|
1162
|
+
"3",
|
|
1163
|
+
),
|
|
1164
|
+
id_="iaaaa",
|
|
1165
|
+
argnames="left, right, type_, expected",
|
|
1166
|
+
)
|
|
1167
|
+
def test_truediv_divisor(
|
|
1168
|
+
self, connection, wrap_divisor, left, right, type_, expected
|
|
1169
|
+
):
|
|
1170
|
+
"""test #13631
|
|
1171
|
+
|
|
1172
|
+
each pair of operands is divided with the divisor's type visible to
|
|
1173
|
+
SQLAlchemy ("typed") and hidden behind a function of unknown type
|
|
1174
|
+
("untyped_function"). The operand pairs each rule out an approach
|
|
1175
|
+
to forcing true division that loses precision on some backend:
|
|
1176
|
+
|
|
1177
|
+
* float - a bare CAST(x AS NUMERIC) truncates 3.5 on SQL Server,
|
|
1178
|
+
where NUMERIC means NUMERIC(18, 0)
|
|
1179
|
+
* numeric_whole_number - SQLite stores 2.00 as the integer 2, so a
|
|
1180
|
+
CAST to NUMERIC alone gives integer division
|
|
1181
|
+
* numeric_many_decimals - CAST to FLOAT gives 7.000000000000001.
|
|
1182
|
+
skipped rather than xfailed on backends without decimal
|
|
1183
|
+
arithmetic such as SQLite, where whether the result comes out
|
|
1184
|
+
as 7 depends on how the platform parses the literals to floats
|
|
1185
|
+
* numeric_tiny_divisor - on SQL Server, multiplying a
|
|
1186
|
+
NUMERIC(38, 20) by 1.0 reduces the scale and rounds the divisor
|
|
1187
|
+
* numeric_38_digit_divisor - on SQL Server, multiplying a
|
|
1188
|
+
NUMERIC(38, 0) by 1.0 overflows
|
|
1189
|
+
|
|
1190
|
+
"""
|
|
1191
|
+
expr = cast(literal_column(left), type_) / wrap_divisor(
|
|
1192
|
+
cast(literal_column(right), type_)
|
|
1193
|
+
)
|
|
1194
|
+
result = connection.scalar(select(expr))
|
|
1195
|
+
|
|
1196
|
+
eq_(decimal.Decimal(str(result)), decimal.Decimal(expected))
|
|
1197
|
+
|
|
1123
1198
|
|
|
1124
1199
|
class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase):
|
|
1125
1200
|
__backend__ = True
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
sqlalchemy/__init__.py,sha256=
|
|
1
|
+
sqlalchemy/__init__.py,sha256=_uCHzwTy6ReaEDykCpWE3XmTA1iJqz7Xej7ma48rhS8,13562
|
|
2
2
|
sqlalchemy/events.py,sha256=vEDW04X_PMhMw5y0_95tbEzht3wua8_gnkMBJstYNRw,525
|
|
3
3
|
sqlalchemy/exc.py,sha256=CKyzx9WSeWTYxueZLAtTFpZTNKSon0YlpGt9v-C8dl8,27503
|
|
4
4
|
sqlalchemy/inspection.py,sha256=2mcgybcOVuQDB2bSIhwidrMteP9qOpEbmehyT2lrnt8,5661
|
|
@@ -15,7 +15,7 @@ sqlalchemy/dialects/_typing.py,sha256=oUmFIxU_AVXmJyRXiE5IsDvKFh8HvAcyiGMQaWmY7M
|
|
|
15
15
|
sqlalchemy/dialects/type_migration_guidelines.txt,sha256=-uHNdmYFGB7bzUNT6i8M5nb4j6j9YUKAtW4lcBZqsMg,8239
|
|
16
16
|
sqlalchemy/dialects/mssql/__init__.py,sha256=j1pNh_cHkSRoTzCjUQcjRNZEVtIfdFCgkTT87mgSs5s,1913
|
|
17
17
|
sqlalchemy/dialects/mssql/aioodbc.py,sha256=RS9TZI4cDa9My9YHQbWW2nD3lUBx-s8aQZ7G2080dDA,2005
|
|
18
|
-
sqlalchemy/dialects/mssql/base.py,sha256=
|
|
18
|
+
sqlalchemy/dialects/mssql/base.py,sha256=Jt_N-oZt4_uaqPqVDFvLKN1Xyj9eJSnlwKORu5S33vQ,160932
|
|
19
19
|
sqlalchemy/dialects/mssql/information_schema.py,sha256=xoO2mKqq99GBN9osJaaYjLw3VQg4YB8rFrh5K6gGfaI,10544
|
|
20
20
|
sqlalchemy/dialects/mssql/json.py,sha256=SgcLWK-xmy_5FCzgxoz2Xa8pnJemVFCuiNQ6aFApHyk,5338
|
|
21
21
|
sqlalchemy/dialects/mssql/mssqlpython.py,sha256=Boe6dsrabesUauvFUDIHeFXDXLBh3qi2pgqYCqI__eI,7832
|
|
@@ -54,14 +54,14 @@ sqlalchemy/dialects/oracle/vector.py,sha256=v7zf88XX7ICORNuycw3da1d5G7KHmYytNtU6
|
|
|
54
54
|
sqlalchemy/dialects/postgresql/__init__.py,sha256=uqvgSydDm7mbLeLtuARI8AXFkcHPCkqTgd8UNDKznxs,3988
|
|
55
55
|
sqlalchemy/dialects/postgresql/_psycopg_common.py,sha256=3btoOFqAcFmkectNE1Vgs7cOv4ccF28xIQZIDEYwOWA,7178
|
|
56
56
|
sqlalchemy/dialects/postgresql/array.py,sha256=fHA_e2ez1SGHXa4BrXxbwCKMEkrDxn2GFzWJOjZrM0c,17907
|
|
57
|
-
sqlalchemy/dialects/postgresql/asyncpg.py,sha256=
|
|
57
|
+
sqlalchemy/dialects/postgresql/asyncpg.py,sha256=ne9Fr2-dWoD0qLjpsLxTvkRmYGD1CtBR-wSeG0E1Or8,42563
|
|
58
58
|
sqlalchemy/dialects/postgresql/base.py,sha256=pMvzDesY5HsgmNnfPDa7HUD7rU_W11QlZfQDM4Y3A44,214444
|
|
59
59
|
sqlalchemy/dialects/postgresql/bitstring.py,sha256=-AowJ4DqlcT0PcFXML44TU4VND_hFuvtkwqUgKBcE1I,10603
|
|
60
60
|
sqlalchemy/dialects/postgresql/dml.py,sha256=ckxPBWuAXCRKkSFvdmwEppvirvczFY-voniqgC3X6DA,12959
|
|
61
61
|
sqlalchemy/dialects/postgresql/ext.py,sha256=ZgdhLnWDYcm3RQ0XlUtrsW3WF1YRcGmzEK-8sdg16wc,19603
|
|
62
62
|
sqlalchemy/dialects/postgresql/hstore.py,sha256=i14ZMZ2oml63W1OMfLiq_IAFAFbh-QUPKT1_vN5obY0,12728
|
|
63
63
|
sqlalchemy/dialects/postgresql/json.py,sha256=LGa5zmfU5tqwcJSKpWwy9azQHklNqNLBuK5HXIUNEKc,14996
|
|
64
|
-
sqlalchemy/dialects/postgresql/named_types.py,sha256=
|
|
64
|
+
sqlalchemy/dialects/postgresql/named_types.py,sha256=qwxZKnBtzujRe6lYJaH8v0kRSCmS--fT6UrHAwDPbXE,19459
|
|
65
65
|
sqlalchemy/dialects/postgresql/operators.py,sha256=CndNmzeu8ytmDA497ZeTxcbHxSVlVrOCmGREuUfjWhU,2840
|
|
66
66
|
sqlalchemy/dialects/postgresql/pg8000.py,sha256=Hb54csBYBbFZS5wkJFH63BDPxp1E1bQtaH_r_U-pSNQ,18392
|
|
67
67
|
sqlalchemy/dialects/postgresql/pg_catalog.py,sha256=7NWViTqCyWjgWiY3buavYo-CA2h-nxwfpc-vzYnNotg,10475
|
|
@@ -81,14 +81,14 @@ sqlalchemy/dialects/sqlite/pysqlcipher.py,sha256=k3qMGR2VvHHT29vsJ-eJYUe7jIXhgGS
|
|
|
81
81
|
sqlalchemy/dialects/sqlite/pysqlite.py,sha256=_jD3LdPia8SV9ma3pz9zm9g46Rp9m4nQ4Hyd6yMDnVk,36592
|
|
82
82
|
sqlalchemy/engine/__init__.py,sha256=Nn05AJVAfZn_sToGjt09vBcZET343-wYwl-oo2Fg6R8,2818
|
|
83
83
|
sqlalchemy/engine/_processors_cy.py,sha256=Q68s_s1zINR4nFQCfUfMJqjdRWI-J2BIF01tpgP7LiE,2498
|
|
84
|
-
sqlalchemy/engine/_result_cy.py,sha256=
|
|
84
|
+
sqlalchemy/engine/_result_cy.py,sha256=Lk65cmkNwSM0tDRBFHCMB8mdMmaAPjP-LY9L6qwdRqo,24006
|
|
85
85
|
sqlalchemy/engine/_row_cy.py,sha256=GUX53624m7KpLOTQhsi5aMHv-ypdB4caWMQPGkuAIC4,7413
|
|
86
86
|
sqlalchemy/engine/_util_cy.py,sha256=AicwKLv6IuJ46WNVhEkT0MUPEFS5z8ltxKKTIA_HyNI,4504
|
|
87
|
-
sqlalchemy/engine/base.py,sha256=
|
|
88
|
-
sqlalchemy/engine/characteristics.py,sha256=
|
|
87
|
+
sqlalchemy/engine/base.py,sha256=Aq3OSbeo-9re9IDDJLNwMUWfnJUfReIexBqHdXGeCDU,124009
|
|
88
|
+
sqlalchemy/engine/characteristics.py,sha256=QctD35XaPso4brk2W8zQmdomMkRRV6X7vbeo96eUvA4,4768
|
|
89
89
|
sqlalchemy/engine/create.py,sha256=7G0aidSUYtghZjyv7C19TZcv_3o3pS62UXj-sRgsWVs,33661
|
|
90
90
|
sqlalchemy/engine/cursor.py,sha256=B5NmeqIEsOiPU8QaE4dXh7s1cSp2_5erukysuKs7ipo,85474
|
|
91
|
-
sqlalchemy/engine/default.py,sha256=
|
|
91
|
+
sqlalchemy/engine/default.py,sha256=u4h11cJackuZ-ImOinv4JbSTiiQGO3I6Em9i8LjL7L8,94768
|
|
92
92
|
sqlalchemy/engine/events.py,sha256=d-BzEd6M8dG8q22w3N6RX98cDcrANTgYyPjb5oFQznE,37475
|
|
93
93
|
sqlalchemy/engine/interfaces.py,sha256=IKYAaYa-iA44O3bsxsmhyNWwIf3FToX7Wx8N-I9xD0E,123015
|
|
94
94
|
sqlalchemy/engine/mock.py,sha256=i9J-z0NsL78VlqC85MRgo5SNNQU256UtEqficO3DCwY,4155
|
|
@@ -114,7 +114,7 @@ sqlalchemy/ext/horizontal_shard.py,sha256=uWbe4iP7pDzYR-8jBmrifyOEPTn7N1_a33YKma
|
|
|
114
114
|
sqlalchemy/ext/hybrid.py,sha256=vfyfb54vRd6S_JpbWsswlketD6mFX-OeK9I06R2mN70,64744
|
|
115
115
|
sqlalchemy/ext/indexable.py,sha256=MhqYUA_KuB95t3kzKTtUwEbh5OMhuNNujwyJ0ENKZrM,11761
|
|
116
116
|
sqlalchemy/ext/instrumentation.py,sha256=4DL2RBcYE8bymiRNTjEDYevBpXTftECjFwg90DBqEuw,15708
|
|
117
|
-
sqlalchemy/ext/mutable.py,sha256=
|
|
117
|
+
sqlalchemy/ext/mutable.py,sha256=vjS-EhR2GW26fSb61woPucZEEzEJCxMYt6AcxxX-NBg,37404
|
|
118
118
|
sqlalchemy/ext/orderinglist.py,sha256=ItEwaVvzeYdoSwj0Ipao0xi8BThXCeLZqFxChsQuCo8,15157
|
|
119
119
|
sqlalchemy/ext/serializer.py,sha256=uOicJGYMBW5S1VXDGU61UIiSfLT3ricVVt5a9oKJJVI,6113
|
|
120
120
|
sqlalchemy/ext/asyncio/__init__.py,sha256=0MnGUog_nAVA71tE0IAiyqVbOn2Dpt71QpMAf5Y1-Lk,1410
|
|
@@ -138,7 +138,7 @@ sqlalchemy/orm/clsregistry.py,sha256=dmIYdM2VTyLVLYiale_x9-JGSK6GpQ0JOqsZuxfSfQE
|
|
|
138
138
|
sqlalchemy/orm/collections.py,sha256=sc-KrVjRZ1EKArBPn2lqmH9QX7HKr6d2oX0fPV5a4h8,50026
|
|
139
139
|
sqlalchemy/orm/context.py,sha256=F1poIa-NftQTO_cNUfSnbJKjbPQs9kWy6tBEyznTD_8,120868
|
|
140
140
|
sqlalchemy/orm/decl_api.py,sha256=gK5IGcbAXMdCN6SzprewMhfbXiZe1yO1Ghv2y2z3EHA,78721
|
|
141
|
-
sqlalchemy/orm/decl_base.py,sha256=
|
|
141
|
+
sqlalchemy/orm/decl_base.py,sha256=DF132BFspNgbSrnVIA63RNk8b8MIzfOe4vk6wqKMQ8g,87748
|
|
142
142
|
sqlalchemy/orm/dependency.py,sha256=gqUUJi7LMF2RIEvq7hw_w-WfbpW8CXzSaDW5QTW5NlQ,47739
|
|
143
143
|
sqlalchemy/orm/descriptor_props.py,sha256=2R4NUuPIyinL5RrTbOAYebb3ZJNJLnT6_J2QCWy0nEM,42407
|
|
144
144
|
sqlalchemy/orm/dynamic.py,sha256=7wyr0eM7xIRqWQk6jcoHjqGYatORwImRbrysJhQaGm8,9968
|
|
@@ -184,11 +184,11 @@ sqlalchemy/sql/annotation.py,sha256=gkFPOq3qGo6fahIxTwXgxCdcEyiD8W4CH0q01d1E0mo,
|
|
|
184
184
|
sqlalchemy/sql/base.py,sha256=1xkh7mgC25GVZS8tczZbwDAxRvdumoaW3UPrJXbynbQ,98615
|
|
185
185
|
sqlalchemy/sql/cache_key.py,sha256=OihJqOVsdU0F_IShr0FIptTRHtIlM1UIZ_5LR8LQd0Q,28872
|
|
186
186
|
sqlalchemy/sql/coercions.py,sha256=XyV6wyiIHHD6ViGdZhLMQ8OVWNk4_LyBvv15t504UYI,39144
|
|
187
|
-
sqlalchemy/sql/compiler.py,sha256=
|
|
187
|
+
sqlalchemy/sql/compiler.py,sha256=9vNcKzGXY-gqOl_R42tzwQR0V0MjBNn79OmJmjiVjQo,301830
|
|
188
188
|
sqlalchemy/sql/crud.py,sha256=1qtcYPM-p9DsjMaqixYgKVSPuQEK43QEsAdgmXYY_ok,61581
|
|
189
189
|
sqlalchemy/sql/ddl.py,sha256=6vfeMHtVcV6vWBQLxDZ906CHBnnadG5C8vmQNbpY5k8,65048
|
|
190
190
|
sqlalchemy/sql/default_comparator.py,sha256=MC1yWLbOArtLAsVWho_08Jk8ogP6mEgtRP-IxBYFtv4,18684
|
|
191
|
-
sqlalchemy/sql/dml.py,sha256
|
|
191
|
+
sqlalchemy/sql/dml.py,sha256=-j0vtiT_JPyZoxUxtgOwtSOT3BHK_S6BlBR5vzfrzcM,71911
|
|
192
192
|
sqlalchemy/sql/elements.py,sha256=zPomd9yuJm5DJ9Jie87V5w2M8Zcv6mrd1nx174QKSmo,196427
|
|
193
193
|
sqlalchemy/sql/events.py,sha256=xpqx3irkG8N3gysXAViLCqXXke9KCSU-6w4zZUdYXzw,18312
|
|
194
194
|
sqlalchemy/sql/expression.py,sha256=SStPoDh7LSBTj6-4_KZSzyH0i5f493lqx4EnwcGPCZU,8342
|
|
@@ -199,7 +199,7 @@ sqlalchemy/sql/operators.py,sha256=91HJboxRkDFNHx9JlpO9hsss7wqTfeoANOxjMFszTt0,8
|
|
|
199
199
|
sqlalchemy/sql/roles.py,sha256=QG4iNsYMCqjnMP3wt-5lEKxQZIh3uD2yVhurcS-z7VM,7857
|
|
200
200
|
sqlalchemy/sql/schema.py,sha256=55oc5r8Mqtkcr2ker8kHjlBSUSO3QhwyyqrG2gaFgu4,262469
|
|
201
201
|
sqlalchemy/sql/selectable.py,sha256=PcrGphf752_nMgFvA5d5LLUGhio9glG3nrCSEJtbvTs,257803
|
|
202
|
-
sqlalchemy/sql/sqltypes.py,sha256=
|
|
202
|
+
sqlalchemy/sql/sqltypes.py,sha256=zykH4bSbQRbmrdq9_lqnOqwwtgWAq0j-XnWa4zQPtQw,138822
|
|
203
203
|
sqlalchemy/sql/traversals.py,sha256=xLBzv1qpTUjBTiTGMBvPUvl1UPffYSWMxV4wHgOM4i4,34355
|
|
204
204
|
sqlalchemy/sql/type_api.py,sha256=nIjquO8VkktzgurEYoxPYDMShBRi_xfCyV0wsw8yEAQ,89578
|
|
205
205
|
sqlalchemy/sql/util.py,sha256=2k520E59ONQEtChkhy7E8Dpmw1WPWbJePwDfG0rRi4A,48610
|
|
@@ -215,9 +215,9 @@ sqlalchemy/testing/entities.py,sha256=ZIE4OCzDlKE1OxVArkWF755gvYZDS8oUuX5fuwPAQg
|
|
|
215
215
|
sqlalchemy/testing/exclusions.py,sha256=Iwz9xZABIW8BmD-3URvCV20-d0LHKncd8xMpBEHGEUE,14572
|
|
216
216
|
sqlalchemy/testing/pickleable.py,sha256=gXgySNI39dUcuNY6e-vM9HFKxQ7Uva7NVZgeYyNY4Zw,2833
|
|
217
217
|
sqlalchemy/testing/profiles_file.py,sha256=sxwF-c6Wd6IBEMHpU1QSdsouyCX7b-4EWWsTTdD8m4w,11349
|
|
218
|
-
sqlalchemy/testing/profiling.py,sha256=
|
|
218
|
+
sqlalchemy/testing/profiling.py,sha256=ES3F7pklXaQJXUMdXmcUmoyXvOC3koYYARsIMGyjtqI,10049
|
|
219
219
|
sqlalchemy/testing/provision.py,sha256=pOMK51WaXJyWAh48HbBjgywDPLk02pSS7rHQqoMLulI,18628
|
|
220
|
-
sqlalchemy/testing/requirements.py,sha256=
|
|
220
|
+
sqlalchemy/testing/requirements.py,sha256=WShbncr8vR1oZKhoap3r3eZMmsnK70oUqtSCc6Ao5CQ,58493
|
|
221
221
|
sqlalchemy/testing/schema.py,sha256=49x-TXARL2k8oIiaSzyGxXG5fh7vJOuBoUv5h9YTfKo,5360
|
|
222
222
|
sqlalchemy/testing/util.py,sha256=vbd6v3shfmdxqnqbL0K_hg-yi-ou5Fe9FpkUZeCEyUk,15809
|
|
223
223
|
sqlalchemy/testing/warnings.py,sha256=j8GWiP-yraCW0Ig5iJxAa5ekN82ZWqcQWyR-BUb4MZA,1546
|
|
@@ -229,7 +229,7 @@ sqlalchemy/testing/fixtures/sql.py,sha256=LAp9DhOJ7gInbcCBDqUaIhDCFIHt4ydh_g53v8
|
|
|
229
229
|
sqlalchemy/testing/plugin/__init__.py,sha256=8LB-gN7jwvGVW4bPAM1b8MmAQQwBSKh_BGVS3HQc4EM,247
|
|
230
230
|
sqlalchemy/testing/plugin/bootstrap.py,sha256=5hrNoDrExsOv6fUaa-4JPPEnTJJVJYlBMYGMPu7PjZ8,1684
|
|
231
231
|
sqlalchemy/testing/plugin/plugin_base.py,sha256=aS9A5zoKaoGKMy8F2OIKbPOMe5SG49lChANZ_cd3UM0,23102
|
|
232
|
-
sqlalchemy/testing/plugin/pytestplugin.py,sha256=
|
|
232
|
+
sqlalchemy/testing/plugin/pytestplugin.py,sha256=H_F1GFG8-NqaP-FgjEkZnyPY9F81OA-JygtiddZ0iQs,29468
|
|
233
233
|
sqlalchemy/testing/suite/__init__.py,sha256=jLYLmFQ6k0Fn7N2iPrbXwzJMKDSe4oMdmD-AC6yu3ws,726
|
|
234
234
|
sqlalchemy/testing/suite/test_cte.py,sha256=7AnV9dR9h76JWY0yWuyeQT-5GQsYbNMz3q2SG8IA_R4,7276
|
|
235
235
|
sqlalchemy/testing/suite/test_ddl.py,sha256=03nV2s8lfcCw4Czq6pkHl0ZGho8KyFe_C-f0HthP3B0,13010
|
|
@@ -238,10 +238,10 @@ sqlalchemy/testing/suite/test_insert.py,sha256=tapEYecSPKqL8xrjlcQzDOfbWdKJz9ldT
|
|
|
238
238
|
sqlalchemy/testing/suite/test_reflection.py,sha256=Em0XdladxD6Lk9YH6ZQUw0cdEvkaXJfEPs-1E21xVn0,128866
|
|
239
239
|
sqlalchemy/testing/suite/test_results.py,sha256=Aw8RK5CX1y39wDK6U8ub8PX9OYe8aoBCBCohjVPvRks,22499
|
|
240
240
|
sqlalchemy/testing/suite/test_rowcount.py,sha256=V6RQGwe9LO5tKzFPFoa29dDs8M0eY8JZ9tqgbzgtCYs,7900
|
|
241
|
-
sqlalchemy/testing/suite/test_select.py,sha256=
|
|
241
|
+
sqlalchemy/testing/suite/test_select.py,sha256=qNeb6RgssJZWur-R4TZ88xyLVi6Offo067It0el-K90,66071
|
|
242
242
|
sqlalchemy/testing/suite/test_sequence.py,sha256=8a6UO3pjRFnQ23ELG9m5cMMRoD3iD7aSgul-HnkeLns,9979
|
|
243
243
|
sqlalchemy/testing/suite/test_table_via_select.py,sha256=ZMJKUhAiqIzTKyK9J2cA_rvTij7CUt77d6o5sqDdrkc,21706
|
|
244
|
-
sqlalchemy/testing/suite/test_types.py,sha256=
|
|
244
|
+
sqlalchemy/testing/suite/test_types.py,sha256=Uva7OT-mmdizJMunxpaaV-SbeK9hhMp799PIPTb5V10,79090
|
|
245
245
|
sqlalchemy/testing/suite/test_unicode_ddl.py,sha256=tVLf9RqCJe-CsyhCWL9d-WuWazDx5iWYzoBrSCbgjXs,6141
|
|
246
246
|
sqlalchemy/testing/suite/test_update_delete.py,sha256=llAnxDGvbK-C7CzEXbSNEjczhOSL1sKTLuzGyJahqV8,5195
|
|
247
247
|
sqlalchemy/util/__init__.py,sha256=2DHFcXP7fB86rfMhHWvngoIZMjKU9ur3L74jd-ROGaE,8671
|
|
@@ -260,9 +260,9 @@ sqlalchemy/util/queue.py,sha256=9cMV3Dea0l5tfWIHw3LUE0L3knt48gtUP_C8fBKLQeo,9740
|
|
|
260
260
|
sqlalchemy/util/tool_support.py,sha256=iZSwvKdF5pA8UtXuwbtln6dEDgerKJWasELSi7q6Epw,6136
|
|
261
261
|
sqlalchemy/util/topological.py,sha256=yMpaA2s0JYIekQF4XKwzJzy8lVo-8yeo8o1J2xzxq48,3451
|
|
262
262
|
sqlalchemy/util/typing.py,sha256=p3vOTJ4F7i3eqeFw7W_tayq88U0e53ZgOsCu7eNQ3lA,21125
|
|
263
|
-
sqlalchemy-2.1.
|
|
264
|
-
sqlalchemy-2.1.
|
|
265
|
-
sqlalchemy-2.1.
|
|
266
|
-
sqlalchemy-2.1.
|
|
267
|
-
sqlalchemy-2.1.
|
|
268
|
-
sqlalchemy-2.1.
|
|
263
|
+
sqlalchemy-2.1.4.dist-info/licenses/AUTHORS,sha256=3B2wtdF0Va3De2k_-OQJyagPYD5EFpWCVRjDb3hslj4,492
|
|
264
|
+
sqlalchemy-2.1.4.dist-info/licenses/LICENSE,sha256=6GK7W5BPtVE8PhQojXoloS6w7MeEegqWXTEOmpVefLk,1100
|
|
265
|
+
sqlalchemy-2.1.4.dist-info/METADATA,sha256=VBbisMQ5oM7iGeIEldC9z43kICE7kpYZqYHIPQr5e_Y,9680
|
|
266
|
+
sqlalchemy-2.1.4.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
267
|
+
sqlalchemy-2.1.4.dist-info/top_level.txt,sha256=rp-ZgB7D8G11ivXON5VGPjupT1voYmWqkciDt5Uaw_Q,11
|
|
268
|
+
sqlalchemy-2.1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|