Skip to content

General wrongness working with Enums #877

@avivey

Description

@avivey

This is for graphene 2.1.3.

There are a bunch of issues working with enums, here are two that bite me right now:

  1. When specifying default_value, we need to explicitly add .name or .value, else introspection breaks (see commented out code).
  • If specifying .value, the schema generated is wrong (See test 1 below).
  • If specifying .name, the schema is correct, but the argument passed to the function is a string that doesn't match any value (See test 1 and 2).
  1. When working with python-backed enums, the value passed to the resolver doesn't match any sensible value (See test 3, below).

Test code:

#! /usr/bin/env python
import graphene
import json
import enum

class Episode(graphene.Enum):
    NEWHOPE = 4
    EMPIRE = 5
    JEDI = 6

class BackendLengthUnit(enum.Enum):
    METER = 'm'
    FOOT = 'f'

LengthUnit = graphene.Enum.from_enum(BackendLengthUnit)

class Query(graphene.ObjectType):
    # desc = graphene.String(
    #    v=graphene.Argument(Episode, default_value=Episode.NEWHOPE),
    #    description='See ./broken-schema.py')
    desc1 = graphene.String(
        v=graphene.Argument(Episode, default_value=Episode.NEWHOPE.value),
        description='default value in schema is `4`, which is not valid. Also, awkward to write.')
    desc2 = graphene.String(
        v=graphene.Argument(Episode, default_value=Episode.NEWHOPE.name),
        description='Default value is correct in schema doc. awkward to write.')
    pyenum = graphene.String(
        v=graphene.Argument(LengthUnit),
        description='More fun with python-enum backed enum.')

    def resolve_desc1(self, info, v):
        return f'argument: {v!r}'

    def resolve_desc2(self, info, v):
        return f'argument: {v!r}'

    def resolve_pyenum(self, info, v):
        return (
            f'Argument: {v!r}. '
            f'Is GrapheneEnum foot: {v == LengthUnit.FOOT}. '
            f'Is Backend enum foot: {v == BackendLengthUnit.FOOT}. '
        )

schema = graphene.Schema(query=Query)
print('*** Schema:')
print(schema)

def qp(query):
    print(json.dumps(schema.execute(query).data, indent=2))

def qpf(query):
    print(json.dumps(schema.execute(query).to_dict(), indent=2))

print('*** Test 1: use default values:')

qp('{desc1, desc2}')
# Should be:
# {
  # "desc1": "argument: <EnumMeta.NEWHOPE: 4>",  (enum value)
  # "desc2": "argument: <EnumMeta.NEWHOPE: 4>"
# }
# but actually is:
# {
  # "desc1": "argument: 4",         (int value)
  # "desc2": "argument: 'NEWHOPE'"  (string name)
# }


print('*** Test 2: Providing a value:')
qp('{desc1(v: JEDI), desc2(v: JEDI)}')
# Should be:
# {
  # "desc1": "argument: <EnumMeta.JEDI: 6>",  (enum value)
  # "desc2": "argument: <EnumMeta.JEDI: 6>"
# }
# but actually is:
# {
  # "desc1": "argument: 6",
  # "desc2": "argument: 6"
# }


print('*** Test 3: Working with Python Enums:')
qp('{pyenum(v: FOOT)}')
# This is what we get:
# {
  # "pyenum": "Argument: 'f'. Is GrapheneEnum foot: False. Is Backend enum foot: False. "
# }
# In order to be useful, it should be at least one of these things!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions