Flask SQL Alchemy and MyPy error with db.model - Incompatible types in assignment
Asked Answered
H

1

6
error: Incompatible types in assignment (expression has type "Type[Any]", variable has type "DefaultMeta")  [assignment]
error: Variable "application.models.BaseModel" is not valid as a type  [valid-type]

Previously it worked when it was declared like this

from sqlalchemy.ext.declarative import DeclarativeMeta
BaseModel: DeclarativeMeta = db.Model

But after packages update I'm seeing that error again. I've read from here that DeclarativeMeta was moved to sqlalchemy.orm, but when tried

from sqlalchemy.orm import DeclarativeMeta
BaseModel: DeclarativeMeta = db.Model

I can still see the error. I've also noticed that sometimes flask_sqlalchemy is used

from flask_sqlalchemy.model import DefaultMeta
BaseModel: DefaultMeta = db.Model

but that makes no difference I'm still seeing that mypy error.

Current version of packages is this:

mypy                   │ 1.1.1
SQLAlchemy             │ 2.0.6
Flask-SQLAlchemy       │ 3.0.3

Does somebody know how write this so mypy is happy? I can always make mypy ignore it, but I somehow want to have this right.

Homeopathist answered 18/3, 2023 at 6:54 Comment(1)
Same over here. Tired of the # type: ignore[assignment]Tucky
E
1

So, I ran into this myself and took an unreasonable amount of time to try and figure it out. I'm on Flask-SQLAlchemy 3.1.1, and there the incompatible type is not Type[Any] but type[_FSAModel]. Same general issue though I suppose.

Long story short, what works for me:

from typing import TYPE_CHECKING
...
if TYPE_CHECKING:
    from flask_sqlalchemy.model import Model
else:
    Model = db.Model
...
class MyModel(Model):
...

I used Model instead of BaseModel here, but otherwise a similar idea to the workaround you mention. I found this one in MyPy issue 8603.

There's another workaround recommended by the Flask-SQLAlchemy project: Just ignore name-defined errors for model classes. Unfortunately, that also ends up ignoring attr-defined in the model class for me, actually made me miss an issue that MyPy normally would have caught.

Since it took me a few hours to arrive at a workaround that works for me, I wrote a lengthy issue in the Flask-SQLAlchemy project, hoping we'll get some documentation on the existing workarounds and their pros/cons.

Reading a whole bunch of issues in both Flask-SQLAlchemy and MyPy, I doubt there'll be something more than workarounds any time soon.

Efficacious answered 22/4 at 8:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.