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

Interface.resolve_type classmethod makes it impossible to have a field named 'type' #899

Closed
lexdene opened this issue Jan 28, 2019 · 4 comments
Labels
3.0 Fix/Release version 3.0 wontfix
Milestone

Comments

@lexdene
Copy link

lexdene commented Jan 28, 2019

The resolve_type method on Interface conflicts with actually resolving a field called type.

The below test fails with GraphQLError('Expected a value of type "Color" but received: RedItem',).

from graphene import (
    Schema,
    ObjectType, Interface, Field,
    List, Enum, Int, String,
)


class ItemData(object):
    def __init__(self, data):
        self.data = data

    def __getattr__(self, key):
        return self.data[key]


class Color(Enum):
    red = 1
    green = 2
    blue = 3


class Item(Interface):
    id = Int()
    type = Field(Color)

    @classmethod
    def resolve_type(cls, instance, info):
        if instance.type == Color.red.value:
            return RedItem
        elif instance.type == Color.green.value:
            return GreenItem
        elif instance.type == Color.blue.value:
            return BlueItem


class RedItem(ObjectType):
    foo = String()

    class Meta:
        interfaces = Item,


class GreenItem(ObjectType):
    bar = String()

    class Meta:
        interfaces = Item,


class BlueItem(ObjectType):
    baz = String()

    class Meta:
        interfaces = Item,


class Query(ObjectType):
    get_items = List(Item)

    def resolve_get_items(self, info):
        items = [
            {
                "id": 4921312,
                "type": 1,
                "foo": "blahblah"
            },
            {
                "id": 3137806,
                "type": 2,
                "bar": "clahclah",
            },
            {
                "id": 9781512,
                "type": 3,
                "baz": "dlahdlah",
            },
        ]

        return [ItemData(i) for i in items]


schema = Schema(
    query=Query,
    types=[RedItem, GreenItem, BlueItem],
)

QUERY = '''
fragment itemFields on Item {
  id
  type
  ... on RedItem {
      foo
  }
  ... on GreenItem {
      bar
  }
  ... on BlueItem {
      baz
  }
}
query SomeQuery {
  getItems{
    ... itemFields
  }
}
'''

EXPECTED_RESPONSE = {
    'getItems': [
        {
            'id': 4921312,
            'type': 'red',
            'foo': 'blahblah',
        },
        {
            'id': 3137806,
            'type': 'green',
            'bar': 'clahclah',
        },
        {
            'id': 9781512,
            'type': 'blue',
            'baz': 'dlahdlah',
        },
    ]
}


def main():
    result = schema.execute(QUERY)
    assert not result.errors
    assert result.data == EXPECTED_RESPONSE
@norman-thomas
Copy link

You can avoid such naming conflicts by using the name parameter. You just name the field differently, but pass name='type' in your field definition. So in your case:

class Item(Interface):
    id = Int()
    type_ = Field(Color, name='type')  # notice the underscore in type_

    @classmethod
    def resolve_type_(cls, instance, info):
        if instance.type == Color.red.value:
            return RedItem
        elif instance.type == Color.green.value:
            return GreenItem
        elif instance.type == Color.blue.value:
            return BlueItem

Typically, you can do the same for other names like id where pylint usually complains about using a reserved keyword as variable name.

@lexdene
Copy link
Author

lexdene commented Feb 19, 2019

@norman-thomas
The resolve_type of ObjectType has been rename to _resolve_type in 7340d80
I suggest that Interface.resolve_type can do the same thing to avoid such naming conflicts.

@jkimbo
Copy link
Member

jkimbo commented Mar 16, 2019

There is an open PR that fixes this: #775

However because it's a breaking change it will have to be part of a v3 release.

@ProjectCheshire ProjectCheshire added this to the v3.0.0 milestone Apr 1, 2019
@ProjectCheshire ProjectCheshire added the 3.0 Fix/Release version 3.0 label Jun 2, 2019
@stale
Copy link

stale bot commented Aug 1, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.0 Fix/Release version 3.0 wontfix
Projects
None yet
Development

No branches or pull requests

4 participants