summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Mueller <15907922+kasium@users.noreply.github.com>2021-12-01 10:58:40 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2021-12-01 13:22:46 -0500
commit20fe2a3dc2597b04338e8907883c6f4ea72518c8 (patch)
tree3c0069d12a995684481bdcca3d604f851ca7c9bc
parent55e0497b080bf7f5159faa5abcb341269ebfdc7f (diff)
downloadsqlalchemy-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.rst9
-rw-r--r--lib/sqlalchemy/orm/decl_api.py2
-rw-r--r--test/orm/declarative/test_typing_py3k.py25
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)