Skip to content

feat: pass resolved field arguments to prefetch_related callables#881

Draft
bellini666 wants to merge 1 commit intomainfrom
feat/prefetch-callable-field-kwargs
Draft

feat: pass resolved field arguments to prefetch_related callables#881
bellini666 wants to merge 1 commit intomainfrom
feat/prefetch-callable-field-kwargs

Conversation

@bellini666
Copy link
Copy Markdown
Member

@bellini666 bellini666 commented Mar 4, 2026

Summary

  • Prefetch callables that declare parameters beyond info now automatically receive the field's resolved GraphQL arguments as keyword arguments (via inspect.signature dispatch)
  • Adds strawberry_django.get_field_arguments(info) — a public utility for resolving the current field's GraphQL arguments from Info without raw AST access
  • Fully backwards-compatible: existing lambda info: ... callables continue to work unchanged

Closes #863

Test plan

  • Prefetch callable receiving field kwargs with variable resolution
  • Backwards compat: existing lambda info: ... still works
  • **kwargs callable receives all args
  • Subset: callable declares only some args, gets only those
  • get_field_arguments() utility test
  • All 159 existing optimizer tests pass
  • pyright clean
  • ruff clean

🤖 Generated with Claude Code

Summary by Sourcery

Allow optimizer prefetch callables to receive resolved field arguments and expose a public helper for accessing field arguments from Info.

New Features:

  • Enable prefetch_related callables to receive resolved field arguments as keyword parameters when declared beyond info.
  • Expose a public strawberry_django.get_field_arguments(info) helper to obtain resolved GraphQL field arguments from Info.

Enhancements:

  • Extend optimizer store resolution helpers to pass resolved field arguments into prefetch callables while preserving backwards compatibility.

Documentation:

  • Add RELEASE.md entry documenting prefetch callable argument support and the new get_field_arguments utility.

Tests:

  • Add optimizer tests covering prefetch callables receiving field kwargs, **kwargs, subset arguments, and the get_field_arguments utility, including backwards compatibility for existing callables.

Prefetch callables that declare parameters beyond `info` now
automatically receive the field's resolved GraphQL arguments as keyword
arguments. Also adds `strawberry_django.get_field_arguments(info)` as a
public utility for resolving field arguments without raw AST access.

Closes #863
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Mar 4, 2026

Reviewer's Guide

Adds argument-aware handling of prefetch-related callables in the optimizer and exposes a public get_field_arguments(info) utility, ensuring prefetch callables can receive resolved field arguments while remaining backwards-compatible with existing info-only callables.

File-Level Changes

Change Details Files
Prefetch callables now receive resolved field arguments when possible, while remaining backwards-compatible with existing info-only callables.
  • Extend OptimizerStore.with_resolved_callables and with_prefix to accept optional field_kwargs and pass them through when resolving prefetch-related callables.
  • Introduce _invoke_prefetch_callable helper that inspects the callable signature and, when field_kwargs are present, dispatches with **kwargs, either passing all arguments to **kwargs callables or only the subset of named parameters beyond info.
  • Update prefetch resolution sites (_get_hints_from_field and _get_hints_from_model_property) to compute field_kwargs via get_field_arguments(info) only when callable prefetches exist, and pass them into the store methods.
strawberry_django/optimizer.py
Introduce a public get_field_arguments(info) utility for resolving GraphQL field arguments into Python keyword arguments.
  • Implement get_field_arguments(info) to locate the current GraphQL field, compute argument values via get_argument_values and get_arguments, and return kwargs excluding info.
  • Export get_field_arguments from the optimizer module and re-export it at the strawberry_django package level for public use.
strawberry_django/optimizer.py
strawberry_django/__init__.py
Add tests and release notes covering the new prefetch callable behavior and utility.
  • Add tests ensuring prefetch callables receive resolved field kwargs, remain backwards-compatible for info-only callables, handle **kwargs, and support subset-of-args signatures.
  • Add a test verifying that get_field_arguments(info) returns correctly resolved arguments including variable resolution and name conversion.
  • Document the feature and new utility in RELEASE.md as a minor release note.
tests/test_optimizer.py
RELEASE.md

Assessment against linked issues

Issue Objective Addressed Explanation
#863 Enable prefetch_related callables to receive the resolved field GraphQL arguments (in addition to info), so filtering logic can be moved into the prefetch callable without requiring unused resolver arguments or custom AST inspection.
#863 Provide an official public helper to retrieve the current field's resolved GraphQL arguments from Info, avoiding custom get_field_args(info) implementations.

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

@botberry
Copy link
Copy Markdown
Member

botberry commented Mar 4, 2026

Thanks for adding the RELEASE.md file!

Below is the changelog that will be used for the release.


Prefetch callables can now receive resolved field arguments as keyword parameters.

If a prefetch_related callable declares parameters beyond info, the optimizer
will automatically resolve the field's GraphQL arguments and pass matching ones
as keyword arguments. Existing callables that only accept info continue to work
unchanged.

Also adds strawberry_django.get_field_arguments(info) — a public utility that
resolves the current field's GraphQL arguments from an Info object without
raw AST access.

This release was contributed by @bellini666 in #881

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 4, 2026

Codecov Report

❌ Patch coverage is 94.28571% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.60%. Comparing base (a443e09) to head (72773a7).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
strawberry_django/optimizer.py 94.11% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #881      +/-   ##
==========================================
+ Coverage   91.56%   91.60%   +0.03%     
==========================================
  Files          49       49              
  Lines        4588     4620      +32     
==========================================
+ Hits         4201     4232      +31     
- Misses        387      388       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

return schema.config.info_class(raw_info, field)


def get_field_arguments(info: Info) -> dict[str, Any]:
Copy link
Copy Markdown
Member

@rcybulski1122012 rcybulski1122012 Mar 4, 2026

Choose a reason for hiding this comment

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

This is the version that Claude generated for me 😅

```python
def _get_field_args(raw_info: GraphQLResolveInfo) -> dict[str, Any]:
    field_def = get_field_def(raw_info.schema, raw_info.parent_type, raw_info.field_nodes[0])
    raw_args = get_argument_values(field_def, raw_info.field_nodes[0], raw_info.variable_values)

    strawberry_schema = getattr(raw_info.schema, "_strawberry_schema", None) or raw_info.schema.extensions.get(
        GraphQLCoreConverter.DEFINITION_BACKREF
    )
    schema_converter = getattr(strawberry_schema, "schema_converter", None)
    strawberry_field = field_def.extensions.get(GraphQLCoreConverter.DEFINITION_BACKREF)

    if not schema_converter:
        raise RuntimeError(
            "Failed to find strawberry schema for field. Ensure the schema is a strawberry.Schema instance."
        )

    if not strawberry_field:
        raise RuntimeError("Failed to find strawberry field definition. Arguments cannot be correctly converted.")

    return convert_arguments(
        value=raw_args,
        arguments=strawberry_field.arguments,
        config=schema_converter.config,
        scalar_registry=schema_converter.scalar_registry,
    )

I don't know the library internals well enough to tell whether they behave differently

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.

Redundant resolver with unused arguments when filtering with prefetch

3 participants