False positive `unexpected-keyword` for inherited SQLAlchemy mapped columns in `Update.values()`

Open
#4,989 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
72/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
python, rust, sqlalchemy

Research direction

Start by running the supplied reproducer with Pyrefly 1.2.0 and 1.3.1, then locate the SQLAlchemy handling for Update.values() and the unexpected-keyword diagnostic. Add a regression test covering both the directly declared and inherited mapped columns, and verify that both calls are accepted.

Written by the indexing model from the issue text.

Description

sqlalchemy typechecking
Describe the Bug

Summary

Pyrefly 1.3.1 reports an unexpected-keyword error when an inherited SQLAlchemy mapped column is passed to Update.values(). A mapped column declared directly on the model is accepted. The same reproducer passes with Pyrefly 1.2.0, so this appears to be a regression.

Reproducer

pyproject.toml:

[project]
name = "pyrefly-sqlalchemy-inherited-columns-repro"
version = "0.1.0"
requires-python = ">=3.14"
dependencies = [
    "SQLAlchemy==2.0.52",
]

[tool.pyrefly]
python-version = "3.14"
preset = "strict"

repro.py:

from datetime import UTC, datetime

from sqlalchemy import update
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column


class Base(DeclarativeBase):
    pass


class TimestampMixin:
    created_at: Mapped[datetime] = mapped_column()


class Item(TimestampMixin, Base):
    __tablename__ = "items"

    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]


update(Item).values(name="updated")
update(Item).values(created_at=datetime.now(UTC))

Run:

$ uv run --with pyrefly==1.2.0 pyrefly check repro.py
 INFO 0 errors

$ uv run --with pyrefly==1.3.1 pyrefly check repro.py
ERROR Unexpected SQLAlchemy update field `created_at` [unexpected-keyword]
  --> repro.py:23:21

Expected behavior

Both calls to Update.values() should be accepted. created_at is a mapped column inherited from TimestampMixin and is present in Item.__table__.columns at runtime.

Actual behavior

Pyrefly 1.3.1 accepts the directly declared name field but rejects the inherited created_at field. Pyrefly 1.2.0 accepts both.

The update also executes successfully against SQLite at runtime.

Environment

  • Pyrefly: 1.3.1 (regression from 1.2.0)
  • Python: 3.14.7
  • SQLAlchemy: 2.0.52
  • OS: macOS 15.7.8
Sandbox Link

No response

(Only applicable for extension issues) IDE Information

No response

Dominant language
Rust
Stars
7k
Forks
521
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from facebook/pyrefly

All issues in facebook/pyrefly

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.