Skip to content

Commit 986d975

Browse files
NotCarlosSerranopre-commit-ci[bot]agronholm
authored
Improve Identity server_default rendering for Decimal values (#470)
* Enhance Identity column support for Decimal values in SQLAlchemy * Improve Identity server defaults rendering to support Decimal values * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix Identity server defaults to cast Decimal values to int * Improve rendering of Identity server defaults to explicitly handle Decimal values * Update src/sqlacodegen/generators.py Co-authored-by: Alex Grönholm <alex.gronholm@nextday.fi> * Refactor Identity server default handling to simplify Decimal value serialization * Refactor Identity handling to improve Decimal value serialization * Add test for Identity column with Decimal values in generator * Add test for Identity column with Decimal values * Fix Identity column Decimal value assignment using setattr * Add test for Identity column with Decimal values serialization * Refactor test for Identity column to directly assign Decimal values --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Alex Grönholm <alex.gronholm@nextday.fi>
1 parent 9234437 commit 986d975

3 files changed

Lines changed: 65 additions & 1 deletion

File tree

CHANGES.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
Version history
22
===============
33

4+
**UNRELEASED**
5+
6+
- Improved rendering of ``Identity`` server defaults by explicitly rendering
7+
non-default parameters; ``Decimal`` values (as returned by some databases) are
8+
now cast to ``int`` (PR by @NotCarlosSerrano)
9+
410
**4.0.2**
511

612
- Fixed rendering of inherited keyword arguments for dialect-specific types that use

src/sqlacodegen/generators.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from collections import defaultdict
88
from collections.abc import Collection, Iterable, Mapping, Sequence
99
from dataclasses import dataclass
10+
from decimal import Decimal
1011
from importlib import import_module
1112
from inspect import Parameter
1213
from itertools import count
@@ -521,7 +522,29 @@ def render_column(
521522
render_callable("Computed", repr(expression), kwargs=computed_kwargs)
522523
)
523524
elif isinstance(column.server_default, Identity):
524-
args.append(repr(column.server_default))
525+
identity = column.server_default
526+
identity_kwargs: dict[str, Any] = {}
527+
528+
for name, param in inspect.signature(Identity).parameters.items():
529+
if name == "self" or param.kind in (
530+
Parameter.VAR_POSITIONAL,
531+
Parameter.VAR_KEYWORD,
532+
):
533+
continue
534+
535+
value = getattr(identity, name, None)
536+
if value is None:
537+
continue
538+
539+
if isinstance(value, Decimal):
540+
value = int(value)
541+
542+
if param.default is not Parameter.empty and value == param.default:
543+
continue
544+
545+
identity_kwargs[name] = value
546+
547+
args.append(render_callable("Identity", kwargs=identity_kwargs))
525548
elif column.server_default:
526549
kwargs["server_default"] = repr(column.server_default)
527550

tests/test_generator_tables.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from decimal import Decimal
34
from textwrap import dedent
45

56
import pytest
@@ -1217,6 +1218,40 @@ def test_identity_column(generator: CodeGenerator) -> None:
12171218
)
12181219

12191220

1221+
def test_identity_column_decimal_values(generator: CodeGenerator) -> None:
1222+
# MSSQL reflects Identity column parameters (start, increment) as Decimal
1223+
# values instead of integers. This test ensures those are serialized correctly.
1224+
identity = Identity(start=1, increment=2)
1225+
# Simulate database reflection returning Decimal values (as MSSQL does)
1226+
identity.start = Decimal("1") # type: ignore[assignment]
1227+
identity.increment = Decimal("2") # type: ignore[assignment]
1228+
Table(
1229+
"simple_items",
1230+
generator.metadata,
1231+
Column(
1232+
"id",
1233+
INTEGER,
1234+
primary_key=True,
1235+
server_default=identity,
1236+
),
1237+
)
1238+
1239+
validate_code(
1240+
generator.generate(),
1241+
"""\
1242+
from sqlalchemy import Column, Identity, Integer, MetaData, Table
1243+
1244+
metadata = MetaData()
1245+
1246+
1247+
t_simple_items = Table(
1248+
'simple_items', metadata,
1249+
Column('id', Integer, Identity(start=1, increment=2), primary_key=True)
1250+
)
1251+
""",
1252+
)
1253+
1254+
12201255
def test_multiline_column_comment(generator: CodeGenerator) -> None:
12211256
Table(
12221257
"simple_items",

0 commit comments

Comments
 (0)