declared_attr.cascading fails to typecheck under mypy / pyright on documented usage
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
- #13736 par @xixi-box — fermée sans fusion
Évaluation
- Difficulté
- 2/5
- Temps estimé
- 1-3 heures
- Accessibilité débutants
- 76/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Active
- Stack technique
- python, sqlalchemy
- Domaine
- backend, databases, testing-qa
Piste de recherche
Commencez dans lib/sqlalchemy/orm/decl_api.py et comparez _stateful_declared_attr.__call__ à _declared_directive.__call__, comme l’issue le signale pour la différence présumée concernant la variable de type. Vérifiez l’utilisation documentée de declared_attr.cascading avec mypy et pyright, puis exécutez les tests de typage pertinents. Le travail est terminé lorsque l’exemple documenté passe la vérification de types et que les types révélés de ses attributs sont précis.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Ensure stubs packages are not installed
- No sqlalchemy stub packages is installed (both
sqlalchemy-stubsandsqlalchemy2-stubsare not compatible with v2)
Verify if the api is typed
- The api is not in a module listed in #6810 so it should pass type checking
Describe the typing issue
@declared_attr.cascading produces a mypy/pyright error when used as documented.
The error seems to be in the library's annotations, not in user-side code.
Adding @classmethod as the 2.1 docs recommend for declared_attr, gives the same error with Callable[[type[HasUser]], ...]. Unfortunately, I didn't find a workaround.
The probable cause is:
_stateful_declared_attr.__call__ reuses the class level _T_co type variable, which is already bound by the time declared_attr.cascading is accessed, so nothing is left to solve and no argument matches. The sibling method _declared_directive.__call__ introduces a fresh _TT type variable and works correctly as expected
To Reproduce
from typing import reveal_type
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import declared_attr
from sqlalchemy.orm import has_inherited_table
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
class Base(DeclarativeBase):
pass
class HasIdMixin:
@declared_attr.cascading
@classmethod
def id(cls) -> Mapped[int]:
if has_inherited_table(cls):
return mapped_column(ForeignKey("person.id"), primary_key=True)
else:
return mapped_column(Integer, primary_key=True)
class Person(HasIdMixin, Base):
__tablename__ = "person"
discriminator: Mapped[str]
__mapper_args__ = {"polymorphic_on": "discriminator"}
class Engineer(Person):
__tablename__ = "engineer"
primary_language: Mapped[str]
__mapper_args__ = {"polymorphic_identity": "engineer"}
reveal_type(Engineer.id) # Expected: InstrumentedAttribute[int], actual: InstrumentedAttribute[_T`1] (mypy)
reveal_type(Engineer().id) # Expected: int, actual: _T`1 (mypy)
Error
mypy 1.15.0
sqlalc_issue.py:17: error: Argument 1 to "__call__" of "_stateful_declared_attr" has incompatible type "Callable[[type[HasIdMixin]], Mapped[int]]"; expected "Callable[..., Mapped[_T] | ORMDescriptor[_T] | SQLCoreOperations[_T]]" [arg-type]
sqlalc_issue.py:40: note: Revealed type is "sqlalchemy.orm.attributes.InstrumentedAttribute[_T`1]"
sqlalc_issue.py:41: note: Revealed type is "_T`1"
Found 1 error in 1 file (checked 1 source file)
pyright 1.1.414
/Users/daniil.kalinin/PyCharmMiscProject/sqlalc_issue.py
/Users/daniil.kalinin/PyCharmMiscProject/sqlalc_issue.py:40:13 - information: Type of "Engineer.id" is "InstrumentedAttribute[Unknown]"
/Users/daniil.kalinin/PyCharmMiscProject/sqlalc_issue.py:41:13 - information: Type of "Engineer().id" is "Unknown"
0 errors, 0 warnings, 2 informations
Versions
- OS: macOS 26.7.1
- Python: 3.15.1
- SQLAlchemy: 2.1.6
- Type checker (eg: mypy 0.991, pyright 1.1.290, etc): mypy 1.15.0, pyright 1.1.414
Additional context
The fix should be quite easy:
file: lib/sqlalchemy/orm/decl_api.py
def __call__(
- self, fn: _DeclaredAttrDecorated[_T_co]
- ) -> declared_attr[_T_co]:
+ self, fn: _DeclaredAttrDecorated[_TT]
+ ) -> declared_attr[_TT]:
return declared_attr(fn, **self.kw)
I would be happy to create a PR
- Langage dominant
- Python
- Étoiles
- 12.3k
- Forks
- 1.8k
- Merge moyen
- 2 j 10 h
- PR mergées (30 j)
- 9
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de sqlalchemy/sqlalchemy
-
requires triage
Difficulté 1/5 1-3 heures Accessibilité débutants 85/100
sqlalchemy/sqlalchemy#13784 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
bug engine
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
sqlalchemy/sqlalchemy#13770 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
PostgreSQL multihost URL with bracketed IPv6 hosts raises ValueError: too many values to unpackPeut-être à nouveau libre Une pull request pour cette issue a été fermée sans être fusionnée. Ouvertebug engine postgresql
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
sqlalchemy/sqlalchemy#13637 · 6 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
asyncpg dialect raises DBAPIError, not DataError, for SQLSTATE class 22 errorsPeut-être pris @HardMax71 l’a pris il y a 20 jours. Ouvertebug code review in progress dialects
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
sqlalchemy/sqlalchemy#13636 · 19 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
documentation bugPeut-être à nouveau libre Une pull request pour cette issue a été fermée sans être fusionnée. Ouvertedocumentation
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
sqlalchemy/sqlalchemy#13594 · 2 commentaires · 5 réactions ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de sqlalchemy/sqlalchemy
Issues similaires
-
Unknown stop ID in slow zone data crashes post formatting and skips the rest of that day's postsOuvertebackend bug tm-new-volunteer
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
transitmatters/mbta-slow-zone-bot#81 · 1 commentaire ·
-
area:schema documentation
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
Les mainteneurs répondent en général sous 1 jour
-
risk:high type:ci
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 64/100
spacetelescope/rdmt-spire#49 ·
Les mainteneurs répondent en général sous 1 jour