graphql-python/gql

`KeyError` when parsing result using fragment and nested field

michael-nml opened this issue ยท 3 comments

Describe the bug
Executing a query that contains a fragment next to a nested field results in a KeyError when parsing results.

Example query:

query HeroNameAndFriendsQuery {
  hero {
    ...HeroSummary
    friends {
      name
    }
  }
}
fragment HeroSummary on Character {
  id
  name
}

Stacktrace:

Traceback (most recent call last):
  File "/home/mvds/nannyml/external/gql/tests/starwars/test_parse_results.py", line 70, in test_hero_name_and_friends_fragment_query
    parsed_result = parse_result(StarWarsSchema, query, result)
  File "/home/mvds/nannyml/external/gql/gql/utilities/parse_result.py", line 441, in parse_result
    return parse_result_recursive(
  File "/home/mvds/nannyml/external/gql/gql/utilities/parse_result.py", line 394, in parse_result_recursive
    visited = visit(
  File "/home/mvds/nannyml/external/gql/.venv/lib/python3.10/site-packages/graphql/language/visitor.py", line 257, in visit
    result = visit_fn(node, key, parent, path, ancestors)
  File "/home/mvds/nannyml/external/gql/.venv/lib/python3.10/site-packages/graphql/utilities/type_info.py", line 280, in enter
    result = fn(node, *args)
  File "/home/mvds/nannyml/external/gql/gql/utilities/parse_result.py", line 264, in enter_field
    visits.append(inner_visit[0][name])
KeyError: 'friends'

To Reproduce
Following test case reproduces the issue using the StarWarsSchema defined in tests/starwars/schema.py

from gql import gql
from gql.utilities import parse_result
from tests.starwars.schema import StarWarsSchema

def test_hero_name_and_friends_fragment_query():
    query = gql(
        """
        query HeroNameAndFriendsQuery {
          hero {
            ...HeroSummary
            friends {
              name
            }
          }
        }
        fragment HeroSummary on Character {
          id
          name
        }
        """
    )
    result = {
        "hero": {
            "id": "2001",
            "friends": [
                {"name": "Luke Skywalker"},
                {"name": "Han Solo"},
                {"name": "Leia Organa"},
            ],
            "name": "R2-D2",
        }
    }

    parsed_result = parse_result(StarWarsSchema, query, result)

    assert result == parsed_result

Expected behavior
Parsing without error so that the assertion passes.

System info (please complete the following information):

  • OS: WSL2 on Windows
  • Python version: 3.10
  • gql version: 3.5.0b6
  • graphql-core version: 3.3.0a3

Thanks for the detailed bug report. I'm looking into it.

As a workaround, it seems to work if you put the fragment at the end like this:

query HeroNameAndFriendsQuery {
  hero {
    friends {
      name
    }
    ...HeroSummary
  }
}
fragment HeroSummary on Character {
  id
  name
}

Thank you for the quick reply! Your proposed workaround works for my purposes ๐Ÿ‘

It should be fixed in pre-release v3.5.0b7.