Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/testapp/testapp/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from litestar.plugins.sqlalchemy import EngineConfig, SQLAlchemyAsyncConfig, SQLAlchemyPlugin
from strawberry.litestar import BaseContext, make_graphql_controller

from .models import Base
from .schema import schema
from testapp.models import Base
from testapp.schema import schema

if TYPE_CHECKING:
from sqlalchemy.ext.asyncio import AsyncSession
Expand Down
3 changes: 1 addition & 2 deletions examples/testapp/testapp/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

import strawberry
from strawchemy.validation.pydantic import PydanticValidation

from .types import (
from testapp.types import (
CustomerCreate,
CustomerType,
MilestoneCreate,
Expand Down
3 changes: 1 addition & 2 deletions examples/testapp/testapp/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
from pydantic import AfterValidator

from strawchemy import Strawchemy, StrawchemyAsyncRepository, StrawchemyConfig

from .models import Customer, Milestone, Project, Ticket
from testapp.models import Customer, Milestone, Project, Ticket

strawchemy = Strawchemy(StrawchemyConfig("sqlite", repository_type=StrawchemyAsyncRepository))

Expand Down
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ classifiers = [
"Typing :: Typed",
]
dependencies = [
"msgspec",
"msgspec>=0.4.2",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for msgspec usage in Python files
rg -n "msgspec" --type=py -B2 -A3

Repository: gazorby/strawchemy

Length of output: 2507


🏁 Script executed:

# Also check the full pyproject.toml for context around the dependency
cat -n pyproject.toml | grep -A5 -B5 msgspec

Repository: gazorby/strawchemy

Length of output: 880


🏁 Script executed:

# Check if there's a changelog or release notes that might document version requirements
git log --oneline -n 20 -- pyproject.toml | head -20

Repository: gazorby/strawchemy

Length of output: 111


Correct msgspec minimum version constraint to reflect actual requirements.

The msgspec.convert function was introduced in version 0.16.0 to replace the deprecated from_builtins. However, the code imports and uses msgspec.convert in repository/_base.py, yet the constraint specifies msgspec>=0.4.2, which does not include this function. Update the constraint to msgspec>=0.16.0 to match the actual minimum version required by the codebase.

🤖 Prompt for AI Agents
In pyproject.toml at line 32, the msgspec dependency is incorrectly constrained
as "msgspec>=0.4.2" while the codebase uses msgspec.convert (introduced in
0.16.0); update the constraint to "msgspec>=0.16.0" so the declared minimum
version matches the actual required API, then run a quick dependency
install/check (pip or poetry) to verify no other version conflicts.

"sqlalchemy>=2.0.10",
"strawberry-graphql",
"typing-extensions"
Expand Down Expand Up @@ -370,10 +370,13 @@ convention = "google"

[tool.ruff.lint.per-file-ignores]
"tests/*" = ["TC001", "UP037", "PLR2004", "PLC0415"]
"src/strawchemy/strawberry/factories/*" = ["UP007", "UP045"]
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove redundant per-file ignore configuration.

The rules UP007 and UP045 are already globally ignored at lines 359-360, making this per-file ignore redundant. The global ignores already apply to src/strawchemy/strawberry/factories/*.

🔎 Apply this diff to remove the redundant configuration:
-"src/strawchemy/strawberry/factories/*" = ["UP007", "UP045"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"src/strawchemy/strawberry/factories/*" = ["UP007", "UP045"]
🤖 Prompt for AI Agents
In pyproject.toml around line 373, remove the redundant per-file ignore entry
""src/strawchemy/strawberry/factories/*" = ["UP007", "UP045"]" because UP007 and
UP045 are already globally ignored at lines 359-360; simply delete this line to
avoid duplication and keep global ignores only.


[tool.ruff.lint.isort]
known-first-party = ["strawchemy", "tests"]

[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "all"

[tool.unasyncd]
add_editors_note = true
Expand Down
16 changes: 8 additions & 8 deletions src/strawchemy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

from __future__ import annotations

from .config.base import StrawchemyConfig
from .mapper import Strawchemy
from .sqlalchemy.hook import QueryHook
from .strawberry import ModelInstance
from .strawberry.mutation.input import Input
from .strawberry.mutation.types import (
from strawchemy.config.base import StrawchemyConfig
from strawchemy.mapper import Strawchemy
from strawchemy.sqlalchemy.hook import QueryHook
from strawchemy.strawberry import ModelInstance
from strawchemy.strawberry.mutation.input import Input
from strawchemy.strawberry.mutation.types import (
ErrorType,
RequiredToManyUpdateInput,
RequiredToOneInput,
Expand All @@ -16,8 +16,8 @@
ToOneInput,
ValidationErrorType,
)
from .strawberry.repository import StrawchemyAsyncRepository, StrawchemySyncRepository
from .validation.base import InputValidationError
from strawchemy.strawberry.repository import StrawchemyAsyncRepository, StrawchemySyncRepository
from strawchemy.validation.base import InputValidationError

__all__ = (
"ErrorType",
Expand Down
6 changes: 3 additions & 3 deletions src/strawchemy/dto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from __future__ import annotations

from .base import DTOFieldDefinition, ModelFieldT, ModelInspector, ModelT
from .types import DTOConfig, Purpose, PurposeConfig
from .utils import config, field
from strawchemy.dto.base import DTOFieldDefinition, ModelFieldT, ModelInspector, ModelT
from strawchemy.dto.types import DTOConfig, Purpose, PurposeConfig
from strawchemy.dto.utils import config, field

__all__ = (
"DTOConfig",
Expand Down
9 changes: 4 additions & 5 deletions src/strawchemy/dto/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@
from typing_extensions import Self, override

from strawchemy.dto.exceptions import DTOError, EmptyDTOError
from strawchemy.graph import Node
from strawchemy.utils import is_type_hint_optional, non_optional_type_hint

from .types import (
from strawchemy.dto.types import (
DTOAuto,
DTOConfig,
DTOFieldConfig,
Expand All @@ -44,7 +41,9 @@
Purpose,
PurposeConfig,
)
from .utils import config
from strawchemy.dto.utils import config
from strawchemy.graph import Node
from strawchemy.utils import is_type_hint_optional, non_optional_type_hint

if TYPE_CHECKING:
from collections.abc import Callable, Generator, Hashable, Iterable, Mapping
Expand Down
6 changes: 3 additions & 3 deletions src/strawchemy/dto/pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

from sqlalchemy.orm import DeclarativeBase, QueryableAttribute

from .backend.pydantic import MappedPydanticDTO, PydanticDTOBackend
from .base import DTOFactory
from .inspectors.sqlalchemy import SQLAlchemyInspector
from strawchemy.dto.backend.pydantic import MappedPydanticDTO, PydanticDTOBackend
from strawchemy.dto.base import DTOFactory
from strawchemy.dto.inspectors.sqlalchemy import SQLAlchemyInspector

__all__ = ("factory", "pydantic_dto")

Expand Down
6 changes: 3 additions & 3 deletions src/strawchemy/dto/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import dataclasses
from dataclasses import dataclass, field
from enum import Enum
from typing import TYPE_CHECKING, Any, Literal, TypeAlias, Union, final, get_type_hints
from typing import TYPE_CHECKING, Any, Literal, TypeAlias, final, get_type_hints

from typing_extensions import override

Expand All @@ -20,8 +20,8 @@
DTOScope: TypeAlias = Literal["global", "dto"]


IncludeFields: TypeAlias = Union[list[str], set[str], Literal["all"]]
ExcludeFields: TypeAlias = Union[list[str], set[str]]
IncludeFields: TypeAlias = "list[str] | set[str] | Literal['all']"
ExcludeFields: TypeAlias = "list[str] | set[str]"


@final
Expand Down
12 changes: 10 additions & 2 deletions src/strawchemy/dto/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@

from typing import TYPE_CHECKING, Any

from .constants import DTO_INFO_KEY
from .types import DTOConfig, DTOFieldConfig, DTOScope, ExcludeFields, IncludeFields, Purpose, PurposeConfig
from strawchemy.dto.constants import DTO_INFO_KEY
from strawchemy.dto.types import (
DTOConfig,
DTOFieldConfig,
DTOScope,
ExcludeFields,
IncludeFields,
Purpose,
PurposeConfig,
)

if TYPE_CHECKING:
from collections.abc import Callable, Mapping
Expand Down
36 changes: 17 additions & 19 deletions src/strawchemy/mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,31 @@
from strawberry.annotation import StrawberryAnnotation
from strawberry.schema.config import StrawberryConfig

from strawchemy.strawberry.factories.aggregations import EnumDTOFactory
from strawchemy.strawberry.factories.enum import EnumDTOBackend, UpsertConflictFieldsEnumDTOBackend

from .config.base import StrawchemyConfig
from .dto.backend.strawberry import StrawberrryDTOBackend
from .dto.base import TYPING_NS
from .strawberry._field import (
from strawchemy.config.base import StrawchemyConfig
from strawchemy.dto.backend.strawberry import StrawberrryDTOBackend
from strawchemy.dto.base import TYPING_NS
from strawchemy.strawberry._field import (
StrawchemyCreateMutationField,
StrawchemyDeleteMutationField,
StrawchemyField,
StrawchemyUpdateMutationField,
StrawchemyUpsertMutationField,
)
from .strawberry._registry import StrawberryRegistry
from .strawberry.dto import BooleanFilterDTO, EnumDTO, MappedStrawberryGraphQLDTO, OrderByDTO, OrderByEnum
from .strawberry.factories.inputs import AggregateFilterDTOFactory, BooleanFilterDTOFactory
from .strawberry.factories.types import (
from strawchemy.strawberry._registry import StrawberryRegistry
from strawchemy.strawberry.dto import BooleanFilterDTO, EnumDTO, MappedStrawberryGraphQLDTO, OrderByDTO, OrderByEnum
from strawchemy.strawberry.factories.aggregations import EnumDTOFactory
from strawchemy.strawberry.factories.enum import EnumDTOBackend, UpsertConflictFieldsEnumDTOBackend
from strawchemy.strawberry.factories.inputs import AggregateFilterDTOFactory, BooleanFilterDTOFactory
from strawchemy.strawberry.factories.types import (
DistinctOnFieldsDTOFactory,
InputFactory,
OrderByDTOFactory,
RootAggregateTypeDTOFactory,
TypeDTOFactory,
UpsertConflictFieldsDTOFactory,
)
from .strawberry.mutation import types
from .types import DefaultOffsetPagination
from strawchemy.strawberry.mutation import types
from strawchemy.types import DefaultOffsetPagination

if TYPE_CHECKING:
from collections.abc import Callable, Mapping, Sequence
Expand All @@ -43,13 +42,12 @@

from strawberry import BasePermission
from strawchemy.sqlalchemy.hook import QueryHook
from strawchemy.sqlalchemy.typing import QueryHookCallable
from strawchemy.strawberry.typing import FilterStatementCallable, MappedGraphQLDTO
from strawchemy.typing import AnyRepository, SupportedDialect
from strawchemy.validation.base import ValidationProtocol
from strawchemy.validation.pydantic import PydanticMapper

from .sqlalchemy.typing import QueryHookCallable
from .strawberry.typing import FilterStatementCallable, MappedGraphQLDTO
from .typing import AnyRepository, SupportedDialect
from .validation.base import ValidationProtocol


T = TypeVar("T", bound="DeclarativeBase")

Expand Down Expand Up @@ -158,7 +156,7 @@ def pydantic(self) -> PydanticMapper:
Returns:
An instance of PydanticMapper.
"""
from .validation.pydantic import PydanticMapper # noqa: PLC0415
from strawchemy.validation.pydantic import PydanticMapper # noqa: PLC0415
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove unused noqa directive.

The # noqa: PLC0415 comment suppresses the "import not at top of file" rule, but static analysis indicates this rule is not enabled in your Ruff configuration. The lazy import pattern itself is valid and intentional to avoid circular imports.

🔎 Apply this diff to remove the unused directive:
-        from strawchemy.validation.pydantic import PydanticMapper  # noqa: PLC0415
+        from strawchemy.validation.pydantic import PydanticMapper
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from strawchemy.validation.pydantic import PydanticMapper # noqa: PLC0415
from strawchemy.validation.pydantic import PydanticMapper
🧰 Tools
🪛 Ruff (0.14.8)

159-159: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)

🤖 Prompt for AI Agents
In src/strawchemy/mapper.py around line 159, the inline comment "# noqa:
PLC0415" on the lazy import is unnecessary; remove the " # noqa: PLC0415" suffix
so the line becomes a plain lazy import (keep the import in place to avoid
circular import issues) and save the file.


return PydanticMapper(self)

Expand Down
6 changes: 5 additions & 1 deletion src/strawchemy/sqlalchemy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

from __future__ import annotations

from .repository import SQLAlchemyGraphQLAsyncRepository, SQLAlchemyGraphQLRepository, SQLAlchemyGraphQLSyncRepository
from strawchemy.sqlalchemy.repository import (
SQLAlchemyGraphQLAsyncRepository,
SQLAlchemyGraphQLRepository,
SQLAlchemyGraphQLSyncRepository,
)

__all__ = ("SQLAlchemyGraphQLAsyncRepository", "SQLAlchemyGraphQLRepository", "SQLAlchemyGraphQLSyncRepository")
8 changes: 3 additions & 5 deletions src/strawchemy/sqlalchemy/_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@
from typing_extensions import Self

from strawchemy.dto import ModelT

from .exceptions import QueryResultError
from .typing import AnyAsyncSession, AnySyncSession, DeclarativeT
from strawchemy.sqlalchemy.exceptions import QueryResultError
from strawchemy.sqlalchemy.typing import AnyAsyncSession, AnySyncSession, DeclarativeT

if TYPE_CHECKING:
from collections.abc import Callable, Generator, Sequence

from sqlalchemy import Label, Result, Select, StatementLambdaElement
from strawchemy.sqlalchemy._scope import QueryScope
from strawchemy.strawberry.typing import QueryNodeType

from ._scope import QueryScope


__all__ = ("AsyncQueryExecutor", "NodeResult", "QueryExecutor", "SyncQueryExecutor")

Expand Down
10 changes: 4 additions & 6 deletions src/strawchemy/sqlalchemy/_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
)
from strawchemy.constants import AGGREGATIONS_KEY, NODES_KEY
from strawchemy.graph import merge_trees
from strawchemy.sqlalchemy.exceptions import TranspilingError
from strawchemy.sqlalchemy.typing import DeclarativeT, OrderBySpec
from strawchemy.strawberry.dto import (
BooleanFilterDTO,
EnumDTO,
Expand All @@ -44,9 +46,6 @@
QueryNode,
)

from .exceptions import TranspilingError
from .typing import DeclarativeT, OrderBySpec

if TYPE_CHECKING:
from collections.abc import Sequence

Expand All @@ -56,11 +55,10 @@
from sqlalchemy.sql.selectable import NamedFromClause

from strawchemy.config.databases import DatabaseFeatures
from strawchemy.sqlalchemy._scope import QueryScope
from strawchemy.sqlalchemy.hook import ColumnLoadingMode, QueryHook
from strawchemy.strawberry.typing import QueryNodeType

from ._scope import QueryScope
from .hook import ColumnLoadingMode, QueryHook

__all__ = ("AggregationJoin", "Conjunction", "DistinctOn", "Join", "OrderBy", "QueryGraph", "Where")


Expand Down
10 changes: 4 additions & 6 deletions src/strawchemy/sqlalchemy/_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,21 @@
from strawchemy.constants import NODES_KEY
from strawchemy.dto.types import DTOConfig, Purpose
from strawchemy.graph import Node
from strawchemy.sqlalchemy.exceptions import TranspilingError
from strawchemy.sqlalchemy.inspector import SQLAlchemyInspector
from strawchemy.sqlalchemy.typing import DeclarativeT
from strawchemy.strawberry.dto import GraphQLFieldDefinition, QueryNode

from .exceptions import TranspilingError
from .inspector import SQLAlchemyInspector
from .typing import DeclarativeT

if TYPE_CHECKING:
from collections.abc import Callable

from sqlalchemy.orm.util import AliasedClass
from sqlalchemy.sql.elements import NamedColumn

from strawchemy.sqlalchemy.typing import DeclarativeSubT, FunctionGenerator, RelationshipSide
from strawchemy.strawberry.typing import QueryNodeType
from strawchemy.typing import SupportedDialect

from .typing import DeclarativeSubT, FunctionGenerator, RelationshipSide

__all__ = ("NodeInspect", "QueryScope")

_FunctionVisitor: TypeAlias = "Callable[[Function[Any]], ColumnElement[Any]]"
Expand Down
Loading