strawberry icon indicating copy to clipboard operation
strawberry copied to clipboard

Implement `oneOf`

Open patrick91 opened this issue 1 year ago • 17 comments

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?

patrick91 avatar Mar 31 '24 09:03 patrick91

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              

codecov[bot] avatar Mar 31 '24 09:03 codecov[bot]

also, I'm not sure this is best approach for us, I'll think about it in the next few days

patrick91 avatar Mar 31 '24 09:03 patrick91

CodSpeed Performance Report

Merging #3429 will not alter performance

Comparing feature/one-of (a79e961) with main (a8b108e)

Summary

✅ 12 untouched benchmarks

codspeed-hq[bot] avatar Mar 31 '24 09:03 codspeed-hq[bot]

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 😊

patrick91 avatar Mar 31 '24 15:03 patrick91

spec is here: https://github.com/graphql/graphql-spec/pull/825

patrick91 avatar Mar 31 '24 15:03 patrick91

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)

patrick91 avatar Mar 31 '24 21:03 patrick91

I think this is almost ready to go! I just need to test it with codegen 😊

patrick91 avatar Apr 17 '24 20:04 patrick91

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

patrick91 avatar Apr 17 '24 20:04 patrick91

/pre-release

patrick91 avatar Apr 18 '24 17:04 patrick91

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

botberry avatar Apr 18 '24 18:04 botberry

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

botberry avatar Apr 18 '24 18:04 botberry

/pre-release

Oh woops didn't see this was marked pre-release literally hours before making my comments!

bradleyoesch avatar Apr 18 '24 21:04 bradleyoesch

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 😊

patrick91 avatar Apr 18 '24 21:04 patrick91

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)

botberry avatar Apr 18 '24 21:04 botberry

Apollo Federation Subgraph Compatibility Results

Federation 1 Support Federation 2 Support
_service🟢
@key (single)🟢
@key (multi)🟢
@key (composite)🟢
repeatable @key🟢
@requires🟢
@provides🟢
federated tracing🔲
@link🟢
@shareable🟢
@tag🟢
@override🟢
@inaccessible🟢
@composeDirective🟢
@interfaceObject🟢

Learn more:

botberry avatar Apr 18 '24 21:04 botberry

/pre-release

patrick91 avatar Apr 18 '24 21:04 patrick91

@bradleyoesch feel free to try the new pre-release 😊

patrick91 avatar Apr 18 '24 21:04 patrick91

/pre-release

patrick91 avatar May 21 '24 19:05 patrick91