Skip to content

🐛 Fix pyright errors in type annotations and select() overloads#1820

Closed
estarfoo wants to merge 3 commits intofastapi:mainfrom
estarfoo:pyright-compatibility
Closed

🐛 Fix pyright errors in type annotations and select() overloads#1820
estarfoo wants to merge 3 commits intofastapi:mainfrom
estarfoo:pyright-compatibility

Conversation

@estarfoo
Copy link

This PR fixes three sources of pyright diagnostics for users of the library:

  • select() overloads: replace __-prefix positional-only convention with explicit / syntax (PEP 570, since Python 3.8), resolving pyright diagnostics in _expression_select_gen.py
  • sa_type annotation: widen from type[Any] to type[Any] | TypeEngine[Any], matching get_sqlalchemy_type() which already accepts instances like BigInteger()
  • __tablename__ override: move default from @declared_attr method to metaclass __new__, so __tablename__ = "my_table" no longer conflicts with the descriptor type. Fixes Pyright cannot recognize the type of SQLModel.__tablename__ #98

AI-generated, human-checked. All changes pass mypy strict and the existing test suite. Tests added for sa_type instances and __tablename__ override/inheritance.

Detailed examples for pyright diagnostics and before/after comparison: gist.

estarfoo and others added 3 commits March 18, 2026 13:03
Replace the `__`-prefix convention (PEP 484) with explicit `/` syntax
(PEP 570) for positional-only parameters in generated `select()` overloads.

Pyright enforces that `__`-prefixed (positional-only) parameters cannot
appear before non-prefixed parameters in the same signature, which caused
30 errors in `_expression_select_gen.py`. Mypy does not enforce this, so
it was never caught.

Both the Jinja2 template and the generator script are updated so that
`test_select_gen` continues to pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The `sa_type` parameter on `Field()` was typed as `type[Any]` (class
only), but the runtime in `get_sqlalchemy_type()` already accepts both
classes and instances.  Users passing instances like `BigInteger()` or
`Numeric(precision=10, scale=2)` got false type errors from pyright.

Widen the annotation to `type[Any] | TypeEngine[Any]` in the
`FieldInfoMetadata` dataclass, all three `Field()` overloads, and the
implementation.

Add tests for `BigInteger()` and `Numeric(...)` instances in
`test_field_sa_column.py`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The `SQLModel` base class declared `__tablename__` both as a `ClassVar`
and as a `@declared_attr` method.  Pyright saw the descriptor type from
`@declared_attr`, causing `reportAssignmentType` errors when subclasses
set `__tablename__ = "my_table"` — a pattern that works at runtime.

Replace the `@declared_attr` method with a default set in
`SQLModelMetaclass.__new__` via `dict_used`, before class creation.
This preserves the `ClassVar[str | Callable]` declaration and makes
plain string assignments work without type errors.

Fixes fastapi#98.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Member

@svlandeg svlandeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This has some overlap with #1806, which we're actively working on, so we'll get that one reviewed & merged first, then see whether there are any outstanding issues that need addressing here.

@estarfoo
Copy link
Author

Extra notes:

  • This does not drag pyright into the project or force anyone to use it in any way, it only adds compatibility for those who want to use sqlmodel and pyright together.
    • …Which is not meant to say that this is in any way encouraged or required by sqlmodel project documentation.
    • And I've deliberately omitted any pyright usage for automated tests.
  • I have zero experience with sqlmodel, and I don't know whether these changes might break downstream usage. Please review with caution.
  • The PR addresses only a subset of pyright diagnostics from those I've seen so far, but they make up most of the volume for my use case.

@YuriiMotov
Copy link
Member

As for sa_type, see #1345

@svlandeg
Copy link
Member

I have zero experience with sqlmodel, and I don't know whether these changes might break downstream usage. Please review with caution.

Hm, out of curiousity, if you have zero experience with sqlmodel, then why contribute a PR? You said you manually reviewed everything?

@estarfoo estarfoo marked this pull request as draft March 18, 2026 14:40
@estarfoo
Copy link
Author

Thank you both very much for the lightning-fast responses! I thought I had looked through open PRs, and I'm sorry for my lack of diligence.

@svlandeg, #1806 may fix my use case for select(), depending on the direction (and extent) it goes; I've left a note there, and I'll follow up with a new PR after that's merged in case there's anything left to do for pyright compatibility.

@YuriiMotov, would the test code in tests/test_field_sa_column.py from this PR be a good addition to #1345, or is that too noisy? (I think it won't affect coverage, only document the additional usage.)

I'll follow up with a PR addressing __tablename__ separately; setting this one as draft and I'll close it later on.

@estarfoo
Copy link
Author

Hm, out of curiousity, if you have zero experience with sqlmodel, then why contribute a PR? You said you manually reviewed everything?

@svlandeg, I've read (parts of) the library code and documentation, and I've tried to plug sqlmodel into my application as replacement for another ORM. Beyond that: I don't know the user community's idiomatic workflows. I can only hope that my changes are either conservative enough not to break anyone else's apps.

I tend to rely on IDE hints for call signatures and type inconsistencies. In my case that's VS Code, and it uses pyright under the hood. (Which has led me to pull pyright into my CI pipelines as well.) I could disable specific diagnostics, but they're exactly the ones that'd help me use the library correctly, if not for false positives. That's without any expectation that you should be using the same tools, or focus on supporting them here.

Thanks again for your feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pyright cannot recognize the type of SQLModel.__tablename__

4 participants