API refactor
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-10-07 16:25:52 +09:00
parent 76d0d86211
commit 91c7e04474
1171 changed files with 81940 additions and 44117 deletions

View File

@@ -14,6 +14,7 @@ from sqlalchemy import inspect
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import Numeric
from sqlalchemy import PrimaryKeyConstraint
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import Text
@@ -149,6 +150,118 @@ class ModelOne:
return m
class NamingConvModel:
__requires__ = ("unique_constraint_reflection",)
configure_opts = {"conv_all_constraint_names": True}
naming_convention = {
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(constraint_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
@classmethod
def _get_db_schema(cls):
# database side - assume all constraints have a name that
# we would assume here is a "db generated" name. need to make
# sure these all render with op.f().
m = MetaData()
Table(
"x1",
m,
Column("q", Integer),
Index("db_x1_index_q", "q"),
PrimaryKeyConstraint("q", name="db_x1_primary_q"),
)
Table(
"x2",
m,
Column("q", Integer),
Column("p", ForeignKey("x1.q", name="db_x2_foreign_q")),
CheckConstraint("q > 5", name="db_x2_check_q"),
)
Table(
"x3",
m,
Column("q", Integer),
Column("r", Integer),
Column("s", Integer),
UniqueConstraint("q", name="db_x3_unique_q"),
)
Table(
"x4",
m,
Column("q", Integer),
PrimaryKeyConstraint("q", name="db_x4_primary_q"),
)
Table(
"x5",
m,
Column("q", Integer),
Column("p", ForeignKey("x4.q", name="db_x5_foreign_q")),
Column("r", Integer),
Column("s", Integer),
PrimaryKeyConstraint("q", name="db_x5_primary_q"),
UniqueConstraint("r", name="db_x5_unique_r"),
CheckConstraint("s > 5", name="db_x5_check_s"),
)
# SQLite and it's "no names needed" thing. bleh.
# we can't have a name for these so you'll see "None" for the name.
Table(
"unnamed_sqlite",
m,
Column("q", Integer),
Column("r", Integer),
PrimaryKeyConstraint("q"),
UniqueConstraint("r"),
)
return m
@classmethod
def _get_model_schema(cls):
from sqlalchemy.sql.naming import conv
m = MetaData(naming_convention=cls.naming_convention)
Table(
"x1", m, Column("q", Integer, primary_key=True), Index(None, "q")
)
Table(
"x2",
m,
Column("q", Integer),
Column("p", ForeignKey("x1.q")),
CheckConstraint("q > 5", name="token_x2check1"),
)
Table(
"x3",
m,
Column("q", Integer),
Column("r", Integer),
Column("s", Integer),
UniqueConstraint("r", name="token_x3r"),
UniqueConstraint("s", name=conv("userdef_x3_unique_s")),
)
Table(
"x4",
m,
Column("q", Integer, primary_key=True),
Index("userdef_x4_idx_q", "q"),
)
Table(
"x6",
m,
Column("q", Integer, primary_key=True),
Column("p", ForeignKey("x4.q")),
Column("r", Integer),
Column("s", Integer),
UniqueConstraint("r", name="token_x6r"),
CheckConstraint("s > 5", "token_x6check1"),
CheckConstraint("s < 20", conv("userdef_x6_check_s")),
)
return m
class _ComparesFKs:
def _assert_fk_diff(
self,

View File

@@ -6,9 +6,7 @@ from sqlalchemy import Table
from ._autogen_fixtures import AutogenFixtureTest
from ... import testing
from ...testing import config
from ...testing import eq_
from ...testing import exclusions
from ...testing import is_
from ...testing import is_true
from ...testing import mock
@@ -63,18 +61,8 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
c = diffs[0][3]
eq_(c.name, "foo")
if config.requirements.computed_reflects_normally.enabled:
is_true(isinstance(c.computed, sa.Computed))
else:
is_(c.computed, None)
if config.requirements.computed_reflects_as_server_default.enabled:
is_true(isinstance(c.server_default, sa.DefaultClause))
eq_(str(c.server_default.arg.text), "5")
elif config.requirements.computed_reflects_normally.enabled:
is_true(isinstance(c.computed, sa.Computed))
else:
is_(c.computed, None)
is_true(isinstance(c.computed, sa.Computed))
is_true(isinstance(c.server_default, sa.Computed))
@testing.combinations(
lambda: (None, sa.Computed("bar*5")),
@@ -85,7 +73,6 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
),
lambda: (sa.Computed("bar*5"), sa.Computed("bar * 42")),
)
@config.requirements.computed_reflects_normally
def test_cant_change_computed_warning(self, test_case):
arg_before, arg_after = testing.resolve_lambda(test_case, **locals())
m1 = MetaData()
@@ -124,10 +111,7 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
lambda: (None, None),
lambda: (sa.Computed("5"), sa.Computed("5")),
lambda: (sa.Computed("bar*5"), sa.Computed("bar*5")),
(
lambda: (sa.Computed("bar*5"), None),
config.requirements.computed_doesnt_reflect_as_server_default,
),
lambda: (sa.Computed("bar*5"), sa.Computed("bar * \r\n\t5")),
)
def test_computed_unchanged(self, test_case):
arg_before, arg_after = testing.resolve_lambda(test_case, **locals())
@@ -158,46 +142,3 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
eq_(mock_warn.mock_calls, [])
eq_(list(diffs), [])
@config.requirements.computed_reflects_as_server_default
def test_remove_computed_default_on_computed(self):
"""Asserts the current behavior which is that on PG and Oracle,
the GENERATED ALWAYS AS is reflected as a server default which we can't
tell is actually "computed", so these come out as a modification to
the server default.
"""
m1 = MetaData()
m2 = MetaData()
Table(
"user",
m1,
Column("id", Integer, primary_key=True),
Column("bar", Integer),
Column("foo", Integer, sa.Computed("bar + 42")),
)
Table(
"user",
m2,
Column("id", Integer, primary_key=True),
Column("bar", Integer),
Column("foo", Integer),
)
diffs = self._fixture(m1, m2)
eq_(diffs[0][0][0], "modify_default")
eq_(diffs[0][0][2], "user")
eq_(diffs[0][0][3], "foo")
old = diffs[0][0][-2]
new = diffs[0][0][-1]
is_(new, None)
is_true(isinstance(old, sa.DefaultClause))
if exclusions.against(config, "postgresql"):
eq_(str(old.arg.text), "(bar + 42)")
elif exclusions.against(config, "oracle"):
eq_(str(old.arg.text), '"BAR"+42')

View File

@@ -24,9 +24,9 @@ class MigrationTransactionTest(TestBase):
self.context = MigrationContext.configure(
dialect=conn.dialect, opts=opts
)
self.context.output_buffer = (
self.context.impl.output_buffer
) = io.StringIO()
self.context.output_buffer = self.context.impl.output_buffer = (
io.StringIO()
)
else:
self.context = MigrationContext.configure(
connection=conn, opts=opts