From 6ae7f2378971b16f024eb5ab851cc4533bc4e61a Mon Sep 17 00:00:00 2001 From: Federico Caselli Date: Wed, 9 Oct 2024 20:35:16 +0200 Subject: [PATCH] Improve error in dataclasses with table Added a better error when trying to map as dataclass a class while also manually providing the ``__table__`` attribute. This usage is currently not supported. Fixes: #11973 Change-Id: I54c721b3f7447b2f062fa0cfb53b6a88c381df42 --- doc/build/changelog/unreleased_20/11973.rst | 7 +++++++ lib/sqlalchemy/orm/decl_base.py | 10 ++++++++++ test/orm/declarative/test_dc_transforms.py | 16 ++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 doc/build/changelog/unreleased_20/11973.rst diff --git a/doc/build/changelog/unreleased_20/11973.rst b/doc/build/changelog/unreleased_20/11973.rst new file mode 100644 index 0000000000..bad0f22088 --- /dev/null +++ b/doc/build/changelog/unreleased_20/11973.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: orm, bug + :tickets: 11973 + + Improved the error message emitted when trying to map as dataclass a class + while also manually providing the ``__table__`` attribute. + This usage is currently not supported. diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py index 271c61a8b6..8b42a32dfb 100644 --- a/lib/sqlalchemy/orm/decl_base.py +++ b/lib/sqlalchemy/orm/decl_base.py @@ -1067,6 +1067,16 @@ class _ClassScanMapperConfig(_MapperConfig): "'@registry.mapped_as_dataclass'" ) + # can't create a dataclass if __table__ is already there. This would + # fail an assertion when calling _get_arguments_for_make_dataclass: + # assert False, "Mapped[] received without a mapping declaration" + if "__table__" in self.cls.__dict__: + raise exc.InvalidRequestError( + f"Class {self.cls} already defines a '__table__'. " + "ORM Annotated Dataclasses do not support a pre-existing " + "'__table__' element" + ) + warn_for_non_dc_attrs = collections.defaultdict(list) def _allow_dataclass_field( diff --git a/test/orm/declarative/test_dc_transforms.py b/test/orm/declarative/test_dc_transforms.py index 8408f69617..4c4f158513 100644 --- a/test/orm/declarative/test_dc_transforms.py +++ b/test/orm/declarative/test_dc_transforms.py @@ -27,6 +27,7 @@ from sqlalchemy import Integer from sqlalchemy import JSON from sqlalchemy import select from sqlalchemy import String +from sqlalchemy import Table from sqlalchemy import testing from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.orm import column_property @@ -742,6 +743,21 @@ class DCTransformsTest(AssertsCompiledSQL, fixtures.TestBase): class Foo(Mixin): bar_value: Mapped[float] = mapped_column(default=78) + def test_MappedAsDataclass_table_provided(self, registry): + """test #11973""" + + with expect_raises_message( + exc.InvalidRequestError, + "Class .*Foo.* already defines a '__table__'. " + "ORM Annotated Dataclasses do not support a pre-existing " + "'__table__' element", + ): + + @registry.mapped_as_dataclass + class Foo: + __table__ = Table("foo", registry.metadata) + foo: Mapped[float] + def test_dataclass_exception_wrapped(self, dc_decl_base): with expect_raises_message( exc.InvalidRequestError, -- 2.47.3