1
0
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:
MoonTestUse1
2025-02-09 01:11:49 +06:00
parent ce52f8a23a
commit 0aa3ef8fc2
5827 changed files with 14316 additions and 1906434 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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"

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)
"""

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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):

View File

@@ -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)),
)

View File

@@ -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

View File

@@ -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])

View File

@@ -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

View File

@@ -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",
)

View File

@@ -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

View File

@@ -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

View File

@@ -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})"
)

View File

@@ -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