Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Take oneOf directive into account in codegen module #3652

Open
wants to merge 18 commits into
base: main
Choose a base branch
from

Conversation

enoua5
Copy link
Contributor

@enoua5 enoua5 commented Sep 28, 2024

Description

Adds support for oneOf to the codegen module

  • The codegen manager now passes is_one_of to GraphQLObjectType making it part of the codegen plugin api
  • Python plugin has been updated to output oneOf types as a union of classes with one field each
  • Typescript plugin has been updated to output oneOf types as a union of objects where in each all but one field has a type of never

Types of Changes

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

Issues Fixed or Closed by This PR

  • None

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • 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

Implement support for the oneOf directive in the code generation module, enhancing the Python and TypeScript plugins to handle oneOf types as unions. Add corresponding tests and snapshots to verify the new functionality.

New Features:

  • Add support for the oneOf directive in the code generation module, allowing the generation of union types for oneOf fields in both Python and TypeScript plugins.

Enhancements:

  • Update the Python plugin to output oneOf types as a union of classes, each with one field.
  • Update the TypeScript plugin to output oneOf types as a union of objects, where each object has all but one field typed as never.

Tests:

  • Add new test cases and snapshots for the oneOf directive in both Python and TypeScript code generation to ensure correct functionality.

Copy link

codecov bot commented Sep 28, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 96.83%. Comparing base (92ae942) to head (1347bde).
Report is 10 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3652      +/-   ##
==========================================
+ Coverage   96.76%   96.83%   +0.06%     
==========================================
  Files         522      503      -19     
  Lines       33824    33457     -367     
  Branches     5635     5596      -39     
==========================================
- Hits        32731    32397     -334     
+ Misses        863      830      -33     
  Partials      230      230              

Copy link

codspeed-hq bot commented Sep 28, 2024

CodSpeed Performance Report

Merging #3652 will not alter performance

Comparing enoua5:codegen-oneof (1347bde) with main (3484480)

Summary

✅ 15 untouched benchmarks

@enoua5 enoua5 changed the title Take oneOf directive into account when codegen module Take oneOf directive into account in codegen module Sep 28, 2024
@enoua5 enoua5 marked this pull request as ready for review September 28, 2024 02:30
Copy link
Contributor

sourcery-ai bot commented Sep 28, 2024

Reviewer's Guide by Sourcery

This pull request adds support for the oneOf directive in the codegen module. The changes primarily affect the Python and TypeScript plugins, introducing new logic to handle oneOf types in code generation. The implementation includes updates to object type handling, field printing, and type definitions to accommodate the oneOf functionality.

Sequence Diagram

sequenceDiagram
    participant CG as Codegen Manager
    participant PY as Python Plugin
    participant TS as TypeScript Plugin
    CG->>CG: Set is_one_of flag in GraphQLObjectType
    CG->>PY: Process oneOf type
    PY->>PY: Generate union of classes
    CG->>TS: Process oneOf type
    TS->>TS: Generate union of objects
Loading

File-Level Changes

Change Details Files
Added support for oneOf directive in the codegen module
  • Updated GraphQLObjectType to include is_one_of flag
  • Modified _collect_type_from_strawberry_type to set is_one_of flag
  • Added new methods to handle oneOf object types in Python and TypeScript plugins
  • Updated existing methods to account for oneOf types
strawberry/codegen/query_codegen.py
strawberry/codegen/types.py
strawberry/codegen/plugins/python.py
strawberry/codegen/plugins/typescript.py
Updated Python plugin to generate oneOf types as a union of classes
  • Added _print_oneof_object_type method to generate oneOf classes
  • Modified _print_field method to handle oneOf members
  • Updated _print_type to use oneOf-specific logic when applicable
strawberry/codegen/plugins/python.py
Updated TypeScript plugin to generate oneOf types as a union of objects
  • Added _print_oneof_object_type method to generate oneOf types
  • Added _print_oneof_field method to handle oneOf fields
  • Updated _print_type to use oneOf-specific logic when applicable
strawberry/codegen/plugins/typescript.py
Added test cases and snapshots for oneOf functionality
  • Created new test queries for oneOf types
  • Added snapshot files for Python and TypeScript oneOf output
tests/codegen/conftest.py
tests/codegen/snapshots/typescript/oneof_typename.ts
tests/codegen/snapshots/python/oneof_typename.py
tests/codegen/snapshots/typescript/oneof.ts
tests/codegen/snapshots/python/oneof.py
tests/codegen/queries/oneof_typename.graphql
tests/codegen/queries/oneof.graphql

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.

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

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 @enoua5 - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 3 issues found
  • 🟢 Security: all looks good
  • 🟡 Testing: 4 issues found
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

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.

strawberry/codegen/plugins/python.py Show resolved Hide resolved
strawberry/codegen/plugins/typescript.py Show resolved Hide resolved
strawberry/codegen/types.py Show resolved Hide resolved
tests/codegen/conftest.py Show resolved Hide resolved
tests/codegen/snapshots/python/oneof.py Outdated Show resolved Hide resolved
tests/codegen/snapshots/typescript/oneof.ts Show resolved Hide resolved
@botberry
Copy link
Member

botberry commented Sep 28, 2024

Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:


The Query Codegen system now supports the @oneOf directive.

When writing plugins, you can now access GraphQLObjectType.is_one_of to determine if the object being worked with has a @oneOf directive.

The default plugins have been updated to take advantage of the new attribute.

For example, given this schema:

@strawberry.input(one_of=True)
class OneOfInput:
    a: Optional[str] = strawberry.UNSET
    b: Optional[str] = strawberry.UNSET


@strawberry.type
class Query:
    @strawberry.field
    def one_of(self, value: OneOfInput) -> str: ...


schema = strawberry.Schema(Query)

And this query:

query OneOfTest($value: OneOfInput!) {
  oneOf(value: $value)
}

The query codegen can now generate this Typescript file:

type OneOfTestResult = {
    one_of: string
}

type OneOfInput = { a: string, b?: never }
    | { a?: never, b: string }

type OneOfTestVariables = {
    value: OneOfInput
}

Here's the tweet text:

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

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

@enoua5
Copy link
Contributor Author

enoua5 commented Sep 29, 2024

I unchecked "My change requires a change to the documentation". I would add a note about this to the documentation on codegen plugins, but the docs already don't go over any of the other types that are passed into the plugin.

@enoua5
Copy link
Contributor Author

enoua5 commented Oct 2, 2024

If anyone has opinions on how those Typescript unions should be formatted, I'd be happy to take the feedback 😄

@patrick91
Copy link
Member

@enoua5 I'll check this on the weekend! thank you so much 😊

@enoua5
Copy link
Contributor Author

enoua5 commented Oct 6, 2024

If anyone has opinions on how those Typescript unions should be formatted, I'd be happy to take the feedback 😄

Looking at dotansimha/graphql-code-generator, it looks like it would generate code like this:

type OneOfInput =
  { a: string, b?: never }
  |  { a?: never, b: string };

I'm not a big fan of the hanging =, but, thoughts?

@patrick91
Copy link
Member

@enoua5 I think that's fine, we could maybe in future run prettier/biome to the output if the user has one of them installed :)

@enoua5
Copy link
Contributor Author

enoua5 commented Oct 6, 2024

@patrick91 That's a fair point. Do you think its not worth changing it from how it is now, then?

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

Successfully merging this pull request may close these issues.

3 participants