Open-source updates
13 September 2021

I'm back after a break in Italy! In the last couple of weeks I've managed to add support for PyRight; this will make the experience of using Strawberry on vscode much better! I've also done a few improvements to our GitHub actions and some code reviews.

# PyRight

A while ago I started a PR to improve the support for PyRight. This was prompted by this PEP proposal. The PEP proposes a standard way for "tagging" function that do similar transform to dataclasses (like we us, Pydantic, SQL Model and more). This allows to use pure python code to define function/decorator that transform classes by adding methods like __init__, __eq__ and so on.

Previously we could only do this with MyPy by using a (complex) plugin. Hopefully the PEP will be accepted at some point, meaning that all python type checkers implementing the spec will properly type check Strawberry and other libraries adopting the PEP.

I did hold off this PR for a bit since I wanted to make sure we supported most of our APIs and I'm very happy to have managed to influnce the PEP proposal to make it a bit easier for libraries to take advantage of the proposal, even when they don't fully dataclasses's semantics, like Strawberry 😊

For example, before that change the following example would result in a class that accepted one parameter, field_x, at least for the type checkers:

def get_x() -> int:
return 42
class Query:
field_x: int = strawberry.field(resolver=get_x)

while at runtime it wouldn't actually accept any parameter since fields with resolvers (in Strawberry) don't need a value (the value comes from the resolver function). To fix this we can follow dataclasses' semantics and pass init=False to the field function:

class Query:
field_x: int = strawberry.field(resolver=get_x, init=False)

But this is quite annoying, since the init parameter won't be used by Strawberry (at least when passing resolvers).

Luckily we can solve this by using overloads and Literals (if you're curious to see how it works see the spec).

By typing the field function something like this:

def field(
*, # Note the omission of `resolver`
init: Literal[True] = True,
) -> Any:
def field(
resolver: Callable[[], T],
init: Literal[False] = False,
) -> T:

See here for the full implementation

we can tell the type checker that when resolver is passed init is always False, and so we don't have to pass it explicitly 💯

Big thanks to Eric for accepting the suggestion and implementing it so quickly!

# Actions

I've also spent some time cleaning up our GitHub actions and moved some of our actions to dedicated repos, hopefully some people might re-use them.

There's an action to get information about a PR. This action works in the PR itself but also on master after the PR has been merged (it finds the PR from the commit). We use this for generating the twitter cards and for inviting contributors to our organisation.

There's a couple of actions for our tweet workflow. They allow to get the tweet text from a TWEET.md file and to validate the text. This action is quite coupled to our workflow, but I'd love to make it more reusable, so if someone needs this, let me know!

I've created a new action to invite contributors to our organisation automatically. I did try to use a pre-build action but it wasn't working so I've made our own :)

We were doing this manually in the past, but now we don't have to anymore, it loses the personal touch, but it is so easy to forget to invite people!

Again, if you want to re-use these actions let me know! Always happy to improve them 😊

# Pull Request reviews

Here's the list of PRs I managed to review in the last couple of weeks:

A PR to add fragments to the selected_fields property on the info parameter by Jon

A PR to fix an issue with the export-schema command by Matt

A PR to fix using union types with Pydantic types by Matt

A PR to fix optional values conversion from Pydantic types by Matt

Big props to Matt for sending 3 PRs!

A PR to allow any version of opentelemetry before 2.0 by Michael

A PR to raise an exception when using unions or interfaces as inputs by Mohammad

# Fin

I was mostly off during the last two weeks but I managed to do some useful work, also I've noticed that Strawberry is gaining quite a bit of traction lately, which is super nice!

Written in Venice 🇮🇹


No replies found! Tweet about this post, and it will show up here! ☝