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

Add Resolver type, use it as a return type for field and fix tests #3383

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

Conversation

lukaspiatkowski
Copy link

Description

Change one of the overrides of strawberry.field to return -> Resolver[T] if resolver = ... is provided. This forces you to annotate your fields as field: Resolver[int] = ... and since Resolver is an abstract final class you cannot create an instance of it. This will prevent you from mistakenly writing or reading that field.

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

@botberry
Copy link
Member

botberry commented Feb 15, 2024

Hi, thanks for contributing to Strawberry 🍓!

We noticed that this PR is missing a RELEASE.md file. We use that to automatically do releases here on GitHub and, most importantly, to PyPI!

So as soon as this PR is merged, a release will be made 🚀.

Here's an example of RELEASE.md:

Release type: patch

Description of the changes, ideally with some examples, if adding a new feature.

Release type can be one of patch, minor or major. We use semver, so make sure to pick the appropriate type. If in doubt feel free to ask :)

Here's the tweet text:

🆕 Release (next) is out! Thanks to Lukasz Piatkowski for the PR 👏

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

Copy link

codecov bot commented Feb 15, 2024

Codecov Report

Merging #3383 (1560cd3) into main (be9a2d5) will decrease coverage by 1.06%.
The diff coverage is 100.00%.

❗ Current head 1560cd3 differs from pull request most recent head 4bd3bca. Consider uploading reports for the commit 4bd3bca to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3383      +/-   ##
==========================================
- Coverage   96.41%   95.36%   -1.06%     
==========================================
  Files         498      498              
  Lines       31133    31148      +15     
  Branches     3814     3809       -5     
==========================================
- Hits        30016    29703     -313     
- Misses        911     1236     +325     
- Partials      206      209       +3     

@patrick91
Copy link
Member

couldn't we use Callable instead of Resolver? 😊

@lukaspiatkowski
Copy link
Author

I will fill up the documentation and release notes as soon as someone tells me there is a chance for merging this PR in :) Also my approach to writing the Resolver class itself is a bit hacky. I want to maintain my own fork with this change if it doesn't get merged, so I wanted to avoid changing core schema converting functions. I am fine fixing this part.

Copy link

codspeed-hq bot commented Feb 15, 2024

CodSpeed Performance Report

Merging #3383 will not alter performance

Comparing wavemm:lukas/resolver_type (1560cd3) with main (be9a2d5)

Summary

✅ 12 untouched benchmarks

@lukaspiatkowski
Copy link
Author

couldn't we use Callable instead of Resolver? 😊

Hmm, yes now that you say that we probably could do it, although it would be a bit of pain. Note that Callable is parametrized over 2 generic (Callable[Param, Ret]), in this case we don't care about Param part. But AFAIK Python doesn't let you yet write type aliases that parametrize part of the Generic, like so:

Resolver: TypeAlias = Callable[Any, T]

    field: Resolver[int] = strawberry.field(resolver=...)

So you would have to write the whole thing every time:

    field: Callable[Any, Int] = strawberry.field(resolver=...)`

which is IMO a mouthfull and not necessary correct - people could try and call this function, but without proper typing they wouldn't get the arguments right.

@lukaspiatkowski
Copy link
Author

Oh, I see that you are using libcst for codemoding backward incompatible changes. I was about to write one for myself, but I can add it here in this PR. Stay tuned! :)

@lukaspiatkowski
Copy link
Author

Codemod added as promised

@lukaspiatkowski lukaspiatkowski force-pushed the lukas/resolver_type branch 2 times, most recently from 5cd56fd to 42c21a7 Compare February 15, 2024 12:50
@lukaspiatkowski
Copy link
Author

One thing that I've noticed when using this new type on my codebase was that if you have an interface it might get difficult to get the types right. Consider this code:

@interface
class Base:
    a: int

@type
class A(Base):
    a: int = field(resolver=...)

@type
class B(Base):
    a: int

With the new Resolver type you won't be able to write:

@interface
class Base:
    a: int

@type
class A(Base):
    a: Resolver[int] = field(resolver=...)

@type
class B(Base):
    a: int

because the child class A changes the type of the base class Base. And for good reason! You wouldn't want this code to work without warnings:

def foo(base: Base) -> int:
    return base.a

def bar(a: A) -> int:
    return foo(a)

So for future reference if you stumble on this problem while changing your codebase my suggestion would be to write something like this:

@interface
class Base:
    a: Resolver[int]

@type
class A(Base):
    a: Resolver[int] = field(resolver=...)

@type
class B(Base):
	_a: Private[int]
    a: Resolver[int] = field(resolver=lambda self: self._a)

@lukaspiatkowski
Copy link
Author

@patrick91 any chance this is going to be merged or closed without merging?

@patrick91
Copy link
Member

@lukaspiatkowski not sure, sorry I didn't have time to take a proper look at this, I have set some time to look at PRs today, hopefully I get to this one

@lukaspiatkowski
Copy link
Author

Just friendly pinging @patrick91 here :)

@patrick91
Copy link
Member

@lukaspiatkowski sorry, still haven't had the time to properly think about this, I'll add it to my things for next week 😊

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.

None yet

3 participants