Skip to content

Conversation

jacobmoshipco
Copy link
Contributor

@jacobmoshipco jacobmoshipco commented Aug 28, 2025

Important

This PR is still a draft as I will not have time to write tests for the change for awhile.
Help in this regard would be appreciated.

Description

This patch fixes a bug where input strawberry.Maybe input fields would fail to have a default None injected when annotated or set with strawberry.field.

Previously, this would cause this example input to require name to be set, despite it being marked Maybe

@strawberry.input
class Example:
    name: strawberry.Maybe[str] = strawberry.field(description="This strawberry.field annotation was breaking in default injection")

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Documentation

Issues Fixed or Closed by This PR

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

Summary by Sourcery

Fix default None injection for input fields annotated with strawberry.Maybe and improve detection of Maybe annotations

Bug Fixes:

  • Ensure default None is injected for fields with Maybe annotations even when defined via strawberry.field

Enhancements:

  • Support unwrapping Annotated types in the Maybe annotation detection logic

Copy link
Contributor

sourcery-ai bot commented Aug 28, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This patch refines the default-injection mechanism for fields annotated with Maybe by ensuring that None is applied even when using strawberry.field, and it augments the annotation detection to recognize Maybe nested within Annotated types.

File-Level Changes

Change Details Files
Refined default injection for Maybe-annotated fields with StrawberryField instances
  • Preserve existing injection behavior when no attribute is present
  • Add branch to detect StrawberryField with missing default and default_factory
  • Assign None to attr.default when both default markers are _MISSING_TYPE
types/object_type.py
Extended _annotation_is_maybe to handle Annotated wrappers
  • Import Annotated from typing
  • Check for Annotated origin and unwrap its first argument
  • Recursively call _annotation_is_maybe on the unwrapped type
types/maybe.py

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@jacobmoshipco jacobmoshipco changed the title Patch _inject_default_for_maybe_annotations Patch default injection for annotated fields Aug 28, 2025
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `strawberry/types/object_type.py:137` </location>
<code_context>
+                setattr(cls, name, None)
+            elif (
+                isinstance(attr := getattr(cls, name), StrawberryField)
+                and isinstance(attr.default, dataclasses._MISSING_TYPE)
+                and isinstance(attr.default_factory, dataclasses._MISSING_TYPE)
+            ):
</code_context>

<issue_to_address>
Using dataclasses._MISSING_TYPE is relying on a private API.

Use dataclasses.MISSING instead, as it is the public API and more stable across Python versions.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

setattr(cls, name, None)
elif (
isinstance(attr := getattr(cls, name), StrawberryField)
and isinstance(attr.default, dataclasses._MISSING_TYPE)
Copy link
Contributor

Choose a reason for hiding this comment

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

issue: Using dataclasses._MISSING_TYPE is relying on a private API.

Use dataclasses.MISSING instead, as it is the public API and more stable across Python versions.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Summary

This PR fixes a bug in Strawberry GraphQL's handling of strawberry.Maybe input fields when they are explicitly defined using strawberry.field(). The core issue was that Maybe fields with field annotations or descriptions would incorrectly be treated as required fields instead of optional ones with default None values.

The fix involves two complementary changes:

  1. Enhanced Maybe detection (maybe.py): The _annotation_is_maybe() function now recursively handles typing.Annotated wrappers, which are created when using strawberry.field() with descriptions or other metadata. Previously, the function would fail to recognize Maybe types when they were wrapped in Annotated.

  2. Improved default injection (object_type.py): The _inject_default_for_maybe_annotations() function now handles cases where a StrawberryField object already exists on the class but lacks explicit default values. The function checks for StrawberryField instances where both default and default_factory are missing and injects None as the default value.

This change preserves the existing behavior for simple Maybe field declarations (e.g., name: strawberry.Maybe[str]) while extending support to field-annotated Maybe types (e.g., name: strawberry.Maybe[str] = strawberry.field(description="...")). The fix ensures that Maybe semantics work consistently across different field definition styles in input types, which is crucial for the GraphQL schema's type system integrity.

Confidence score: 4/5

  • This PR addresses a specific bug with a targeted fix that should be safe to merge with minimal risk
  • Score reflects well-isolated changes to core type handling logic, though the lack of tests in the current PR reduces confidence slightly
  • Pay close attention to the Maybe type detection logic and default injection mechanisms, as these are foundational to input type behavior

2 files reviewed, 1 comment

Edit Code Review Bot Settings | Greptile

@botberry
Copy link
Member

Hi, thanks for contributing to Strawberry 🍓!

We noticed that this PR is missing a RELEASE.md file. We use that to automatically do releases here on GitHub and, most importantly, to PyPI!

So as soon as this PR is merged, a release will be made 🚀.

Here's an example of RELEASE.md:

Release type: patch

Description of the changes, ideally with some examples, if adding a new feature.

Release type can be one of patch, minor or major. We use semver, so make sure to pick the appropriate type. If in doubt feel free to ask :)

Here's the tweet text:

🆕 Release (next) is out! Thanks to jacobmoshipco for the PR 👏

Get it here 👉 https://strawberry.rocks/release/(next)

@jacobmoshipco jacobmoshipco marked this pull request as draft August 28, 2025 16:21
Copy link

codspeed-hq bot commented Aug 28, 2025

CodSpeed Performance Report

Merging #3985 will not alter performance

Comparing jacobmoshipco:patch-maybe-default-injection (f09af16) with main (58ea8c9)

Summary

✅ 26 untouched benchmarks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants