From ece524c0059d0814e45f4bba63abebd7e9af4b8b Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 21 Nov 2022 08:51:34 -0500 Subject: [PATCH] fall back to eval() for names that have dots Fixed regression in 2.0.0b3 caused by :ticket:`8759` where indicating the :class:`.Mapped` name using a qualified name such as ``sqlalchemy.orm.Mapped`` would fail to be recognized by Declarative as indicating the :class:`.Mapped` construct. Fixes: #8853 Change-Id: Iddb6efaae864d4545e80c54658244670f81ef6cc --- doc/build/changelog/unreleased_20/8853.rst | 8 ++++++++ lib/sqlalchemy/util/typing.py | 2 ++ .../declarative/test_tm_future_annotations.py | 17 +++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 doc/build/changelog/unreleased_20/8853.rst diff --git a/doc/build/changelog/unreleased_20/8853.rst b/doc/build/changelog/unreleased_20/8853.rst new file mode 100644 index 0000000000..97d1f08efa --- /dev/null +++ b/doc/build/changelog/unreleased_20/8853.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, orm + :tickets: 8853 + + Fixed regression in 2.0.0b3 caused by :ticket:`8759` where indicating the + :class:`.Mapped` name using a qualified name such as + ``sqlalchemy.orm.Mapped`` would fail to be recognized by Declarative as + indicating the :class:`.Mapped` construct. diff --git a/lib/sqlalchemy/util/typing.py b/lib/sqlalchemy/util/typing.py index 9eb761eff0..20ad148f81 100644 --- a/lib/sqlalchemy/util/typing.py +++ b/lib/sqlalchemy/util/typing.py @@ -141,6 +141,8 @@ def eval_expression(expression: str, module_name: str) -> Any: def eval_name_only(name: str, module_name: str) -> Any: + if "." in name: + return eval_expression(name, module_name) try: base_globals: Dict[str, Any] = sys.modules[module_name].__dict__ diff --git a/test/orm/declarative/test_tm_future_annotations.py b/test/orm/declarative/test_tm_future_annotations.py index d66b08f4e0..b63d856906 100644 --- a/test/orm/declarative/test_tm_future_annotations.py +++ b/test/orm/declarative/test_tm_future_annotations.py @@ -19,6 +19,7 @@ from sqlalchemy import String from sqlalchemy import Table from sqlalchemy import testing from sqlalchemy import Uuid +import sqlalchemy.orm from sqlalchemy.orm import attribute_keyed_dict from sqlalchemy.orm import DeclarativeBase from sqlalchemy.orm import DynamicMapped @@ -55,6 +56,22 @@ class M3: class MappedColumnTest(_MappedColumnTest): + def test_fully_qualified_mapped_name(self, decl_base): + """test #8853, regression caused by #8759 ;)""" # noqa: E501 + + class Foo(decl_base): + __tablename__ = "foo" + + id: sqlalchemy.orm.Mapped[int] = mapped_column(primary_key=True) + + data: sqlalchemy.orm.Mapped[int] = mapped_column() + + data2: sqlalchemy.orm.Mapped[int] + + self.assert_compile( + select(Foo), "SELECT foo.id, foo.data, foo.data2 FROM foo" + ) + def test_indirect_mapped_name_module_level(self, decl_base): """test #8759 -- 2.47.2