dbconform 0.2.1__tar.gz → 0.2.3__tar.gz
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.
- {dbconform-0.2.1/src/dbconform.egg-info → dbconform-0.2.3}/PKG-INFO +1 -1
- {dbconform-0.2.1 → dbconform-0.2.3}/pyproject.toml +2 -2
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/cli.py +7 -6
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/plan/builder.py +7 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/sql_dialect/postgresql.py +24 -5
- {dbconform-0.2.1 → dbconform-0.2.3/src/dbconform.egg-info}/PKG-INFO +1 -1
- {dbconform-0.2.1 → dbconform-0.2.3}/LICENSE +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/README.md +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/setup.cfg +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/__init__.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/adapters/__init__.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/adapters/model_schema.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/adapters/sa_to_neutral.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/compare/__init__.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/compare/db_schema.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/compare/diff.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/conform.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/errors.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/internal/__init__.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/internal/objects.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/internal/types.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/plan/__init__.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/plan/steps.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/schema/__init__.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/schema/db_schema.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/schema/diff.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/schema/model_schema.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/schema/objects.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/schema/sa_to_neutral.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/sql_dialect/__init__.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/sql_dialect/base.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/sql_dialect/sqlite.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform/sql_dialect/sqlite_rebuild.py +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform.egg-info/SOURCES.txt +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform.egg-info/dependency_links.txt +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform.egg-info/entry_points.txt +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform.egg-info/requires.txt +0 -0
- {dbconform-0.2.1 → dbconform-0.2.3}/src/dbconform.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dbconform"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "Synchronize database schema to models — document-driven project."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -61,7 +61,7 @@ where = ["src"]
|
|
|
61
61
|
dbconform = "dbconform.cli:main"
|
|
62
62
|
|
|
63
63
|
[tool.commitizen]
|
|
64
|
-
version = "0.2.
|
|
64
|
+
version = "0.2.3"
|
|
65
65
|
version_scheme = "semver"
|
|
66
66
|
commit = true
|
|
67
67
|
tag = true
|
|
@@ -14,23 +14,24 @@ import time
|
|
|
14
14
|
from importlib.metadata import PackageNotFoundError, version as pkg_version
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
-
from dbconform.sql_dialect.postgresql import try_connect_to_postgres
|
|
18
|
-
|
|
19
17
|
try:
|
|
20
18
|
import typer
|
|
21
19
|
except ImportError:
|
|
22
|
-
print(
|
|
23
|
-
|
|
20
|
+
print(
|
|
21
|
+
"To enable the CLI, install dbconform with optional development packages:\n\tpip install dbconform[dev]", # noqa: E501
|
|
22
|
+
file=sys.stderr,
|
|
23
|
+
)
|
|
24
24
|
sys.exit(1)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
from dbconform.sql_dialect.postgresql import try_connect_to_postgres
|
|
28
|
+
|
|
29
|
+
|
|
27
30
|
# Container constants (match tests/docker-compose.yml image)
|
|
28
31
|
POSTGRES_IMAGE = "postgres:16-alpine"
|
|
29
32
|
CONTAINER_NAME = "dbconform-postgres"
|
|
30
33
|
POSTGRES_PORT = 15432
|
|
31
34
|
POSTGRES_URL = f"postgresql://postgres:postgres@127.0.0.1:{POSTGRES_PORT}/postgres"
|
|
32
|
-
|
|
33
|
-
|
|
34
35
|
def _get_container_runtime_path_or_none() -> str | None:
|
|
35
36
|
"""Return docker or podman path if available, else None. Does not echo or exit."""
|
|
36
37
|
cmd = os.environ.get("DBCONFORM_CONTAINER_CMD", "").strip()
|
|
@@ -232,6 +232,13 @@ class ConformPlanBuilder:
|
|
|
232
232
|
alter_sql = self.dialect.alter_column_sql(name, old_col, new_col)
|
|
233
233
|
if alter_sql:
|
|
234
234
|
if self.dialect.would_shrink(old_col, new_col) and not self.allow_shrink_column:
|
|
235
|
+
skipped_steps.append(
|
|
236
|
+
SkippedStep(
|
|
237
|
+
description=f"Alter column {new_col.name} on {name}",
|
|
238
|
+
reason="Column shrink blocked: allow_shrink_column=False",
|
|
239
|
+
table_name=name,
|
|
240
|
+
)
|
|
241
|
+
)
|
|
235
242
|
continue
|
|
236
243
|
steps.append(
|
|
237
244
|
AlterTableStep(
|
|
@@ -223,13 +223,18 @@ class PostgreSQLDialect(Dialect):
|
|
|
223
223
|
|
|
224
224
|
def normalize_reflected_table(self, table_def: TableDef) -> TableDef:
|
|
225
225
|
"""
|
|
226
|
-
Normalize reflected table so
|
|
226
|
+
Normalize reflected table so it compares equal to model-side internal schema.
|
|
227
227
|
|
|
228
|
-
Columns with a sequence default (nextval) and integer-like type are rewritten
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
- Columns with a sequence default (nextval) and integer-like type are rewritten
|
|
229
|
+
to default=None, autoincrement=True, data_type_name=INTEGER|BIGINT so they match
|
|
230
|
+
the model's representation and no spurious ALTER steps are emitted.
|
|
231
|
+
- Implicit single-column UNIQUE constraints (e.g. habitat.name created from
|
|
232
|
+
column unique=True) are given auto-generated names like habitat_name_key
|
|
233
|
+
in PostgreSQL. Model-side UniqueDef for such constraints has name=None,
|
|
234
|
+
so we strip the auto-generated name here to avoid drop/add churn on recompare.
|
|
231
235
|
"""
|
|
232
236
|
INTEGER_LIKE = ("SERIAL", "INTEGER", "BIGSERIAL", "BIGINT", "INT8")
|
|
237
|
+
|
|
233
238
|
new_columns: list[ColumnDef] = []
|
|
234
239
|
for col in table_def.columns:
|
|
235
240
|
if (
|
|
@@ -266,11 +271,25 @@ class PostgreSQLDialect(Dialect):
|
|
|
266
271
|
autoincrement=False,
|
|
267
272
|
)
|
|
268
273
|
)
|
|
274
|
+
|
|
275
|
+
# Normalize unique constraint names for implicit single-column uniques.
|
|
276
|
+
new_uniques: list[UniqueDef] = []
|
|
277
|
+
table_name = table_def.name.name
|
|
278
|
+
for u in table_def.unique_constraints:
|
|
279
|
+
name = u.name
|
|
280
|
+
if name and len(u.column_names) == 1:
|
|
281
|
+
col = u.column_names[0]
|
|
282
|
+
auto_name = f"{table_name}_{col}_key"
|
|
283
|
+
if name == auto_name:
|
|
284
|
+
# Match model-side representation where name is None for column unique=True.
|
|
285
|
+
name = None
|
|
286
|
+
new_uniques.append(UniqueDef(name=name, column_names=u.column_names))
|
|
287
|
+
|
|
269
288
|
return TableDef(
|
|
270
289
|
name=table_def.name,
|
|
271
290
|
columns=tuple(new_columns),
|
|
272
291
|
primary_key=table_def.primary_key,
|
|
273
|
-
unique_constraints=
|
|
292
|
+
unique_constraints=tuple(new_uniques),
|
|
274
293
|
foreign_keys=table_def.foreign_keys,
|
|
275
294
|
check_constraints=table_def.check_constraints,
|
|
276
295
|
indexes=table_def.indexes,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|