fastapi / sqlmodel

SQL databases in Python, designed for simplicity, compatibility, and robustness.
https://sqlmodel.tiangolo.com/
MIT License
14.44k stars 658 forks source link

`Unexpected argument(s)` warning in PyCharm when using `select()` with many parameters #92

Open avi-perl opened 3 years ago

avi-perl commented 3 years ago

First Check

Commit to Help

Example Code

from typing import Optional
from datetime import datetime

from sqlmodel import Field, SQLModel, select, func, create_engine, Session

class Item(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    created: datetime
    deleted: bool = False
    category: str
    version: float = 1
    data: str

# Create and save records to show that the query itself is working.
item_1 = Item(created=datetime.now(), category="category_1", data="❤️ I love SQLModel.")
item_2 = Item(created=datetime.now(), category="category_1", data="❤️ I love FastAPI.", deleted=True)
item_3 = Item(created=datetime.now(), category="category_2", data="🥰 I appreciate your work on all of it!")

engine = create_engine("sqlite://")

SQLModel.metadata.create_all(engine)

with Session(engine) as session:
    session.add(item_1)
    session.add(item_2)
    session.add(item_3)
    session.commit()

    # This "statement" is where the issue presents itself in PyCharm
    statement = (
        select(
            Item.category,
            func.count(Item.id),
            func.total(Item.deleted).label("delete_count"),
            func.min(Item.created).label("oldest_timestamp"),
            func.max(Item.created).label("newest_timestamp"),
            func.group_concat(Item.version).label("version_list"),
        )
            .distinct()
            .group_by(Item.category)
    )
    category_metadata = session.exec(statement)
    for result in category_metadata:
        print(dict(result))

Description

Operating System

Windows

Operating System Details

Windows = 10 PyCharm Version = 2021.2 (Community Edition)

SQLModel Version

0.0.4

Python Version

Python 3.9.7

Additional Context

image

Cielquan commented 2 years ago

I have the same issue.

I have a table with 5 foreign keys. And when I want to do a full join like below I get a mypy error. So I assume the typing is the issue here. And PyCharm uses the types too I think.

from sqlmodel import select
...
stmt = (
    select(
        Ticket, TicketStage, ConspicuityType, User, ATFeedbackType, StatisticalEvaluationType
    )
    .join(TicketStage)
    .join(ConspicuityType)
    .join(User)
    .join(ATFeedbackType)
    .join(StatisticalEvaluationType)
)

And when I use reveal_type from typing_extensions I get this:

from typing_extensions import reveal_type
from sqlmodel import select
...
stmt = (
    select(
        Ticket, TicketStage, ConspicuityType, User, ATFeedbackType, StatisticalEvaluationType
    )
    .join(TicketStage)
    .join(ConspicuityType)
    .join(User)
    .join(ATFeedbackType)
    .join(StatisticalEvaluationType)
)
reveal_type(stmt)  # Type of "stmt" is "Any"

When I reduce the arguments to select I get:

from typing_extensions import reveal_type
from sqlmodel import select
...
stmt = (
    select(
        Ticket, TicketStage, ConspicuityType, User
    )
    .join(TicketStage)
    .join(ConspicuityType)
    .join(User)
    .join(ATFeedbackType)
    .join(StatisticalEvaluationType)
)
reveal_type(stmt)  # Type of "stmt" is "Select[Tuple[Ticket, TicketStage, ConspicuityType, User]]"

When I use select from sqlalchemy instead it works with all arguments and I get:

from typing_extensions import reveal_type
from sqlalchemy import select
...
stmt = (
    select(
        Ticket, TicketStage, ConspicuityType, User, ATFeedbackType, StatisticalEvaluationType
    )
    .join(TicketStage)
    .join(ConspicuityType)
    .join(User)
    .join(ATFeedbackType)
    .join(StatisticalEvaluationType)
)
reveal_type(stmt)  # Type of "stmt" is "Select"
Cielquan commented 2 years ago

Basically the issues lies here: https://github.com/tiangolo/sqlmodel/blob/main/sqlmodel/sql/expression.py#L140-L442

The overloads are hardcoded and end with 4 parameters. So I guess there are 3 Solutions:

kiddten commented 2 years ago

Same issue here

etash47 commented 4 months ago

@tiangolo we're still having this issue in a ton of places in our code base, any we can resolve or merge max's fix? Would be a huge QOL improvement for us. Thank you !!

1990heidou commented 1 month ago

Due to the fact that the 'select' parameter in the SQL model is as follows: image

You can first create a list of parameters that need to be queried: image