sqlalchemy-stubs icon indicating copy to clipboard operation
sqlalchemy-stubs copied to clipboard

Can not set nullable relationship to None

Open lexicalunit opened this issue 3 years ago • 2 comments

Given the following relationship:

class Game(Base):
    __tablename__ = "games"
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    users = relationship("User", back_populates="game")

class User(Base):
    __tablename__ = "users"
    xid = Column(BigInteger, primary_key=True, nullable=False)
    game_id = Column(Integer, ForeignKey("games.id", ondelete="SET NULL"), nullable=True)
    game = relationship("Game", back_populates="users")

I'm trying to do the following in the application:

user.game = None

This should be fine and it does work as intended in practice, however I get an error from mypy:

error: Incompatible types in assignment (expression has type "None", variable has type "Game")

lexicalunit avatar Jul 22 '20 19:07 lexicalunit

Note that the workaround in this case would be to use user.game_id = None instead, but I feel like that's not as nice as being able to use the relationship as intended.

lexicalunit avatar Jul 22 '20 20:07 lexicalunit

@lexicalunit a simple but not ideal workaround would be:

game = cast(Optional[Game], relationship("Game", back_populates="users"))

If I understand it correctly, making it work nicer would require creating a plugin. It could be similar to the one supporting Column, which enables support for nullable and some other column parameters.

In that case, the plugin would need to know whether the foreign key column is nullable or not, which could be inferred from the foreign_keys argument, i.e.:

game = relationship("Game", foreign_keys=game_id, back_populates="users")

killthekitten avatar Jul 22 '20 22:07 killthekitten