strawberry-graphql / strawberry

A GraphQL library for Python that leverages type annotations 🍓
https://strawberry.rocks
MIT License
3.87k stars 511 forks source link

Implement scalars using Annotated #3369

Open patrick91 opened 5 months ago

patrick91 commented 5 months ago

This is how you create a custom scalar now:

import base64
from typing import NewType

import strawberry

Base64 = strawberry.scalar(
    NewType("Base64", bytes),
    serialize=lambda v: base64.b64encode(v).decode("utf-8"),
    parse_value=lambda v: base64.b64decode(v).encode("utf-8"),
)

Unfortunately this is can't be typed properly (See #3312, but I'd love to be wrong, I haven't spent too much time to check this)

If we can type this correctly we could think of implementing scalars using Annotated, like this:

import base64
from typing import NewType

import strawberry

Base64 = Annotated[
    NewType("Base64", bytes),
    strawberry.scalar(
        serialize=lambda v: base64.b64encode(v).decode("utf-8"),
        parse_value=lambda v: base64.b64decode(v).encode("utf-8"),
   )
]

Upvote & Fund

Fund with Polar

jacobmoshipco commented 5 months ago

Unfortunately this is can't be typed properly (See https://github.com/strawberry-graphql/strawberry/issues/3312, but I'd love to be wrong, I haven't spent too much time to check this)

There's a decorator form of strawberry.scalar that doesn't seem to appear in the strawberry.rocks documentation. You can use it to make properly typed version of a lot of custom scalars:


@strawberry.scalar(
    serialize=lambda v: base64.b64encode(v).decode("utf-8"),
    parse_value=lambda v: base64.b64decode(v),
)
class Base64(bytes):
    pass

Of course, this only helps if the type you want to serialize is valid as a base class, but it's something to make the type-checker happy until the annotated version is implemented.