strawberry-graphql / strawberry

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

Support default factory for query arguments #1657

Open bibekyess opened 2 years ago

bibekyess commented 2 years ago

It seems strawberry doesn't support default_factory for query arguments. Like in example below:

import json
import typing
from typing import NewType

import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter

data = [{"name": "A", "age": 12}, {"name": "B", "age": 20}]

@strawberry.type
class Info:
    name: str
    age: int

JSON = strawberry.scalar(
    NewType("JSON", object),
    description="The `JSON` scalar type represents JSON values as specified by ECMA-404",
    serialize=lambda v: v,
    parse_value=lambda v: v,
)

def get_data(
    where: typing.Optional[JSON] = strawberry.field(default_factory=dict), #FIXME to None
) -> typing.Optional[typing.List[Info]]:
    if where is None: result= data
    elif len(where) != 0: result = [d for d in data if d.get("name") == where.get("name")]
    else: result = data
    return json.loads(json.dumps(result), object_hook=lambda d: Info(**d))

@strawberry.type
class Query:
    informations: typing.Optional[typing.List[Info]] = strawberry.field(resolver=get_data)

schema = strawberry.Schema(query=Query)
graphql_app = GraphQLRouter(
    schema
)
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")

Here, I couldn't find a way to set where argument be dict using default_factory. Using the same code as above result in AST error unless we replace strawberry.field(default_factory=dict) or {} by None.

Upvote & Fund

Fund with Polar

patrick91 commented 1 year ago

I think we need to add support for default_factory inside strawberry.argument

Voldemat commented 1 year ago

Any news on this?

coady commented 1 year ago

Factory functions aside, these tips might help:

Voldemat commented 1 year ago

There is case for array fields where it is more logical to use empty list as default rather null(None). Maybe creation of some sort of marker could resolve the issue.

coady commented 1 year ago

There is case for array fields where it is more logical to use empty list as default rather null(None). Maybe creation of some sort of marker could resolve the issue.

That already works too: arg: list[...] = [].

patrick91 commented 1 year ago

I'd be happy to review a PR if anyone has time to implement this 😊

Voldemat commented 1 year ago

There is case for array fields where it is more logical to use empty list as default rather null(None). Maybe creation of some sort of marker could resolve the issue.

That already works too: arg: list[...] = [].

mmm.... It doesn`t work in inputs or types, I suppose you implemented strawberry decorators on top of dataclasses which also have such problem, but in their case you can use field(default_factory=list), which kinda solves the issue. So for now we forced to use optional array fields or required one without default, which is a bit annoying.