Skip to content

feat: add field extension support #2567

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

Merged
merged 28 commits into from
Mar 10, 2023

Conversation

erikwrede
Copy link
Member

@erikwrede erikwrede commented Feb 18, 2023

  • fix(test): correct pytest.raises exception matching
  • feat: add field extension support

Description

Adds support for field extensions using the approach specified in PR #2168. Field extensions can support sync ,async or both.

However, sync and async extensions cannot be mixed on the same field: The result of an async resolver would have to be awaited before calling the sync extension, making it impossible for the sync extension to modify any arguments before calling the resolvers.

async-only extensions can be applied to sync resolvers, because we automatically wrap sync resolvers in a SyncToAsyncExtension.

Additional checks to verify no async extensions are used in a sync server (django, flask) may be added in a later PR.

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 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).

@erikwrede erikwrede force-pushed the 2168-field-extensions branch from 566e9f7 to 9525070 Compare February 18, 2023 16:37
@erikwrede erikwrede force-pushed the 2168-field-extensions branch from 9525070 to c0c7bed Compare February 18, 2023 16:46
@codecov
Copy link

codecov bot commented Feb 18, 2023

Codecov Report

Merging #2567 (62002c6) into main (548d612) will increase coverage by 0.01%.
The diff coverage is 98.30%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2567      +/-   ##
==========================================
+ Coverage   96.28%   96.30%   +0.01%     
==========================================
  Files         184      185       +1     
  Lines        7653     7708      +55     
  Branches     1404     1422      +18     
==========================================
+ Hits         7369     7423      +54     
  Misses        183      183              
- Partials      101      102       +1     

erikwrede added a commit to erikwrede/strawberry that referenced this pull request Feb 18, 2023
@erikwrede erikwrede marked this pull request as ready for review February 20, 2023 16:40
@botberry
Copy link
Member

botberry commented Feb 20, 2023

Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:


Adds support for a custom field using the approach specified in issue #2168.
Field Extensions may be used to change the way how fields work and what they return.
Use cases might include pagination, permissions or other behavior modifications.

from strawberry.extensions import FieldExtension


class UpperCaseExtension(FieldExtension):
    async def resolve_async(
        self, next: Callable[..., Awaitable[Any]], source: Any, info: Info, **kwargs
    ):
        result = await next(source, info, **kwargs)
        return str(result).upper()


@strawberry.type
class Query:
    @strawberry.field(extensions=[UpperCaseExtension()])
    async def string(self) -> str:
        return "This is a test!!"
query {
    string
}
{
  "string": "THIS IS A TEST!!"
}

Here's the tweet text:

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

Get it here 👉 https://github.com/strawberry-graphql/strawberry/releases/tag/(next)

@erikwrede erikwrede force-pushed the 2168-field-extensions branch from 2cb8d1c to f71430b Compare February 23, 2023 17:29
erikwrede added a commit to erikwrede/strawberry that referenced this pull request Feb 24, 2023
Copy link
Member

@jkimbo jkimbo left a comment

Choose a reason for hiding this comment

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

This is really great! 👏 Just added a couple of suggestions for the docs but otherwise I say we ship it.

Co-authored-by: Jonathan Kim <jkimbo@gmail.com>
Copy link
Member

@bellini666 bellini666 left a comment

Choose a reason for hiding this comment

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

LGTM 👍🏼

There are some comments that I made at the other PR, but they are mostly for the permissions integration.

@erikwrede erikwrede mentioned this pull request Mar 2, 2023
2 tasks
@github-actions
Copy link

github-actions bot commented Mar 7, 2023


## Combining multiple field extensions

When chaining multiple field extensions, the outermost extension is called first,
Copy link
Member

Choose a reason for hiding this comment

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

do you think we could replace outermost with last?

or could we make it so that the order is the same as the one you pass? I think the current behaviour might be confusing 😊

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd love to have a diagram here for nested extensions, that would clear things up a lot. Do we have a preferred tool for that?

Copy link
Member

Choose a reason for hiding this comment

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

let's use mermaid, it should work on github too: https://mermaid.js.org

Copy link
Member Author

Copy link
Member

Choose a reason for hiding this comment

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

yup, maybe vertical, as it might be easier to read on mobile 😊

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok I just realized that doesn't work because the content inside those tags (the diagram in this case) won't be parsed by markdown then.

Copy link
Member

Choose a reason for hiding this comment

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

@erikwrede we could make a custom component for that if it helps

or add a directive, like

```mermaid (mobile:vertical)

if it is easy to change the setting 😊

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok it actually looks just fine on the github preview. The strawberry preview doesn't seem to update though.

Copy link
Member

Choose a reason for hiding this comment

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

it's probably because we don't support mermaid yet on the site :D I'll see if I can add support to the current design in the next couple of days 😊

Copy link
Member Author

Choose a reason for hiding this comment

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

We could also add the graph later when the new website is ready

Copy link
Member

@patrick91 patrick91 left a comment

Choose a reason for hiding this comment

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

This is awesome 😊

@patrick91 patrick91 merged commit dfc3d51 into strawberry-graphql:main Mar 10, 2023
@patrick91 patrick91 mentioned this pull request Mar 10, 2023
11 tasks
@jkimbo
Copy link
Member

jkimbo commented Mar 12, 2023

🎉

patrick91 added a commit that referenced this pull request Dec 18, 2023
* feat: add field extension support

* fix: revert imports broken by pycharm

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: match error message on test

* chore: refactor & add RELEASE.md

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* chore: make mypy happy

* chore: enable async-only extensions on sync

* chore: adjust callable type hint for resolve_async

* hopefully fix codecov...

* hopefully fix codecov... #2

* fix: make field directives mutable

* docs: add field extension documentation

* chore: change next to next_

* chore: make sync-only extensions before async-only extensions possible

* fix: test case match string adapted

* feat(draft): add permission extension

blocked by #2567

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: use permission.raise_error

* chore: fix mypy, drop old PermissionError raise

* fix: add permissions extension to field automatically

* fix: fix failing tests

* fix: recognize async permissions correctly

* refactor: move permission error raising to extension

* tests: fix test regex to support python <3.10

* refactor: enable silent permissions

* fix?: move noqa comment

* chore: refactor permissions directives and add RELEASE.md

* fix: use correct type annotation for schema_directive

* fix: remove permission classes from base resolver

Co-authored-by: Thiago Bellini Ribeiro <hackedbellini@gmail.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* chore: address review comment

* chore: add type alias type hint

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* chore: add better error docs

* chore: import type alias from extensions

* chore: remove unused private method on strawberry field to improve code cov

* chore: improve on review comments

* chore: improve coverage

* chore: improve coverage

* docs: fix keyword name in Release.MD

Co-authored-by: Etty <28976199+estyxx@users.noreply.github.com>

* chore: rename handle_no_permission to on_unauthorized

* docs: describe permission extensions

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: update cached property import

* fix: update cached property import

* chore: mypy fixes

* Make sure we test the exception

* Lint

* "Improve" coverage

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Thiago Bellini Ribeiro <hackedbellini@gmail.com>
Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
Co-authored-by: Etty <28976199+estyxx@users.noreply.github.com>
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.

5 participants