strawberry-graphql / strawberry

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

Enum types from Pydantic models are not registered in GraphQL schema #1598

Open merlinus1 opened 2 years ago

merlinus1 commented 2 years ago

If pydantic model contains Enum field this enum definition is not registered in GraphQL Schema

Running following code raises error:

import typing
from enum import Enum

import strawberry
from pydantic import BaseModel

class ModelTypeEnum(str, Enum):
    type_1 = "type_1"
    type_2 = "type_2"

class PydanticModel(BaseModel):
    name: str
    model_type: typing.Optional[ModelTypeEnum]

@strawberry.experimental.pydantic.type(model=PydanticModel, all_fields=True)
class StrawberryModel:
    pass

@strawberry.type
class Query:
    models: typing.List[StrawberryModel]

def get_models():
    return []

@strawberry.type
class Query:
    models: typing.List[StrawberryModel] = strawberry.field(resolver=get_models)

if __name__ == '__main__':
    schema = strawberry.Schema(query=Query)
Traceback (most recent call last):
  File "C:\Users\merlinus1\PycharmProjects\test_strawbery\main.py", line 38, in <module>
    schema = strawberry.Schema(query=Query)
  File "C:\Users\merlinus1\AppData\Local\pypoetry\Cache\virtualenvs\test-strawbery-ZCOgkqdC-py3.9\lib\site-packages\strawberry\schema\schema.py", line 84, in __init__
    self._schema = GraphQLSchema(
  File "C:\Users\merlinus1\AppData\Local\pypoetry\Cache\virtualenvs\test-strawbery-ZCOgkqdC-py3.9\lib\site-packages\graphql\type\schema.py", line 208, in __init__
    collect_referenced_types(query)
  File "C:\Users\merlinus1\AppData\Local\pypoetry\Cache\virtualenvs\test-strawbery-ZCOgkqdC-py3.9\lib\site-packages\graphql\type\schema.py", line 423, in collect_referenced_types
    collect_referenced_types(field.type)
  File "C:\Users\merlinus1\AppData\Local\pypoetry\Cache\virtualenvs\test-strawbery-ZCOgkqdC-py3.9\lib\site-packages\graphql\type\schema.py", line 422, in collect_referenced_types
    for field in named_type.fields.values():
  File "C:\Program Files\Python39\lib\functools.py", line 993, in __get__
    val = self.func(instance)
  File "C:\Users\merlinus1\AppData\Local\pypoetry\Cache\virtualenvs\test-strawbery-ZCOgkqdC-py3.9\lib\site-packages\graphql\type\definition.py", line 737, in fields
    raise TypeError(f"{self.name} fields cannot be resolved. {error}")
TypeError: StrawberryModel fields cannot be resolved. _enum_definition

Manually registering enum fixes error:

strawberry.enum(ModelTypeEnum)

But maybe enum has to be auto registered? Probably in replace_pydantic_types method https://github.com/strawberry-graphql/strawberry/blob/7738ceacf10c928f3bae7e00184286cc245ed2bc/strawberry/experimental/pydantic/object_type.py#L47

if issubclass(type_, Enum):
    strawberry.enum(type_)

Upvote & Fund

Fund with Polar

checor commented 2 years ago

Facing the same issue. In the meantime, I will register the types manually. Thanks for the insight!

motherofcoconuts commented 2 years ago

+1 Facing the same issue.

In my case I had a a list of enum types: List[EnumType] as a field type so the above solution did not work out of the box. I ended up adding the following at the top of replace_pydantic_types to get this to work:

import inspect

def replace_pydantic_types(type_: Any, is_input: bool):
    if inspect.isclass(type_) and issubclass(type_, Enum):
        return strawberry.enum(type_)

    ...
thejaminator commented 2 years ago

+1 Facing the same issue.

In my case I had a a list of enum types: List[EnumType] as a field type so the above solution did not work out of the box. I ended up adding the following at the top of replace_pydantic_types to get this to work:

import inspect

def replace_pydantic_types(type_: Any, is_input: bool):
    if inspect.isclass(type_) and issubclass(type_, Enum):
        return strawberry.enum(type_)

    ...

@motherofcoconuts let me investigate this, manually registering should have worked. Whats your strawberry version? Could you have a small example to replicate?

SuHotdog commented 2 years ago

+1 Facing the same issue. In my case I had a a list of enum types: List[EnumType] as a field type so the above solution did not work out of the box. I ended up adding the following at the top of replace_pydantic_types to get this to work:

import inspect

def replace_pydantic_types(type_: Any, is_input: bool):
    if inspect.isclass(type_) and issubclass(type_, Enum):
        return strawberry.enum(type_)

    ...

@motherofcoconuts let me investigate this, manually registering should have worked. Whats your strawberry version? Could you have a small example to replicate?

same issue here strawberry-graphql = "0.112.0"

*update: fixed by adding @strawberry.enum to Enum class image

motherofcoconuts commented 2 years ago

@motherofcoconuts let me investigate this, manually registering should have worked. Whats your strawberry version? Could you have a small example to replicate?

Sorry for the delayed response, must of missed this.

Version = 0.114.1 Fix: I put the following lines in my __init__.py

super_rpt = strawberry.experimental.pydantic.fields.replace_pydantic_types

def replace_pydantic_types(type_: Any, is_input: bool) -> Any:
    if inspect.isclass(type_) and issubclass(type_, Enum):
        return strawberry.enum(type_)
    return super_rpt(type_, is_input)

strawberry.experimental.pydantic.fields.replace_pydantic_types = replace_pydantic_types

The example @merlinus1 gives is a perfect example of the error. Copy and paste my fix to the top of that solution and the error disappears without having to register each type to the schema. Registering each type to the schema manually is something i want to avoid as i use ALOT of enums in my application.

cat-turner commented 1 year ago

when will this be resolved?

shipitparrotclemz commented 1 year ago

@cat-turner Hi, we can fix this by manually registering the enum / decorating the enum class with @strawberry.enum.

Do you mean you are looking for an automatic enum registering feature?

There is a documentation here by Patrick, the creator of strawberry, on how to register an enum. This will fix it for now.