Support Annotated field configuration everywhere - #4594
Conversation
|
Thanks for adding the Below is the changelog that will be used for the release. This release fixes fields configured with You can now use this syntax consistently on object types, input types, and from typing import Annotated
import strawberry
Name = Annotated[
str,
strawberry.field(name="displayName", default="Anonymous"),
]
@strawberry.type
class User:
name: NameAll This release was contributed by @patrick91 in #4594 |
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="strawberry/types/object_type.py" line_range="112-118" />
<code_context>
+ arg for arg in rest if not isinstance(arg, StrawberryField)
+ ]
+ field_type = (
+ Annotated[(first, *remaining_metadata)] if remaining_metadata else first
+ )
+ type_annotation = field.type_annotation or StrawberryAnnotation(
+ field_type,
+ namespace=module_namespace,
+ )
+ field.type_annotation = type_annotation
+
+ setattr(cls, field_name, field)
</code_context>
<issue_to_address>
**issue (broader_impact):** An `Annotated` field with an explicit `graphql_type` override drops all sibling metadata because the existing override annotation wins over the reconstructed annotation containing the remaining metadata. Named unions, enums, lazy references, `auto`, and private markers placed alongside that field configuration are therefore not preserved.
**Triggers:** When `strawberry.field(graphql_type=...)` is combined with another Strawberry metadata object inside the same `Annotated` annotation.
**Suggested fix:** Rebuild the annotation with the non-`StrawberryField` metadata while retaining the explicit GraphQL type override separately, rather than selecting the pre-existing `field.type_annotation` wholesale.
</issue_to_address>Sourcery assessment
Approval pending. 1 finding to address first.
Blocking findings: strawberry/types/object_type.py:118
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Greptile SummaryThis PR moves
Confidence Score: 4/5This PR should not merge until postponed lazy Annotated fields continue to work on the supported Python 3.10–3.13 runtimes. The new eager evaluator catches and discards unresolved lazy annotations before their Strawberry field metadata is extracted, while the previous later extraction path has been removed. Files Needing Attention: strawberry/types/object_type.py, strawberry/types/type_resolver.py
|
| Filename | Overview |
|---|---|
| strawberry/types/object_type.py | Adds the central early-processing flow, but its exception path drops valid lazy postponed fields on Python 3.10–3.13. |
| strawberry/types/type_resolver.py | Removes post-dataclass Annotated extraction, making the new early processor the sole recovery point for field metadata. |
| strawberry/types/field.py | Adjusts field copying to preserve dataclass defaults while avoiding duplicate permission extensions. |
| tests/types/test_annotated_fields_future_annotations.py | Adds broad postponed-annotation coverage, including an unskipped lazy-reference case that exposes the unsupported-version failure path. |
| docs/types/object-types.md | Documents Annotated field configuration, constructor defaults, and composable metadata. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Class annotation] --> B[Evaluate postponed annotation]
B --> C[Extract StrawberryField metadata]
C --> D[Install dataclass field]
D --> E[Generate dataclass constructor]
E --> F[Build Strawberry definition]
B -->|Unresolved name on Python 3.10-3.13| G[NameError caught]
G --> H[Field processing skipped]
Reviews (1): Last reviewed commit: "Use plain release messaging" | Re-trigger Greptile
Amp-Thread-ID: https://ampcode.com/threads/T-01a047e0-b77e-773e-b1b6-d45bd45b6494 Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a047e0-b77e-773e-b1b6-d45bd45b6494 Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a047e0-b77e-773e-b1b6-d45bd45b6494 Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
569b33f to
d89bf6d
Compare
Amp-Thread-ID: https://ampcode.com/threads/T-01a047e0-b77e-773e-b1b6-d45bd45b6494 Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a047e0-b77e-773e-b1b6-d45bd45b6494 Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
|
Warning Sourcery was unable to dismiss its earlier approval of this pull request, because the latest commits introduced blocking findings. The approval above no longer reflects the current commits. How to resolve thisAdd the Sourcery app under Restrict who can dismiss pull request reviews in this repository's branch protection rules. Sourcery only ever dismisses its own reviews. It does not dismiss reviews from anyone else. |
|
This PR was published as 0.324.2. Thank you for contributing! |
Summary
Annotated[..., strawberry.field(...)]before dataclass generation so field defaults and factories configure constructorsauto, and private markersImplementation notes
Annotation evaluation uses the public
Format.FORWARDREFAPIs first. On Python 3.10–3.13, Strawberry's existing lazy-aware evaluator is used only when the backport leaves the complete expression unresolved. No new annotation parser is introduced.Directly unresolved postponed expressions such as
Annotated[Later, strawberry.field(...)]rely on Python 3.14's PEP 649/749 support. Resolvable postponed annotations and Strawberry lazy references remain supported on all Strawberry Python versions.Validation
uv run pytest tests/types tests/test_printer/test_schema_directives.py tests/federation/test_types.py tests/relay/test_fields.py -q— 530 passed, 5 skipped, 1 xfaileduv run pytest tests/federation/test_types.py tests/relay/test_fields.py -q— 237 passeduv run --isolated --python 3.14 pytest tests/types/test_annotated_fields_future_annotations.py tests/test_printer/test_schema_directives.py -q— 29 passed, 4 skippeduv run --isolated --python 3.15 pytest tests/types/test_annotated_fields_future_annotations.py tests/test_printer/test_schema_directives.py -q— 29 passed, 4 skippeduv run mypy --config-file mypy.ini strawberry/types/object_type.py strawberry/types/type_resolver.py strawberry/types/field.pyCloses #4241
Summary by Sourcery
Enable full Strawberry field configuration through
typing.Annotatedacross supported type and field definitions.New Features:
strawberry.field()insidetyping.Annotated, including defaults and factories.Bug Fixes:
Documentation:
Tests: