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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions