strawberry
strawberry copied to clipboard
Implement `oneOf`
We are still missing the equivalent of the check in coerce value
Mostly based on https://github.com/graphql/graphql-js/pull/3513/files
Closes #2421 #2560
TODO:
- [x] Check print of schema directive
- [x] Test with a frontend library
- [x] schema codegen support
- [x] Introspection support?
Codecov Report
All modified and coverable lines are covered by tests :white_check_mark:
Project coverage is 96.53%. Comparing base (
fc322a8) to head (a79e961). Report is 2 commits behind head on main.
Additional details and impacted files
@@ Coverage Diff @@
## main #3429 +/- ##
==========================================
+ Coverage 96.51% 96.53% +0.02%
==========================================
Files 511 516 +5
Lines 32965 33174 +209
Branches 5482 5521 +39
==========================================
+ Hits 31815 32025 +210
+ Misses 917 916 -1
Partials 233 233
also, I'm not sure this is best approach for us, I'll think about it in the next few days
CodSpeed Performance Report
Merging #3429 will not alter performance
Comparing feature/one-of (a79e961) with main (a8b108e)
Summary
✅ 12 untouched benchmarks
so far I've added a out_type on the GraphQL input which seems to be the best place to check for one of.
But I'm not sure on the check 🤔 At the moment we need to use unset, otherwise we'd get an error since some of the keys won't be populated. Maybe we can allow None and change the check? I need to read the spec 😊
spec is here: https://github.com/graphql/graphql-spec/pull/825
I don't want to overcomplicate this, but it would be interesting to investigate if we can use @overload for this too, something like:
import strawberry
@strawberry.type
class Query:
@strawberry.field
def search(self, query: str) -> list[str]:
...
@strawberry.field
@overload
def search(self, something_else: str) -> list[str]:
...
(I'm actually not sure this is valid in python either, but just writing it down in case it might be useful in future)
I think this is almost ready to go! I just need to test it with codegen 😊
actually, maybe we should introduce a new decorator to make this easier to use:
@strawberry.one_of_input
class ExampleInputTagged:
a: str | None
b: int | None
/pre-release
Pre-release
:wave:
Pre-release 0.230.0.dev.1716318708 [2dc1a076bedb0f73dcb1904dfa960a6da3a17f01] has been released on PyPi! :rocket: You can try it by doing:
poetry add strawberry-graphql==0.230.0.dev.1716318708
Pre-release
:wave:
Pre-release 0.227.0.dev.1713463204 [a9b1edd2e9cb7c88c2fa271333b86e8ff699320a] has been released on PyPi! :rocket: You can try it by doing:
poetry add strawberry-graphql==0.227.0.dev.1713463204
/pre-release
Oh woops didn't see this was marked pre-release literally hours before making my comments!
I've tested this with GraphQL-codegen and it works when using the SDL, but doesn't work when using introspection, but that's not our issue 😊
Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:
This release adds support for @oneOf on input types! 🎉 You can use
one_of=True on input types to create an input type that should only have one
of the fields set.
import strawberry
@strawberry.input(one_of=True)
class ExampleInputTagged:
a: str | None = strawberry.UNSET
b: int | None = strawberry.UNSET
Here's the tweet text:
🆕 Release (next) is out! Thanks to @patrick91 for the PR 👏
We now support the `@oneOf` directive on input types, ensuring exactly one
key is specified.
Check out the details and improvements! Get it here 👉 https://strawberry.rocks/release/(next)
Apollo Federation Subgraph Compatibility Results
| Federation 1 Support | Federation 2 Support | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Learn more:
/pre-release
@bradleyoesch feel free to try the new pre-release 😊
/pre-release