It seems that mypy
is having problems taking into account all the superclasses and reports missing attributes. Here is a simple example:
import uuid
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import String
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import mapped_column, DeclarativeBase
db = SQLAlchemy()
class Base(DeclarativeBase):
pass
class IdMixin:
id = mapped_column(UUID(as_uuid=True), nullable=False, default=uuid.uuid4, primary_key=True)
class ImageMixin:
image_name = mapped_column(String, default=None)
image_uri = mapped_column(String, default=None)
class Model(IdMixin, Base):
pass
class Post(Model, ImageMixin):
content = mapped_column(String)
class Comment(Model, ImageMixin):
text = mapped_column(String)
def generate_image_uri(image_name: str) -> str:
return f"https://example.com/{image_name}"
models = [Comment, Post]
for model in models:
entities = db.session.query(model).all()
for entity in entities:
entity.image_uri = generate_image_uri(image_name=entity.image_name) # Line 45
Mypy reports:
mypy-warning.py:45: error: "Model" has no attribute "image_uri" [attr-defined]
mypy-warning.py:45: error: "Model" has no attribute "image_name" [attr-defined]
It works just fine when I move the ImageMixin
to the Model
class and then only subclass Model
in the Post
and Comment
classes, but this is not what I want as I don’t necessarily want all models to mix in the image functionality.