collerek/ormar

Model field types and pyright

Opened this issue · 0 comments

Is your feature request related to a problem? Please describe.
This is a broad follow-up to #25, concerning pyright warnings for ormar model fields. I am using ormar 0.20.0, which pulls pydantic 2.5.3 by exact dependency version match, with Python 3.12. I have also encountered this issue with earlier ormar versions, using pre-v2 pydantic. For pyright, I am using version 1.1.358, but a wide range of earlier versions have shown the same behaviour.

Given code like this:

class Demo(ormar.Model):
    ormar_config = ormar.OrmarConfig(database=db, metadata=md)

    foo: str = ormar.Text(primary_key=True)
    bar: float | None = ormar.Float()

pyright produces diagnostics on each model field:

  error: Expression of type "BaseField" cannot be assigned to declared type "str"
    "BaseField" is incompatible with "str" (reportAssignmentType)
  error: Expression of type "BaseField" cannot be assigned to declared type "float | None"
    Type "BaseField" cannot be assigned to type "float | None"
      "BaseField" is incompatible with "float"
      "BaseField" is incompatible with "None" (reportAssignmentType)
2 errors, 0 warnings, 0 informations 

From searching Google, the issue list here, and the usual forums, my impression is that everybody’s solution consists of disabling type checking for ormar models, i. e. annotating either every field or entire files with # type: ignore comments, or disabling type checking for model files via configuration. If that is still the only way to deal with this: fine.

Describe the solution you'd like
I would like to have a way of defining model fields which works in ormar and passes, not bypasses, pyright verification.

Describe alternatives you've considered
I have briefly tried the following, using typing.Annotated, because I like the look & feel with pydantic parameters for constraints, validation and serialization:

class Demo(ormar.Model):
    ormar_config = ormar.OrmarConfig(database=db, metadata=md)

    foo: Annotated[str, Field(default=ormar.Text(primary_key=True))]
    bar: Annotated[float | None, Field(default=ormar.Float())]

And, even more optimistically, this:

class Demo(ormar.Model):
    ormar_config = ormar.OrmarConfig(database=db, metadata=md)

    foo: Annotated[str, Field(), ormar.Text(primary_key=True)]
    bar: Annotated[float | None, Field(), ormar.Float()]

Either way, these fields vanish completely from the model definition:

WARNING:root:Table demos had no fields so auto Integer primary key named `id` created.

And deserialization, e. g. from database records, triggers errors concerning missing properties.

(I understand that the ormar documentation does not suggest in any way that this, or anything like it, should work.)

Additional context
I’ve put the above code snippets in a minimal runnable demo: https://github.com/estarfoo/ormar-pyright-demo

While this is a feature request, I don’t have any specific expectation as to the exact solution, if one is possible. I’m also open to the idea that I’ve made a trivial mistake somewhere, and this should otherwise already work. 😅

Finally, I understand that one solution to this issue is not to use pyright.