mypy plugin: infer relationship information for models specified as strings
See original GitHub issueIs your feature request related to a problem? Please describe.
Currently the mypy plugin can infer types/information for a relationship
when the model parameter is an actual class value, but cannot do so when it is a string:
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import as_declarative
from typing import List, Optional
@as_declarative()
class Base:
pass
class Foo(Base):
id = Column(Integer(), primary_key=True)
bars = relationship("Bar", back_populates="foo", uselist=True)
# error, must be: bars: List["Bar"] = relationship("Bar", back_populates="foo", uselist=True)
class Bar(Base):
id = Column(Integer(), primary_key=True)
foo_id: Optional[int] = Column(ForeignKey(Foo.id))
foo = relationship(Foo, back_populates="bars", uselist=False)
# successful inference:
reveal_type(Bar().foo) # Union[test2.Foo, None]
Describe the solution you’d like
In https://github.com/sqlalchemy/sqlalchemy/discussions/6372, we discussed that string parameters could be handled via doing a name lookup in the current module, similar to the plugin in https://github.com/dropbox/sqlalchemy-stubs. This requires the other model name being imported (potentially in an if TYPE_CHECKING:
block), but that’s okay: doing the explicit type annotation also requires the name being in scope for mypy.
(This approach could potentially be used for Column(ForeignKey("Abc.def"), ...)
too, but it was mentioned in #6372 that doing the .def
lookup might be hard.)
Describe alternatives you’ve considered
The current situation of annotating the type explicitly is a little suboptimal, as the plugin doesn’t validate, that, for instance, the collection types are correct. Another option would to have the righthand side be partially inferred, e.g. list[_]
and then do a type join between LHS and RHS; if the LHS annotation is list[Bar]
, then the join will be successful, but if it’s very wrong (e.g. just Bar
), then the join(Bar, list[_])
will not be possible an error can be reported.
Additional context N/A
Have a nice day! you too 😄
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (4 by maintainers)
I guess we can close as will not fix since v2 will not use the plugin
it’s all in 2.0 now, docs are not up yet save for the quickstart at https://docs.sqlalchemy.org/en/20/orm/quickstart.html where you can see relationship() works in the most minimal way possible, inferring the class from the string annotation.