diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6169c12b3a..96a5e5448b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: - id: local-ty name: ty check entry: >- - uv run ty check sqlmodel tests/test_field_sa_type.py + uv run ty check sqlmodel tests/test_dataclass_transform.py tests/test_field_sa_type.py tests/test_select_typing.py require_serial: true language: unsupported diff --git a/scripts/lint.sh b/scripts/lint.sh index a4717ec1c0..79c62bf0ec 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,6 +3,6 @@ set -e set -x -ty check sqlmodel tests/test_field_sa_type.py tests/test_select_typing.py +ty check sqlmodel tests/test_dataclass_transform.py tests/test_field_sa_type.py tests/test_select_typing.py ruff check sqlmodel tests docs_src scripts ruff format sqlmodel tests docs_src scripts --check diff --git a/sqlmodel/main.py b/sqlmodel/main.py index d94bd3e6cc..d325e99658 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -52,7 +52,7 @@ from sqlalchemy.sql.schema import MetaData from sqlalchemy.sql.sqltypes import LargeBinary, Time, Uuid from sqlalchemy.types import TypeEngine -from typing_extensions import deprecated +from typing_extensions import dataclass_transform, deprecated from ._compat import ( PYDANTIC_MINOR_VERSION, @@ -82,7 +82,6 @@ from pydantic_core import PydanticUndefined as Undefined from pydantic_core import PydanticUndefinedType as UndefinedType -_T = TypeVar("_T") NoArgAnyCallable = Callable[[], Any] IncEx: TypeAlias = ( set[int] @@ -101,16 +100,6 @@ ) -def __dataclass_transform__( - *, - eq_default: bool = True, - order_default: bool = False, - kw_only_default: bool = False, - field_descriptors: tuple[type | Callable[..., Any], ...] = (()), -) -> Callable[[_T], _T]: - return lambda a: a - - class FieldInfo(PydanticFieldInfo): # ty: ignore[subclass-of-final-class] # mypy - ignore that PydanticFieldInfo is @final def __init__(self, default: Any = Undefined, **kwargs: Any) -> None: @@ -565,7 +554,7 @@ def Relationship( return relationship_info -@__dataclass_transform__(kw_only_default=True, field_descriptors=(Field, FieldInfo)) +@dataclass_transform(kw_only_default=True, field_specifiers=(Field, FieldInfo)) class SQLModelMetaclass(ModelMetaclass, DeclarativeMeta): __sqlmodel_relationships__: dict[str, RelationshipInfo] model_config: SQLModelConfig diff --git a/tests/test_dataclass_transform.py b/tests/test_dataclass_transform.py new file mode 100644 index 0000000000..52c4b54712 --- /dev/null +++ b/tests/test_dataclass_transform.py @@ -0,0 +1,25 @@ +from typing import TYPE_CHECKING + +from sqlmodel import Field, SQLModel + + +def test_field_parameters() -> None: + class Hero(SQLModel): + name: str = Field() + secret_name: str = Field(alias="secretName") + age: int = Field(default=42) + tags: list[str] = Field(default_factory=list) + + hero = Hero(name="Deadpond", secretName="Dive Wilson") + other = Hero(name="Spider-Boy", secretName="Pedro Parqueador") + + assert hero.name == "Deadpond" + assert hero.secret_name == "Dive Wilson" + assert hero.age == 42 + assert hero.tags == [] + assert hero.tags is not other.tags + + if TYPE_CHECKING: + Hero(secretName="Dive Wilson") # ty: ignore[missing-argument] + Hero("Deadpond", "Dive Wilson") # ty: ignore[too-many-positional-arguments, missing-argument] + Hero(name=123, secretName="Dive Wilson") # ty: ignore[invalid-argument-type]