]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Improve typing of DeclarativeBase
authorFederico Caselli <cfederico87@gmail.com>
Tue, 18 Oct 2022 19:08:48 +0000 (21:08 +0200)
committerFederico Caselli <cfederico87@gmail.com>
Wed, 19 Oct 2022 20:02:26 +0000 (22:02 +0200)
Also allow mapped columns inside indexes, unique cosntraints, primary key constriant

Fixes: #8645
Change-Id: If37ab85ead0fbd1125cd6329c2f01a031777b081

doc/build/changelog/unreleased_20/8645.rst [new file with mode: 0644]
lib/sqlalchemy/orm/decl_api.py
lib/sqlalchemy/orm/properties.py
test/ext/mypy/plain_files/declared_attr_one.py
test/ext/mypy/plain_files/declared_attr_two.py

diff --git a/doc/build/changelog/unreleased_20/8645.rst b/doc/build/changelog/unreleased_20/8645.rst
new file mode 100644 (file)
index 0000000..7745b41
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: bug, typing
+    :tickets: 8645
+
+    Fixed typing issue where pylance strict mode would report "instance
+    variable overrides class variable" when using a method to define
+    ``__tablename__``, ``__mapper_args__`` or ``__table_args__``.
index a43b59a45c7e3813202a5ae1d3b1ca3f3714b6c4..e4a89cc80bc632609abd155637ea88748069b7d8 100644 (file)
@@ -684,7 +684,11 @@ class DeclarativeBase(
         __mapper__: ClassVar[Mapper[Any]]
         __table__: ClassVar[Optional[FromClause]]
 
-        __tablename__: ClassVar[Any]
+        # pyright/pylance do not consider a classmethod a ClassVar so use Any
+        # https://github.com/microsoft/pylance-release/issues/3484
+        __tablename__: Any
+        __mapper_args__: Any
+        __table_args__: Any
 
         def __init__(self, **kw: Any):
             ...
index 841f29d15a4031039e36981636afbc4194da6807..c67da3905f42bc368a7071782925535dc7b93e66 100644 (file)
@@ -48,6 +48,7 @@ from ..sql import roles
 from ..sql import sqltypes
 from ..sql.base import _NoArg
 from ..sql.elements import SQLCoreOperations
+from ..sql.roles import DDLConstraintColumnRole
 from ..sql.schema import Column
 from ..sql.schema import SchemaConst
 from ..util.typing import de_optionalize_union_types
@@ -499,6 +500,7 @@ class MappedSQLExpression(ColumnProperty[_T], _DeclarativeMapped[_T]):
 
 
 class MappedColumn(
+    DDLConstraintColumnRole,
     SQLCoreOperations[_T],
     _IntrospectsAnnotations,
     _MapsColumns[_T],
index 969c86c3cd5c2dd8fb97fd0c9067ba471ff515b8..a6d96f39ee53bfb8b03db080b040cf6d3fb66f31 100644 (file)
@@ -2,12 +2,15 @@ from datetime import datetime
 import typing
 
 from sqlalchemy import DateTime
+from sqlalchemy import Index
 from sqlalchemy import Integer
 from sqlalchemy import String
+from sqlalchemy import UniqueConstraint
 from sqlalchemy.orm import DeclarativeBase
 from sqlalchemy.orm import declared_attr
 from sqlalchemy.orm import Mapped
 from sqlalchemy.orm import mapped_column
+from sqlalchemy.sql.schema import PrimaryKeyConstraint
 
 
 class Base(DeclarativeBase):
@@ -25,6 +28,13 @@ class Employee(Base):
         "polymorphic_identity": "employee",
     }
 
+    __table_args__ = (
+        Index("my_index", name, type),
+        UniqueConstraint(name),
+        PrimaryKeyConstraint(id),
+        {"prefix": []},
+    )
+
 
 class Engineer(Employee):
     __mapper_args__ = {
index 863e79f39bb15495faf6478a0731c0a461286d2b..d2653a9208695558013b985ba4f987a791ba97c5 100644 (file)
@@ -31,7 +31,7 @@ class User(HasRelatedDataMixin, Base):
 
 
 class Foo(Base):
-    __tablename__: typing.ClassVar[str] = "foo"
+    __tablename__ = "foo"
 
     id = mapped_column(Integer, primary_key=True)