Skip to content

New Rules Ideas / Discussion #54

Description

@kreathon

Here, are a few ideas for new rules for discussion.

1. Unnecessary mapped_column()

What it does

Checks for redundant i.e. empty mapped_column() calls in SQLAlchemy models. Empty mapped_column() calls do not carry any additional information and can be removed.

Example

from sqlalchemy import orm


class MyModel(Base):
    __tablename__ = "my_model"
    id: orm.Mapped[int] = orm.mapped_column(primary_key=True)

    count: orm.Mapped[int | None] = orm.mapped_column()

Use instead:

from sqlalchemy import orm


class MyModel(Base):
    __tablename__ = "my_model"
    id: orm.Mapped[int] = orm.mapped_column(primary_key=True)

    count: orm.Mapped[int | None]

2. filter_by vs. filter vs. where

What it does

Checks for use of filter_by calls in SQLAlchemy queries.

Why is this bad?

Using where or filter (where is preferred in SQLAlchemy2) has many advantages for static code analysis (and refactoring tools).

Example

import sqlalchemy as sa

query = sa.select(MyModel).filter_by(x=3)

Use instead:

import sqlalchemy as sa

query = sa.select(MyModel).where(MyModel.x == 3)

3. Missing type annotation

What it does

Checks for existence of Mapped type annotations in SQLAlchemy models.

Why is this bad?

If Mapped type annotations are missing, type checkers wills treat the corresponding field as type Any.

Example

import sqlalchemy as sa
from sqlalchemy import orm


class MyModel(Base):
    __tablename__ = "my_model"
    id: orm.Mapped[int] = orm.mapped_column(primary_key=True)

    count = orm.mapped_column(sa.Integer)


m = MyModel()
reveal_type(m.count)  #  note: Revealed type is "Any"

Use instead:

from sqlalchemy import orm


class MyModel(Base):
    __tablename__ = "my_model"
    id: orm.Mapped[int] = orm.mapped_column(primary_key=True)

    count: orm.Mapped[int | None]


m = MyModel()
reveal_type(m.count)  #  note: Revealed type is "Union[builtins.int, None]"

4. Consistency filter vs. where

There could be a could about consistently using filter or where, but where is preferred in the new SQLAlchemy2 style.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions