strawberry icon indicating copy to clipboard operation
strawberry copied to clipboard

Expose `dataclasses.asdict` to `strawberry.asdict` and document it

Open patrick91 opened this issue 3 years ago • 1 comments
trafficstars

A common use case is to convert types to dicts, which we already support through dataclasses.asdict.

We should expose asdict via the strawberry namespace, so we can make sure there's always a supported way to convert types to dictionaries. And we can also add additional code checks if needed :)

Example here: https://play.strawberry.rocks/?gist=c8e729c52efef8b75f1599c759c069c8

patrick91 avatar Sep 14 '22 16:09 patrick91

  1. should the asdict resolve the child types as dict as well?
  2. what would be the API?
@strawberry.type
class Foo:
    bar: str

d = Foo("baz").asdict()

vs

d = asdict(Foo("baz"))

vs

d = dict(Foo("baz"))
  1. Should we do type checks while casting to dict?
  2. what should we do with fields with resolvers?

nrbnlulu avatar Sep 14 '22 17:09 nrbnlulu

This seems helpful and would like to know if it would support resolvers. Here is a simple example:

from dataclasses import asdict

import strawberry

@strawberry.type
class Position:
    trading_pl: float
    position_pl: float

    @strawberry.field
    def desk_pl(self) -> float:
        return self.trading_pl + self.position_pl

dict_data = asdict(Position(1, 2))

In the above example, dict_data["desk_pl"] will be a method and you have to call it to get the result, e.g.:

dict_data["desk_pl"] = dict_data["desk_pl"]()

The same issue exists with dataclasses support in Pandas. The same behavior occurs with pd.DataFrame([Position(1,2)]).

I can see it may be challenging to implement built-in behavior to support all scenarios.

In my examples, I would to avoid hardcoding calls to the methods generated from resolvers. Does Strawberry expose a public API to get the list of resolvers for a given type?

bperkins24 avatar Oct 17 '22 19:10 bperkins24

@bperkins24 it's not really possible to support resolvers in any kind of strawberry type serialisation because resolvers have to be called in the context of a GraphQL execution since they can rely on the info object: https://strawberry.rocks/docs/types/resolvers#accessing-execution-information

jkimbo avatar Oct 19 '22 09:10 jkimbo

When I using dataclasses.asdict(...) PyCharm or other lint always said "asdict() should be called on dataclass instances". So I really agreed with @patrick91's feature request to expose strawberry.asdict(...).

I want to try to solve this issue. I'm newcomer of strawberry's internal. But... Can I try this?

Nebu1eto avatar Dec 23 '22 03:12 Nebu1eto

@Hazealign sure! I think we can start by exposing a function called asdict that calls dataclasses.asdict, then we can improve on it later :)

def asdict(o: object) -> dict:
    return dataclasses.asdict(o)

something like this :)

patrick91 avatar Dec 23 '22 10:12 patrick91