Repository navigation
Why are select()'s scalar TypeVars constrained rather than bounded?
#2125
Replies: 1 comment
|
I can't speak to the original intent: the constrained form has been there since the first commit ( from datetime import date
from decimal import Decimal
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
status: Status = Status.ACTIVE # StrEnum
born: date = date(2000, 1, 1)
salary: Decimal = Decimal("1.5")
session.exec(select(Hero.status)).all() # mypy/pyright: Sequence[str] (enum collapses to the constraint)
session.exec(select(Hero.born)).all() # mypy: No overload variant of "select" matches argument type "date"
session.exec(select(Hero.salary)).all() # mypy: No overload variant of "select" matches argument type "Decimal"
session.exec(select(col(Hero.born))).all() # Sequence[date]On SQLModel 0.0.48 with mypy 2.4.1, both So the two behaviours you saw have the same cause. A constrained TypeVar must solve to exactly one of the listed types, so a subclass ( Until something changes, |
Uh oh!
There was an error while loading. Please reload this page.
First Check
Example Code
Description
I'm migrating a SQLModel project from mypy to ty. After the switch, ty reported
no-matching-overloadon calls likesession.exec(select(Hero.name))that mypy accepts. That turned out to be a ty regression, which I reported in astral-sh/ty#4892.While looking into it, I noticed that the
_TScalar_*TypeVars thatselect()uses for single columns are constrained (TypeVar("_TScalar_0", Column, Sequence, Mapping, UUID, datetime, float, int, bool, bytes, str, None)). Out of curiosity, I tried changing them locally to a bound with the same types:That avoids the ty problem. It also changes what mypy and pyright infer for some columns, and the results look more accurate to me. The example above prints
ACTIVEand['Deadpond', None]at runtime. With SQLModel 0.0.48 as it is:statusesstatuses[0].namenicknamesSequence[str]"str" has no attribute "name"Sequence[str] | Sequence[None]Sequence[str]Cannot access attribute "name" for class "str"Sequence[str] | Sequence[None]Sequence[Unknown]Sequence[Unknown]With the bound, all three infer
Sequence[Status]andSequence[str | None]with no errors.Of course the general advice is to use
col().select(col(Hero.status))andselect(col(Hero.nickname))give those same accurate types on the current release, so this is less a report than a question: is there a reason these are constrained rather than bounded?Operating System
Linux
Operating System Details
No response
Project Version
0.0.48
Python Version
3.14.9
Additional Context
No response
All reactions