Skip to content

Docs: condecimal gives type error "Illegal type annotation: call expression not allowed" #354

Description

@cassieopea

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the SQLModel documentation, with the integrated search.
  • I already searched in Google "How to X in SQLModel" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to SQLModel but to Pydantic.
  • I already checked if it is not related to SQLModel but to SQLAlchemy.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

from pydantic import condecimal
from sqlmodel import Field, SQLModel


class Lineitem(SQLModel, table=True):
    price: condecimal(max_digits=5, decimal_places=2) = Field(default=0)

Description

The above code yields a Pylance error in VsCode:

Illegal type annotation: call expression not allowed Pylance(reportGeneralTypeIssues)

And with mypy:

$ mypy code/example.py
code/example.py:6: error: Invalid type comment or annotation
code/example.py:6: note: Suggestion: use condecimal[...] instead of condecimal(...)
Found 1 error in 1 file (checked 1 source file)

This is definitely a Pydantic issue: pydantic/pydantic#156.

However, I thought it might be a good idea to add to the docs for decimals that this error can occur. There's a comment on the pydantic issue that gives an ugly workaround, which in my case would look something like:

from decimal import Decimal
from typing import TYPE_CHECKING
from typing_extensions import reveal_type
from pydantic import condecimal
from sqlmodel import Field, SQLModel


class Lineitem(SQLModel, table=True):
    if TYPE_CHECKING:
        price: Decimal = Field(default=0)
    else:
        price: condecimal(max_digits=5, decimal_places=2) = Field(default=0)


item = Lineitem(price=Decimal(1))
if TYPE_CHECKING:
    reveal_type(item.price) # result: Type of "item.price" is "Decimal"

item = Lineitem(price=Decimal(9.999)) # should throw a validation error

The mypy result is:

$ mypy code/example_fixed.py
code/example_fixed.py:17: note: Revealed type is "_decimal.Decimal"
Success: no issues found in 1 source file

I don't think this workaround should be added to the docs: nobody would go this far to make a type checker happy. I was thinking the docs could say something like:

Warning (or Tip?)
Type checkers will complain about the type of condecimal being the result of a callable, or be confused by it. There is no fix for this, so to silence the error add # type: ignore:

class Lineitem(SQLModel, table=True):
    price: condecimal(max_digits=5, decimal_places=2) = Field(default=0)  # type: ignore

Operating System

macOS

Operating System Details

$ sw_vers
ProductName: macOS
ProductVersion: 12.4
BuildVersion: 21F79

SQLModel Version

0.0.6

Python Version

Python 3.10.2

Additional Context

Screenshot of Pylance error:

image

Activity

  1. phi-friday commented on Jun 13, 2022

    @phi-friday
    Contributor

    If you add "from __future__ import annotations" and define the decimal_type outside, there is no problem in pylance.

    from __future__ import annotations
    
    from pydantic import condecimal
    from sqlmodel import Field, SQLModel
    
    decimal_type = condecimal(max_digits=5, decimal_places=2)
    
    
    class Lineitem(SQLModel, table=True):
        price: decimal_type = Field(default=0)
  2. cassieopea commented on Jun 13, 2022

    @cassieopea
    Author

    @phi-friday Thanks, this is awesome! I didn't know future annotations could do that! 🚀

  3. tiangolo commented on Oct 26, 2023

    @tiangolo
    Member

    Support for Pydantic's Decimals was added in #440 🎉

    This will be available in version 0.0.10 🚀

    from decimal import Decimal
    
    from sqlmodel import Field, SQLModel
    
    
    class Model(SQLModel):
        dec: Decimal = Field(max_digits=4, decimal_places=2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions