diff options
author | Kai Mueller <15907922+kasium@users.noreply.github.com> | 2021-12-01 10:58:40 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-12-01 13:22:46 -0500 |
commit | 20fe2a3dc2597b04338e8907883c6f4ea72518c8 (patch) | |
tree | 3c0069d12a995684481bdcca3d604f851ca7c9bc | |
parent | 55e0497b080bf7f5159faa5abcb341269ebfdc7f (diff) | |
download | sqlalchemy-20fe2a3dc2597b04338e8907883c6f4ea72518c8.tar.gz |
Add __class_getitem__ to the declarative Base class
Fixed issue where the :func:`_orm.as_declarative` decorator and similar
functions used to generate the declarative base class would not copy the
``__class_getitem__()`` method from a given superclass, which prevented the
use of pep-484 generics in conjunction with the ``Base`` class. Pull
request courtesy Kai Mueller.
Fixes: #7368
Closes: #7381
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/7381
Pull-request-sha: 7db7fd869a6bb617f767fad5b71ddf7cb5f14ff5
Change-Id: I495718c3082ad6dd2c83fdbf6feba7c529e351cb
-rw-r--r-- | doc/build/changelog/unreleased_14/7368.rst | 9 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/decl_api.py | 2 | ||||
-rw-r--r-- | test/orm/declarative/test_typing_py3k.py | 25 |
3 files changed, 36 insertions, 0 deletions
diff --git a/doc/build/changelog/unreleased_14/7368.rst b/doc/build/changelog/unreleased_14/7368.rst new file mode 100644 index 000000000..d4415ffec --- /dev/null +++ b/doc/build/changelog/unreleased_14/7368.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, orm, mypy + :tickets: 7368 + + Fixed issue where the :func:`_orm.as_declarative` decorator and similar + functions used to generate the declarative base class would not copy the + ``__class_getitem__()`` method from a given superclass, which prevented the + use of pep-484 generics in conjunction with the ``Base`` class. Pull + request courtesy Kai Mueller. diff --git a/lib/sqlalchemy/orm/decl_api.py b/lib/sqlalchemy/orm/decl_api.py index 6bc857094..6951b3546 100644 --- a/lib/sqlalchemy/orm/decl_api.py +++ b/lib/sqlalchemy/orm/decl_api.py @@ -807,6 +807,8 @@ class registry: class_dict["__abstract__"] = True if mapper: class_dict["__mapper_cls__"] = mapper + if hasattr(cls, "__class_getitem__"): + class_dict["__class_getitem__"] = cls.__class_getitem__ return metaclass(name, bases, class_dict) diff --git a/test/orm/declarative/test_typing_py3k.py b/test/orm/declarative/test_typing_py3k.py new file mode 100644 index 000000000..823fe54f1 --- /dev/null +++ b/test/orm/declarative/test_typing_py3k.py @@ -0,0 +1,25 @@ +from typing import Generic +from typing import Type +from typing import TypeVar + +from sqlalchemy import Column +from sqlalchemy import Integer +from sqlalchemy.orm import as_declarative +from sqlalchemy.testing import fixtures + + +class DeclarativeBaseTest(fixtures.TestBase): + def test_class_getitem(self): + T = TypeVar("T", bound="CommonBase") # noqa + + class CommonBase(Generic[T]): + @classmethod + def boring(cls: Type[T]) -> Type[T]: + return cls + + @as_declarative() + class Base(CommonBase[T]): + pass + + class Tab(Base["Tab"]): + a = Column(Integer, primary_key=True) |