From: Federico Caselli Date: Tue, 18 Oct 2022 19:08:48 +0000 (+0200) Subject: Improve typing of DeclarativeBase X-Git-Tag: rel_2_0_0b2~5^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4e8777b03f194ff0012bdd32fabd8a398a93687b;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Improve typing of DeclarativeBase Also allow mapped columns inside indexes, unique cosntraints, primary key constriant Fixes: #8645 Change-Id: If37ab85ead0fbd1125cd6329c2f01a031777b081 --- diff --git a/doc/build/changelog/unreleased_20/8645.rst b/doc/build/changelog/unreleased_20/8645.rst new file mode 100644 index 0000000000..7745b41db3 --- /dev/null +++ b/doc/build/changelog/unreleased_20/8645.rst @@ -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__``. diff --git a/lib/sqlalchemy/orm/decl_api.py b/lib/sqlalchemy/orm/decl_api.py index a43b59a45c..e4a89cc80b 100644 --- a/lib/sqlalchemy/orm/decl_api.py +++ b/lib/sqlalchemy/orm/decl_api.py @@ -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): ... diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 841f29d15a..c67da3905f 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -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], diff --git a/test/ext/mypy/plain_files/declared_attr_one.py b/test/ext/mypy/plain_files/declared_attr_one.py index 969c86c3cd..a6d96f39ee 100644 --- a/test/ext/mypy/plain_files/declared_attr_one.py +++ b/test/ext/mypy/plain_files/declared_attr_one.py @@ -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__ = { diff --git a/test/ext/mypy/plain_files/declared_attr_two.py b/test/ext/mypy/plain_files/declared_attr_two.py index 863e79f39b..d2653a9208 100644 --- a/test/ext/mypy/plain_files/declared_attr_two.py +++ b/test/ext/mypy/plain_files/declared_attr_two.py @@ -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)