Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I would like my enum input values to be the enum instance instead of the enum values #1151

Closed
radix opened this issue Mar 9, 2020 · 5 comments

Comments

@radix
Copy link

radix commented Mar 9, 2020

Is there a way for me to do this?

Here is some example code.

from enum import Enum, auto

from graphene import Enum as GQLEnum, ObjectType, Schema, String
from graphene.relay import ClientIDMutation
from graphene.test import Client

class EnumThing(Enum):
    a = auto()
    b = auto()

GQLEnumThing = GQLEnum.from_enum(EnumThing)

class TestMut(ClientIDMutation):
    class Input:
        enumthing = GQLEnumThing(required=True)

    enumtype = String()

    @classmethod
    def mutate_and_get_payload(cls, root, info, enumthing, client_mutation_id=None):
        print("enumthing is", repr(enumthing), type(enumthing))
        return cls(enumtype=type(enumthing).__name__)

class Mutations(ObjectType):
    testmut = TestMut.Field()

schema = Schema(mutation=Mutations, auto_camelcase=False)

client = Client(schema)

mutation = '''
mutation whatever {
    testmut(input: {enumthing: a}) {
        enumtype
    }
}
'''

print(client.execute(mutation))

When I run this, I get the following output:

enumthing is 1 <class 'int'>
{'data': OrderedDict([('testmut', OrderedDict([('enumtype', 'int')]))])}

Instead of getting the integer 1 passed to my mutation function, I would like to have EnumThing.a passed, which is an instance of EnumThing. I haven't figured out where in graphene this translation of the literal a to the value 1 is actually happening (I would expect an access of the .value attribute on the enum somewhere).

Why? because I don't really care about the integer 1 -- that's just something generated by Python. If I log the value of this enum, I want to see that it's a EnumThing.a, not the integer 1. If I pass this thing to the rest of my codebase which is expecting it to be an instance of EnumThing, it breaks. So I end up converting it back to the instance from the integer that Graphene gave me.

@jkimbo
Copy link
Member

jkimbo commented Mar 14, 2020

@radix yep this is a change that we are going to make as part of v3. I've created a PR for it here: #1153

@tymokvo
Copy link

tymokvo commented May 13, 2020

Just upping this request. Thanks for looking into it!

And for anyone who finds their way here and wants a workaround you can use:

EnumThing.get(1)

which comes from graphene's EnumMeta.

@skewty
Copy link

skewty commented Jul 16, 2020

if the int value isn't important and you want a human friendly way to specify the value there is always str values.

from enum import Enum, auto

__all__ = ['StrEnum', 'auto']

class StrEnum(Enum):
    """Auto generates unique lowercase str names for values.

    Allows quick enum generation code like:
       Foo = StrEnum("Foo", "CREATED ADDED REMOVED")
    which rougly equates to:
        class Foo(Enum):
           CREATED = "created"
           ADDED = "added"
           REMOVED = "removed"
    or
        class Foo(StrEnum):
           CREATED = auto()
           ADDED = auto()
           REMOVED = auto()
   """

    # noinspection PyMethodParameters
    def _generate_next_value_(name, start, count, last_values) -> str:
        return name.lower()

    def __eq__(self, other: object) -> bool:
        return self.value.__eq__(other)

    def __ne__(self, other: object) -> bool:
        return self.value.__ne__(other)

    def __hash__(self) -> int:
        return self.value.__hash__()

    def __str__(self) -> str:
        return self.value

    def __len__(self) -> int:
        return self.value.__len__()

    def __cmp__(self, o: object):
        return self.value.__cmp__(o)

    def __gt__(self, other: object) -> bool:
        return self.value.__gt__(other)

    def __ge__(self, other: object) -> bool:
        return self.value.__ge__(other)

    def __lt__(self, other: object) -> bool:
        return self.value.__lt__(other)

    def __le__(self, other: object) -> bool:
        return self.value.__le__(other)

@stale
Copy link

stale bot commented Oct 18, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@jkimbo
Copy link
Member

jkimbo commented Oct 21, 2020

This was resolved in #1153

@jkimbo jkimbo closed this as completed Oct 21, 2020
karisal-anders added a commit to City-of-Helsinki/kukkuu that referenced this issue Jun 20, 2024
might be useful because Graphene 3 has changed from using enum values to
enums, for example:

```python
class TestEnum(graphene.Enum):
  FIRST = 'first'
  SECOND = 'second'
```

would've been serialized previously using the enum values, i.e.
'first' and 'second'. But with Graphene 3 they are serialized as
'TestEnum.FIRST' and 'TestEnum.SECOND'. This breaks functionality as
parts of the codebase are expecting the enum values as per Graphene 2.

Related https://github.com/graphql-python/graphene issues & PRs:
 - "Improve enum compatibility" PR:
   - graphql-python/graphene#1153
 - "graphene3: enum doesn't resolve to value" issue:
   - graphql-python/graphene#1277
 - "I would like my enum input values to be the enum instance instead
   of the enum values" issue:
   - graphql-python/graphene#1151

refs KK-1108
karisal-anders added a commit to City-of-Helsinki/kukkuu that referenced this issue Jul 8, 2024
might be useful because Graphene 3 has changed from using enum values to
enums, for example:

```python
class TestEnum(graphene.Enum):
  FIRST = 'first'
  SECOND = 'second'
```

would've been serialized previously using the enum values, i.e.
'first' and 'second'. But with Graphene 3 they are serialized as
'TestEnum.FIRST' and 'TestEnum.SECOND'. This breaks functionality as
parts of the codebase are expecting the enum values as per Graphene 2.

Related https://github.com/graphql-python/graphene issues & PRs:
 - "Improve enum compatibility" PR:
   - graphql-python/graphene#1153
 - "graphene3: enum doesn't resolve to value" issue:
   - graphql-python/graphene#1277
 - "I would like my enum input values to be the enum instance instead
   of the enum values" issue:
   - graphql-python/graphene#1151

refs KK-1108
karisal-anders added a commit to City-of-Helsinki/kukkuu that referenced this issue Jul 11, 2024
might be useful because Graphene 3 has changed from using enum values to
enums, for example:

```python
class TestEnum(graphene.Enum):
  FIRST = 'first'
  SECOND = 'second'
```

would've been serialized previously using the enum values, i.e.
'first' and 'second'. But with Graphene 3 they are serialized as
'TestEnum.FIRST' and 'TestEnum.SECOND'. This breaks functionality as
parts of the codebase are expecting the enum values as per Graphene 2.

Related https://github.com/graphql-python/graphene issues & PRs:
 - "Improve enum compatibility" PR:
   - graphql-python/graphene#1153
 - "graphene3: enum doesn't resolve to value" issue:
   - graphql-python/graphene#1277
 - "I would like my enum input values to be the enum instance instead
   of the enum values" issue:
   - graphql-python/graphene#1151

refs KK-1108
karisal-anders added a commit to City-of-Helsinki/kukkuu that referenced this issue Jul 15, 2024
might be useful because Graphene 3 has changed from using enum values to
enums, for example:

```python
class TestEnum(graphene.Enum):
  FIRST = 'first'
  SECOND = 'second'
```

would've been serialized previously using the enum values, i.e.
'first' and 'second'. But with Graphene 3 they are serialized as
'TestEnum.FIRST' and 'TestEnum.SECOND'. This breaks functionality as
parts of the codebase are expecting the enum values as per Graphene 2.

Related https://github.com/graphql-python/graphene issues & PRs:
 - "Improve enum compatibility" PR:
   - graphql-python/graphene#1153
 - "graphene3: enum doesn't resolve to value" issue:
   - graphql-python/graphene#1277
 - "I would like my enum input values to be the enum instance instead
   of the enum values" issue:
   - graphql-python/graphene#1151

refs KK-1108
karisal-anders added a commit to City-of-Helsinki/palvelutarjotin that referenced this issue Oct 9, 2024
Done:
 - Upgrade all dependencies
 - Upgrade postgresql from v10 to v13 (v13 is used in production)
 - Use ruff instead of black/isort/flake8, remove noqa's, reformat
 - Use pyproject.toml instead of setup.cfg

Background for @map_enums_to_values_in_kwargs decorator:

Graphene 3 changed from using enum values to enums, for example:
```python
class TestEnum(graphene.Enum):
  FIRST = 'first'
  SECOND = 'second'
```
would've been serialized previously using the enum values, i.e.
'first' and 'second'. But with Graphene 3 they are serialized as
'TestEnum.FIRST' and 'TestEnum.SECOND'. This broke functionality as
parts of the codebase were expecting the enum values as per Graphene 2.

Forced backwards compatibility by forcefully mapping enums to their
values.

Related https://github.com/graphql-python/graphene issues & PRs:
 - "Improve enum compatibility" PR:
   - graphql-python/graphene#1153
 - "graphene3: enum doesn't resolve to value" issue:
   - graphql-python/graphene#1277
 - "I would like my enum input values to be the enum instance instead
   of the enum values" issue:
   - graphql-python/graphene#1151

See https://github.com/graphql-python/graphene/wiki/v3-release-notes
for Graphene v3's breaking changes,

refs PT-1730
karisal-anders added a commit to City-of-Helsinki/palvelutarjotin that referenced this issue Oct 11, 2024
Done:
 - Upgrade all dependencies
 - Upgrade postgresql from v10 to v13 (v13 is used in production)
 - Use ruff instead of black/isort/flake8, remove noqa's, reformat
 - Use pyproject.toml instead of setup.cfg

Background for @map_enums_to_values_in_kwargs decorator:

Graphene 3 changed from using enum values to enums, for example:
```python
class TestEnum(graphene.Enum):
  FIRST = 'first'
  SECOND = 'second'
```
would've been serialized previously using the enum values, i.e.
'first' and 'second'. But with Graphene 3 they are serialized as
'TestEnum.FIRST' and 'TestEnum.SECOND'. This broke functionality as
parts of the codebase were expecting the enum values as per Graphene 2.

Forced backwards compatibility by forcefully mapping enums to their
values.

Related https://github.com/graphql-python/graphene issues & PRs:
 - "Improve enum compatibility" PR:
   - graphql-python/graphene#1153
 - "graphene3: enum doesn't resolve to value" issue:
   - graphql-python/graphene#1277
 - "I would like my enum input values to be the enum instance instead
   of the enum values" issue:
   - graphql-python/graphene#1151

See https://github.com/graphql-python/graphene/wiki/v3-release-notes
for Graphene v3's breaking changes,

refs PT-1730
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants