mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Проверка 09.02.2025
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# testing/__init__.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -83,6 +83,7 @@ from .util import provide_metadata
|
||||
from .util import resolve_lambda
|
||||
from .util import rowset
|
||||
from .util import run_as_contextmanager
|
||||
from .util import skip_if_timeout
|
||||
from .util import teardown_events
|
||||
from .warnings import assert_warnings
|
||||
from .warnings import warn_test_suite
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/assertions.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/assertsql.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/asyncio.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -24,16 +24,21 @@ from functools import wraps
|
||||
import inspect
|
||||
|
||||
from . import config
|
||||
from ..util.concurrency import _util_async_run
|
||||
from ..util.concurrency import _util_async_run_coroutine_function
|
||||
from ..util.concurrency import _AsyncUtil
|
||||
|
||||
# may be set to False if the
|
||||
# --disable-asyncio flag is passed to the test runner.
|
||||
ENABLE_ASYNCIO = True
|
||||
_async_util = _AsyncUtil() # it has lazy init so just always create one
|
||||
|
||||
|
||||
def _shutdown():
|
||||
"""called when the test finishes"""
|
||||
_async_util.close()
|
||||
|
||||
|
||||
def _run_coroutine_function(fn, *args, **kwargs):
|
||||
return _util_async_run_coroutine_function(fn, *args, **kwargs)
|
||||
return _async_util.run(fn, *args, **kwargs)
|
||||
|
||||
|
||||
def _assume_async(fn, *args, **kwargs):
|
||||
@@ -50,7 +55,7 @@ def _assume_async(fn, *args, **kwargs):
|
||||
if not ENABLE_ASYNCIO:
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
return _util_async_run(fn, *args, **kwargs)
|
||||
return _async_util.run_in_greenlet(fn, *args, **kwargs)
|
||||
|
||||
|
||||
def _maybe_async_provisioning(fn, *args, **kwargs):
|
||||
@@ -69,7 +74,7 @@ def _maybe_async_provisioning(fn, *args, **kwargs):
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
if config.any_async:
|
||||
return _util_async_run(fn, *args, **kwargs)
|
||||
return _async_util.run_in_greenlet(fn, *args, **kwargs)
|
||||
else:
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
@@ -89,7 +94,7 @@ def _maybe_async(fn, *args, **kwargs):
|
||||
is_async = config._current.is_async
|
||||
|
||||
if is_async:
|
||||
return _util_async_run(fn, *args, **kwargs)
|
||||
return _async_util.run_in_greenlet(fn, *args, **kwargs)
|
||||
else:
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/config.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -122,7 +122,9 @@ def combinations(
|
||||
passed, each argument combination is turned into a pytest.param() object,
|
||||
mapping the elements of the argument tuple to produce an id based on a
|
||||
character value in the same position within the string template using the
|
||||
following scheme::
|
||||
following scheme:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
i - the given argument is a string that is part of the id only, don't
|
||||
pass it as an argument
|
||||
@@ -146,7 +148,7 @@ def combinations(
|
||||
(operator.ne, "ne"),
|
||||
(operator.gt, "gt"),
|
||||
(operator.lt, "lt"),
|
||||
id_="na"
|
||||
id_="na",
|
||||
)
|
||||
def test_operator(self, opfunc, name):
|
||||
pass
|
||||
@@ -228,14 +230,9 @@ def variation(argname_or_fn, cases=None):
|
||||
|
||||
@testing.variation("querytyp", ["select", "subquery", "legacy_query"])
|
||||
@testing.variation("lazy", ["select", "raise", "raise_on_sql"])
|
||||
def test_thing(
|
||||
self,
|
||||
querytyp,
|
||||
lazy,
|
||||
decl_base
|
||||
):
|
||||
def test_thing(self, querytyp, lazy, decl_base):
|
||||
class Thing(decl_base):
|
||||
__tablename__ = 'thing'
|
||||
__tablename__ = "thing"
|
||||
|
||||
# use name directly
|
||||
rel = relationship("Rel", lazy=lazy.name)
|
||||
@@ -250,7 +247,6 @@ def variation(argname_or_fn, cases=None):
|
||||
else:
|
||||
querytyp.fail()
|
||||
|
||||
|
||||
The variable provided is a slots object of boolean variables, as well
|
||||
as the name of the case itself under the attribute ".name"
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/engines.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -330,16 +330,18 @@ def testing_engine(
|
||||
url = url or config.db.url
|
||||
|
||||
url = make_url(url)
|
||||
if options is None:
|
||||
if config.db is None or url.drivername == config.db.url.drivername:
|
||||
options = config.db_opts
|
||||
else:
|
||||
options = {}
|
||||
elif config.db is not None and url.drivername == config.db.url.drivername:
|
||||
default_opt = config.db_opts.copy()
|
||||
default_opt.update(options)
|
||||
|
||||
engine = create_engine(url, **options)
|
||||
if (
|
||||
config.db is None or url.drivername == config.db.url.drivername
|
||||
) and config.db_opts:
|
||||
use_options = config.db_opts.copy()
|
||||
else:
|
||||
use_options = {}
|
||||
|
||||
if options is not None:
|
||||
use_options.update(options)
|
||||
|
||||
engine = create_engine(url, **use_options)
|
||||
|
||||
if sqlite_savepoint and engine.name == "sqlite":
|
||||
# apply SQLite savepoint workaround
|
||||
@@ -368,7 +370,12 @@ def testing_engine(
|
||||
True # enable event blocks, helps with profiling
|
||||
)
|
||||
|
||||
if isinstance(engine.pool, pool.QueuePool):
|
||||
if (
|
||||
isinstance(engine.pool, pool.QueuePool)
|
||||
and "pool" not in use_options
|
||||
and "pool_timeout" not in use_options
|
||||
and "max_overflow" not in use_options
|
||||
):
|
||||
engine.pool._timeout = 0
|
||||
engine.pool._max_overflow = 0
|
||||
if use_reaper:
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/entities.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/exclusions.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/fixtures/__init__.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/fixtures/base.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/fixtures/mypy.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/fixtures/orm.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/fixtures/sql.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -459,6 +459,10 @@ def insertmanyvalues_fixture(
|
||||
# by not having the other methods we assert that those aren't being
|
||||
# used
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.cursor.description
|
||||
|
||||
def fetchall(self):
|
||||
rows = self.cursor.fetchall()
|
||||
rows = list(rows)
|
||||
@@ -466,22 +470,29 @@ def insertmanyvalues_fixture(
|
||||
return rows
|
||||
|
||||
def _deliver_insertmanyvalues_batches(
|
||||
cursor, statement, parameters, generic_setinputsizes, context
|
||||
connection,
|
||||
cursor,
|
||||
statement,
|
||||
parameters,
|
||||
generic_setinputsizes,
|
||||
context,
|
||||
):
|
||||
if randomize_rows:
|
||||
cursor = RandomCursor(cursor)
|
||||
for batch in orig_dialect(
|
||||
cursor, statement, parameters, generic_setinputsizes, context
|
||||
connection,
|
||||
cursor,
|
||||
statement,
|
||||
parameters,
|
||||
generic_setinputsizes,
|
||||
context,
|
||||
):
|
||||
if warn_on_downgraded and batch.is_downgraded:
|
||||
util.warn("Batches were downgraded for sorted INSERT")
|
||||
|
||||
yield batch
|
||||
|
||||
def _exec_insertmany_context(
|
||||
dialect,
|
||||
context,
|
||||
):
|
||||
def _exec_insertmany_context(dialect, context):
|
||||
with mock.patch.object(
|
||||
dialect,
|
||||
"_deliver_insertmanyvalues_batches",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/pickleable.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/plugin/__init__.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/plugin/bootstrap.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/plugin/plugin_base.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/plugin/pytestplugin.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -182,6 +182,12 @@ def pytest_sessionfinish(session):
|
||||
collect_types.dump_stats(session.config.option.dump_pyannotate)
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
from sqlalchemy.testing import asyncio
|
||||
|
||||
asyncio._shutdown()
|
||||
|
||||
|
||||
def pytest_collection_finish(session):
|
||||
if session.config.option.dump_pyannotate:
|
||||
from pyannotate_runtime import collect_types
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/profiling.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/provision.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -108,7 +108,9 @@ def generate_db_urls(db_urls, extra_drivers):
|
||||
"""Generate a set of URLs to test given configured URLs plus additional
|
||||
driver names.
|
||||
|
||||
Given::
|
||||
Given:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
--dburi postgresql://db1 \
|
||||
--dburi postgresql://db2 \
|
||||
@@ -116,7 +118,9 @@ def generate_db_urls(db_urls, extra_drivers):
|
||||
--dbdriver=psycopg2 --dbdriver=asyncpg?async_fallback=true
|
||||
|
||||
Noting that the default postgresql driver is psycopg2, the output
|
||||
would be::
|
||||
would be:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
postgresql+psycopg2://db1
|
||||
postgresql+asyncpg://db1
|
||||
@@ -133,6 +137,8 @@ def generate_db_urls(db_urls, extra_drivers):
|
||||
driver name. For example, to enable the async fallback option for
|
||||
asyncpg::
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
--dburi postgresql://db1 \
|
||||
--dbdriver=asyncpg?async_fallback=true
|
||||
|
||||
@@ -362,7 +368,7 @@ def update_db_opts(db_url, db_opts, options):
|
||||
def post_configure_engine(url, engine, follower_ident):
|
||||
"""Perform extra steps after configuring an engine for testing.
|
||||
|
||||
(For the internal dialects, currently only used by sqlite, oracle)
|
||||
(For the internal dialects, currently only used by sqlite, oracle, mssql)
|
||||
"""
|
||||
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/requirements.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -91,7 +91,9 @@ class SuiteRequirements(Requirements):
|
||||
|
||||
@property
|
||||
def table_value_constructor(self):
|
||||
"""Database / dialect supports a query like::
|
||||
"""Database / dialect supports a query like:
|
||||
|
||||
.. sourcecode:: sql
|
||||
|
||||
SELECT * FROM VALUES ( (c1, c2), (c1, c2), ...)
|
||||
AS some_table(col1, col2)
|
||||
@@ -796,6 +798,11 @@ class SuiteRequirements(Requirements):
|
||||
"""target dialect supports reflection of unique constraints"""
|
||||
return exclusions.open()
|
||||
|
||||
@property
|
||||
def inline_check_constraint_reflection(self):
|
||||
"""target dialect supports reflection of inline check constraints"""
|
||||
return exclusions.closed()
|
||||
|
||||
@property
|
||||
def check_constraint_reflection(self):
|
||||
"""target dialect supports reflection of check constraints"""
|
||||
@@ -987,7 +994,9 @@ class SuiteRequirements(Requirements):
|
||||
@property
|
||||
def binary_literals(self):
|
||||
"""target backend supports simple binary literals, e.g. an
|
||||
expression like::
|
||||
expression like:
|
||||
|
||||
.. sourcecode:: sql
|
||||
|
||||
SELECT CAST('foo' AS BINARY)
|
||||
|
||||
@@ -1093,6 +1102,11 @@ class SuiteRequirements(Requirements):
|
||||
|
||||
return exclusions.only_if(go)
|
||||
|
||||
@property
|
||||
def array_type(self):
|
||||
"""Target platform implements a native ARRAY type"""
|
||||
return exclusions.closed()
|
||||
|
||||
@property
|
||||
def json_type(self):
|
||||
"""target platform implements a native JSON type."""
|
||||
@@ -1163,9 +1177,7 @@ class SuiteRequirements(Requirements):
|
||||
|
||||
expr = decimal.Decimal("15.7563")
|
||||
|
||||
value = e.scalar(
|
||||
select(literal(expr))
|
||||
)
|
||||
value = e.scalar(select(literal(expr)))
|
||||
|
||||
assert value == expr
|
||||
|
||||
@@ -1333,7 +1345,9 @@ class SuiteRequirements(Requirements):
|
||||
present in a subquery in the WHERE clause.
|
||||
|
||||
This is an ANSI-standard syntax that apparently MySQL can't handle,
|
||||
such as::
|
||||
such as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
|
||||
UPDATE documents SET flag=1 WHERE documents.title IN
|
||||
(SELECT max(documents.title) AS title
|
||||
@@ -1366,7 +1380,11 @@ class SuiteRequirements(Requirements):
|
||||
"""target database supports ordering by a column from a SELECT
|
||||
inside of a UNION
|
||||
|
||||
E.g. (SELECT id, ...) UNION (SELECT id, ...) ORDER BY id
|
||||
E.g.:
|
||||
|
||||
.. sourcecode:: sql
|
||||
|
||||
(SELECT id, ...) UNION (SELECT id, ...) ORDER BY id
|
||||
|
||||
"""
|
||||
return exclusions.open()
|
||||
@@ -1376,7 +1394,9 @@ class SuiteRequirements(Requirements):
|
||||
"""target backend supports ORDER BY a column label within an
|
||||
expression.
|
||||
|
||||
Basically this::
|
||||
Basically this:
|
||||
|
||||
.. sourcecode:: sql
|
||||
|
||||
select data as foo from test order by foo || 'bar'
|
||||
|
||||
@@ -1781,3 +1801,28 @@ class SuiteRequirements(Requirements):
|
||||
def materialized_views_reflect_pk(self):
|
||||
"""Target database reflect MATERIALIZED VIEWs pks."""
|
||||
return exclusions.closed()
|
||||
|
||||
@property
|
||||
def supports_bitwise_or(self):
|
||||
"""Target database supports bitwise or"""
|
||||
return exclusions.closed()
|
||||
|
||||
@property
|
||||
def supports_bitwise_and(self):
|
||||
"""Target database supports bitwise and"""
|
||||
return exclusions.closed()
|
||||
|
||||
@property
|
||||
def supports_bitwise_not(self):
|
||||
"""Target database supports bitwise not"""
|
||||
return exclusions.closed()
|
||||
|
||||
@property
|
||||
def supports_bitwise_xor(self):
|
||||
"""Target database supports bitwise xor"""
|
||||
return exclusions.closed()
|
||||
|
||||
@property
|
||||
def supports_bitwise_shift(self):
|
||||
"""Target database supports bitwise left or right shift"""
|
||||
return exclusions.closed()
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/schema.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/__init__.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_cte.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_ddl.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_deprecations.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_dialect.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_insert.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,11 +1,12 @@
|
||||
# testing/suite/test_reflection.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
||||
# mypy: ignore-errors
|
||||
|
||||
import contextlib
|
||||
import operator
|
||||
import re
|
||||
|
||||
@@ -2454,62 +2455,158 @@ class TableNoColumnsTest(fixtures.TestBase):
|
||||
class ComponentReflectionTestExtra(ComparesIndexes, fixtures.TestBase):
|
||||
__backend__ = True
|
||||
|
||||
@testing.combinations(
|
||||
(True, testing.requires.schemas), (False,), argnames="use_schema"
|
||||
)
|
||||
@testing.requires.check_constraint_reflection
|
||||
def test_get_check_constraints(self, metadata, connection, use_schema):
|
||||
if use_schema:
|
||||
schema = config.test_schema
|
||||
@testing.fixture(params=[True, False])
|
||||
def use_schema_fixture(self, request):
|
||||
if request.param:
|
||||
return config.test_schema
|
||||
else:
|
||||
schema = None
|
||||
return None
|
||||
|
||||
Table(
|
||||
"sa_cc",
|
||||
metadata,
|
||||
Column("a", Integer()),
|
||||
sa.CheckConstraint("a > 1 AND a < 5", name="cc1"),
|
||||
sa.CheckConstraint(
|
||||
"a = 1 OR (a > 2 AND a < 5)", name="UsesCasing"
|
||||
),
|
||||
schema=schema,
|
||||
)
|
||||
Table(
|
||||
"no_constraints",
|
||||
metadata,
|
||||
Column("data", sa.String(20)),
|
||||
schema=schema,
|
||||
)
|
||||
@testing.fixture()
|
||||
def inspect_for_table(self, metadata, connection, use_schema_fixture):
|
||||
@contextlib.contextmanager
|
||||
def go(tablename):
|
||||
yield use_schema_fixture, inspect(connection)
|
||||
|
||||
metadata.create_all(connection)
|
||||
metadata.create_all(connection)
|
||||
|
||||
insp = inspect(connection)
|
||||
reflected = sorted(
|
||||
insp.get_check_constraints("sa_cc", schema=schema),
|
||||
key=operator.itemgetter("name"),
|
||||
)
|
||||
return go
|
||||
|
||||
def ck_eq(self, reflected, expected):
|
||||
# trying to minimize effect of quoting, parenthesis, etc.
|
||||
# may need to add more to this as new dialects get CHECK
|
||||
# constraint reflection support
|
||||
def normalize(sqltext):
|
||||
return " ".join(
|
||||
re.findall(r"and|\d|=|a|or|<|>", sqltext.lower(), re.I)
|
||||
re.findall(r"and|\d|=|a|b|c|or|<|>", sqltext.lower(), re.I)
|
||||
)
|
||||
|
||||
reflected = [
|
||||
{"name": item["name"], "sqltext": normalize(item["sqltext"])}
|
||||
for item in reflected
|
||||
]
|
||||
eq_(
|
||||
reflected = sorted(
|
||||
[
|
||||
{"name": item["name"], "sqltext": normalize(item["sqltext"])}
|
||||
for item in reflected
|
||||
],
|
||||
key=lambda item: (item["sqltext"]),
|
||||
)
|
||||
|
||||
expected = sorted(
|
||||
expected,
|
||||
key=lambda item: (item["sqltext"]),
|
||||
)
|
||||
eq_(reflected, expected)
|
||||
|
||||
@testing.requires.check_constraint_reflection
|
||||
def test_check_constraint_no_constraint(self, metadata, inspect_for_table):
|
||||
with inspect_for_table("no_constraints") as (schema, inspector):
|
||||
Table(
|
||||
"no_constraints",
|
||||
metadata,
|
||||
Column("data", sa.String(20)),
|
||||
schema=schema,
|
||||
)
|
||||
|
||||
self.ck_eq(
|
||||
inspector.get_check_constraints("no_constraints", schema=schema),
|
||||
[],
|
||||
)
|
||||
|
||||
@testing.requires.inline_check_constraint_reflection
|
||||
@testing.combinations(
|
||||
"my_inline", "MyInline", None, argnames="constraint_name"
|
||||
)
|
||||
def test_check_constraint_inline(
|
||||
self, metadata, inspect_for_table, constraint_name
|
||||
):
|
||||
|
||||
with inspect_for_table("sa_cc") as (schema, inspector):
|
||||
Table(
|
||||
"sa_cc",
|
||||
metadata,
|
||||
Column("id", Integer(), primary_key=True),
|
||||
Column(
|
||||
"a",
|
||||
Integer(),
|
||||
sa.CheckConstraint(
|
||||
"a > 1 AND a < 5", name=constraint_name
|
||||
),
|
||||
),
|
||||
Column("data", String(50)),
|
||||
schema=schema,
|
||||
)
|
||||
|
||||
reflected = inspector.get_check_constraints("sa_cc", schema=schema)
|
||||
|
||||
self.ck_eq(
|
||||
reflected,
|
||||
[
|
||||
{"name": "UsesCasing", "sqltext": "a = 1 or a > 2 and a < 5"},
|
||||
{"name": "cc1", "sqltext": "a > 1 and a < 5"},
|
||||
{
|
||||
"name": constraint_name or mock.ANY,
|
||||
"sqltext": "a > 1 and a < 5",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
@testing.requires.check_constraint_reflection
|
||||
@testing.combinations(
|
||||
"my_ck_const", "MyCkConst", None, argnames="constraint_name"
|
||||
)
|
||||
def test_check_constraint_standalone(
|
||||
self, metadata, inspect_for_table, constraint_name
|
||||
):
|
||||
with inspect_for_table("sa_cc") as (schema, inspector):
|
||||
Table(
|
||||
"sa_cc",
|
||||
metadata,
|
||||
Column("a", Integer()),
|
||||
sa.CheckConstraint(
|
||||
"a = 1 OR (a > 2 AND a < 5)", name=constraint_name
|
||||
),
|
||||
schema=schema,
|
||||
)
|
||||
|
||||
reflected = inspector.get_check_constraints("sa_cc", schema=schema)
|
||||
|
||||
self.ck_eq(
|
||||
reflected,
|
||||
[
|
||||
{
|
||||
"name": constraint_name or mock.ANY,
|
||||
"sqltext": "a = 1 or a > 2 and a < 5",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
@testing.requires.inline_check_constraint_reflection
|
||||
def test_check_constraint_mixed(self, metadata, inspect_for_table):
|
||||
with inspect_for_table("sa_cc") as (schema, inspector):
|
||||
Table(
|
||||
"sa_cc",
|
||||
metadata,
|
||||
Column("id", Integer(), primary_key=True),
|
||||
Column("a", Integer(), sa.CheckConstraint("a > 1 AND a < 5")),
|
||||
Column(
|
||||
"b",
|
||||
Integer(),
|
||||
sa.CheckConstraint("b > 1 AND b < 5", name="my_inline"),
|
||||
),
|
||||
Column("c", Integer()),
|
||||
Column("data", String(50)),
|
||||
sa.UniqueConstraint("data", name="some_uq"),
|
||||
sa.CheckConstraint("c > 1 AND c < 5", name="cc1"),
|
||||
sa.UniqueConstraint("c", name="some_c_uq"),
|
||||
schema=schema,
|
||||
)
|
||||
|
||||
reflected = inspector.get_check_constraints("sa_cc", schema=schema)
|
||||
|
||||
self.ck_eq(
|
||||
reflected,
|
||||
[
|
||||
{"name": "cc1", "sqltext": "c > 1 and c < 5"},
|
||||
{"name": "my_inline", "sqltext": "b > 1 and b < 5"},
|
||||
{"name": mock.ANY, "sqltext": "a > 1 and a < 5"},
|
||||
],
|
||||
)
|
||||
no_cst = "no_constraints"
|
||||
eq_(insp.get_check_constraints(no_cst, schema=schema), [])
|
||||
|
||||
@testing.requires.indexes_with_expressions
|
||||
def test_reflect_expression_based_indexes(self, metadata, connection):
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_results.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -7,6 +7,7 @@
|
||||
# mypy: ignore-errors
|
||||
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from .. import engines
|
||||
from .. import fixtures
|
||||
@@ -273,6 +274,8 @@ class ServerSideCursorsTest(
|
||||
return getattr(cursor, "server_side", False)
|
||||
elif self.engine.dialect.driver == "psycopg":
|
||||
return bool(getattr(cursor, "name", False))
|
||||
elif self.engine.dialect.driver == "oracledb":
|
||||
return getattr(cursor, "server_side", False)
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -293,11 +296,26 @@ class ServerSideCursorsTest(
|
||||
)
|
||||
return self.engine
|
||||
|
||||
def stringify(self, str_):
|
||||
return re.compile(r"SELECT (\d+)", re.I).sub(
|
||||
lambda m: str(select(int(m.group(1))).compile(testing.db)), str_
|
||||
)
|
||||
|
||||
@testing.combinations(
|
||||
("global_string", True, "select 1", True),
|
||||
("global_text", True, text("select 1"), True),
|
||||
("global_string", True, lambda stringify: stringify("select 1"), True),
|
||||
(
|
||||
"global_text",
|
||||
True,
|
||||
lambda stringify: text(stringify("select 1")),
|
||||
True,
|
||||
),
|
||||
("global_expr", True, select(1), True),
|
||||
("global_off_explicit", False, text("select 1"), False),
|
||||
(
|
||||
"global_off_explicit",
|
||||
False,
|
||||
lambda stringify: text(stringify("select 1")),
|
||||
False,
|
||||
),
|
||||
(
|
||||
"stmt_option",
|
||||
False,
|
||||
@@ -315,15 +333,22 @@ class ServerSideCursorsTest(
|
||||
(
|
||||
"for_update_string",
|
||||
True,
|
||||
"SELECT 1 FOR UPDATE",
|
||||
lambda stringify: stringify("SELECT 1 FOR UPDATE"),
|
||||
True,
|
||||
testing.skip_if(["sqlite", "mssql"]),
|
||||
),
|
||||
("text_no_ss", False, text("select 42"), False),
|
||||
(
|
||||
"text_no_ss",
|
||||
False,
|
||||
lambda stringify: text(stringify("select 42")),
|
||||
False,
|
||||
),
|
||||
(
|
||||
"text_ss_option",
|
||||
False,
|
||||
text("select 42").execution_options(stream_results=True),
|
||||
lambda stringify: text(stringify("select 42")).execution_options(
|
||||
stream_results=True
|
||||
),
|
||||
True,
|
||||
),
|
||||
id_="iaaa",
|
||||
@@ -334,6 +359,11 @@ class ServerSideCursorsTest(
|
||||
):
|
||||
engine = self._fixture(engine_ss_arg)
|
||||
with engine.begin() as conn:
|
||||
if callable(statement):
|
||||
statement = testing.resolve_lambda(
|
||||
statement, stringify=self.stringify
|
||||
)
|
||||
|
||||
if isinstance(statement, str):
|
||||
result = conn.exec_driver_sql(statement)
|
||||
else:
|
||||
@@ -348,7 +378,7 @@ class ServerSideCursorsTest(
|
||||
# should be enabled for this one
|
||||
result = conn.execution_options(
|
||||
stream_results=True
|
||||
).exec_driver_sql("select 1")
|
||||
).exec_driver_sql(self.stringify("select 1"))
|
||||
assert self._is_server_side(result.cursor)
|
||||
|
||||
# the connection has autobegun, which means at the end of the
|
||||
@@ -402,7 +432,9 @@ class ServerSideCursorsTest(
|
||||
test_table = Table(
|
||||
"test_table",
|
||||
md,
|
||||
Column("id", Integer, primary_key=True),
|
||||
Column(
|
||||
"id", Integer, primary_key=True, test_needs_autoincrement=True
|
||||
),
|
||||
Column("data", String(50)),
|
||||
)
|
||||
|
||||
@@ -442,7 +474,9 @@ class ServerSideCursorsTest(
|
||||
test_table = Table(
|
||||
"test_table",
|
||||
md,
|
||||
Column("id", Integer, primary_key=True),
|
||||
Column(
|
||||
"id", Integer, primary_key=True, test_needs_autoincrement=True
|
||||
),
|
||||
Column("data", String(50)),
|
||||
)
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_rowcount.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_select.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -1886,3 +1886,114 @@ class IsOrIsNotDistinctFromTest(fixtures.TablesTest):
|
||||
len(result),
|
||||
expected_row_count_for_is_not,
|
||||
)
|
||||
|
||||
|
||||
class WindowFunctionTest(fixtures.TablesTest):
|
||||
__requires__ = ("window_functions",)
|
||||
|
||||
__backend__ = True
|
||||
|
||||
@classmethod
|
||||
def define_tables(cls, metadata):
|
||||
Table(
|
||||
"some_table",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True),
|
||||
Column("col1", Integer),
|
||||
Column("col2", Integer),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def insert_data(cls, connection):
|
||||
connection.execute(
|
||||
cls.tables.some_table.insert(),
|
||||
[{"id": i, "col1": i, "col2": i * 5} for i in range(1, 50)],
|
||||
)
|
||||
|
||||
def test_window(self, connection):
|
||||
some_table = self.tables.some_table
|
||||
rows = connection.execute(
|
||||
select(
|
||||
func.max(some_table.c.col2).over(
|
||||
order_by=[some_table.c.col1.desc()]
|
||||
)
|
||||
).where(some_table.c.col1 < 20)
|
||||
).all()
|
||||
|
||||
eq_(rows, [(95,) for i in range(19)])
|
||||
|
||||
def test_window_rows_between(self, connection):
|
||||
some_table = self.tables.some_table
|
||||
|
||||
# note the rows are part of the cache key right now, not handled
|
||||
# as binds. this is issue #11515
|
||||
rows = connection.execute(
|
||||
select(
|
||||
func.max(some_table.c.col2).over(
|
||||
order_by=[some_table.c.col1],
|
||||
rows=(-5, 0),
|
||||
)
|
||||
)
|
||||
).all()
|
||||
|
||||
eq_(rows, [(i,) for i in range(5, 250, 5)])
|
||||
|
||||
|
||||
class BitwiseTest(fixtures.TablesTest):
|
||||
__backend__ = True
|
||||
run_inserts = run_deletes = "once"
|
||||
|
||||
inserted_data = [{"a": i, "b": i + 1} for i in range(10)]
|
||||
|
||||
@classmethod
|
||||
def define_tables(cls, metadata):
|
||||
Table("bitwise", metadata, Column("a", Integer), Column("b", Integer))
|
||||
|
||||
@classmethod
|
||||
def insert_data(cls, connection):
|
||||
connection.execute(cls.tables.bitwise.insert(), cls.inserted_data)
|
||||
|
||||
@testing.combinations(
|
||||
(
|
||||
lambda a: a.bitwise_xor(5),
|
||||
[i for i in range(10) if i != 5],
|
||||
testing.requires.supports_bitwise_xor,
|
||||
),
|
||||
(
|
||||
lambda a: a.bitwise_or(1),
|
||||
list(range(10)),
|
||||
testing.requires.supports_bitwise_or,
|
||||
),
|
||||
(
|
||||
lambda a: a.bitwise_and(4),
|
||||
list(range(4, 8)),
|
||||
testing.requires.supports_bitwise_and,
|
||||
),
|
||||
(
|
||||
lambda a: (a - 2).bitwise_not(),
|
||||
[0],
|
||||
testing.requires.supports_bitwise_not,
|
||||
),
|
||||
(
|
||||
lambda a: a.bitwise_lshift(1),
|
||||
list(range(1, 10)),
|
||||
testing.requires.supports_bitwise_shift,
|
||||
),
|
||||
(
|
||||
lambda a: a.bitwise_rshift(2),
|
||||
list(range(4, 10)),
|
||||
testing.requires.supports_bitwise_shift,
|
||||
),
|
||||
argnames="case, expected",
|
||||
)
|
||||
def test_bitwise(self, case, expected, connection):
|
||||
tbl = self.tables.bitwise
|
||||
|
||||
a = tbl.c.a
|
||||
|
||||
op = testing.resolve_lambda(case, a=a)
|
||||
|
||||
stmt = select(tbl).where(op > 0).order_by(a)
|
||||
|
||||
res = connection.execute(stmt).mappings().all()
|
||||
eq_(res, [self.inserted_data[i] for i in expected])
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_sequence.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_types.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -32,6 +32,7 @@ from ... import case
|
||||
from ... import cast
|
||||
from ... import Date
|
||||
from ... import DateTime
|
||||
from ... import Enum
|
||||
from ... import Float
|
||||
from ... import Integer
|
||||
from ... import Interval
|
||||
@@ -1918,6 +1919,74 @@ class JSONLegacyStringCastIndexTest(
|
||||
)
|
||||
|
||||
|
||||
class EnumTest(_LiteralRoundTripFixture, fixtures.TablesTest):
|
||||
__backend__ = True
|
||||
|
||||
enum_values = "a", "b", "a%", "b%percent", "réveillé"
|
||||
|
||||
datatype = Enum(*enum_values, name="myenum")
|
||||
|
||||
@classmethod
|
||||
def define_tables(cls, metadata):
|
||||
Table(
|
||||
"enum_table",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True),
|
||||
Column("enum_data", cls.datatype),
|
||||
)
|
||||
|
||||
@testing.combinations(*enum_values, argnames="data")
|
||||
def test_round_trip(self, data, connection):
|
||||
connection.execute(
|
||||
self.tables.enum_table.insert(), {"id": 1, "enum_data": data}
|
||||
)
|
||||
|
||||
eq_(
|
||||
connection.scalar(
|
||||
select(self.tables.enum_table.c.enum_data).where(
|
||||
self.tables.enum_table.c.id == 1
|
||||
)
|
||||
),
|
||||
data,
|
||||
)
|
||||
|
||||
def test_round_trip_executemany(self, connection):
|
||||
connection.execute(
|
||||
self.tables.enum_table.insert(),
|
||||
[
|
||||
{"id": 1, "enum_data": "b%percent"},
|
||||
{"id": 2, "enum_data": "réveillé"},
|
||||
{"id": 3, "enum_data": "b"},
|
||||
{"id": 4, "enum_data": "a%"},
|
||||
],
|
||||
)
|
||||
|
||||
eq_(
|
||||
connection.scalars(
|
||||
select(self.tables.enum_table.c.enum_data).order_by(
|
||||
self.tables.enum_table.c.id
|
||||
)
|
||||
).all(),
|
||||
["b%percent", "réveillé", "b", "a%"],
|
||||
)
|
||||
|
||||
@testing.requires.insert_executemany_returning
|
||||
def test_round_trip_executemany_returning(self, connection):
|
||||
result = connection.execute(
|
||||
self.tables.enum_table.insert().returning(
|
||||
self.tables.enum_table.c.enum_data
|
||||
),
|
||||
[
|
||||
{"id": 1, "enum_data": "b%percent"},
|
||||
{"id": 2, "enum_data": "réveillé"},
|
||||
{"id": 3, "enum_data": "b"},
|
||||
{"id": 4, "enum_data": "a%"},
|
||||
],
|
||||
)
|
||||
|
||||
eq_(result.scalars().all(), ["b%percent", "réveillé", "b", "a%"])
|
||||
|
||||
|
||||
class UuidTest(_LiteralRoundTripFixture, fixtures.TablesTest):
|
||||
__backend__ = True
|
||||
|
||||
@@ -2066,6 +2135,7 @@ __all__ = (
|
||||
"DateHistoricTest",
|
||||
"StringTest",
|
||||
"BooleanTest",
|
||||
"EnumTest",
|
||||
"UuidTest",
|
||||
"NativeUUIDTest",
|
||||
)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_unicode_ddl.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/suite/test_update_delete.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/util.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -10,13 +10,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import deque
|
||||
import contextlib
|
||||
import decimal
|
||||
import gc
|
||||
from itertools import chain
|
||||
import random
|
||||
import sys
|
||||
from sys import getsizeof
|
||||
import time
|
||||
import types
|
||||
from typing import Any
|
||||
|
||||
from . import config
|
||||
from . import mock
|
||||
@@ -251,18 +254,19 @@ def flag_combinations(*combinations):
|
||||
dict(lazy=False, passive=True),
|
||||
dict(lazy=False, passive=True, raiseload=True),
|
||||
)
|
||||
|
||||
def test_fn(lazy, passive, raiseload): ...
|
||||
|
||||
would result in::
|
||||
|
||||
@testing.combinations(
|
||||
('', False, False, False),
|
||||
('lazy', True, False, False),
|
||||
('lazy_passive', True, True, False),
|
||||
('lazy_passive', True, True, True),
|
||||
id_='iaaa',
|
||||
argnames='lazy,passive,raiseload'
|
||||
("", False, False, False),
|
||||
("lazy", True, False, False),
|
||||
("lazy_passive", True, True, False),
|
||||
("lazy_passive", True, True, True),
|
||||
id_="iaaa",
|
||||
argnames="lazy,passive,raiseload",
|
||||
)
|
||||
def test_fn(lazy, passive, raiseload): ...
|
||||
|
||||
"""
|
||||
|
||||
@@ -517,3 +521,18 @@ def count_cache_key_tuples(tup):
|
||||
if elem:
|
||||
stack = list(elem) + [sentinel] + stack
|
||||
return num_elements
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def skip_if_timeout(seconds: float, cleanup: Any = None):
|
||||
|
||||
now = time.time()
|
||||
yield
|
||||
sec = time.time() - now
|
||||
if sec > seconds:
|
||||
try:
|
||||
cleanup()
|
||||
finally:
|
||||
config.skip_test(
|
||||
f"test took too long ({sec:.4f} seconds > {seconds})"
|
||||
)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# testing/warnings.py
|
||||
# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
Reference in New Issue
Block a user