Skip to content

Issues using a deep-copied GraphQLSchema  #100

Closed
@pmantica1

Description

@pmantica1

To make our tests in the GraphQL compiler library run faster, we wanted to parse and build our test schema once and have each test case use a deep copied version of our test schema. We want each test to use their own deep-copied schema so that accidental schema modifications in one test case wouldn't affect the results of another test case.
kensho-technologies/graphql-compiler#873

It seems, however, that we can't use deep-copied schemas with certain GraphQL core functions as evidenced by the code below.:

from graphql import build_schema, print_schema, lexicographic_sort_schema
from copy import deepcopy

SCHEMA_TEXT = """
    schema {
        query: RootSchemaQuery
    }

    type Animal {
        uuid: ID
    }

    type RootSchemaQuery {
        Animal: [Animal]
    }
"""
# This test case passes
assert (
    print_schema(lexicographic_sort_schema(build_schema(SCHEMA_TEXT))) ==
    print_schema(lexicographic_sort_schema(build_schema(SCHEMA_TEXT)))
)

graphql_schema = build_schema(SCHEMA_TEXT)
graphql_schema_copy = deepcopy(graphql_schema)

# This test case fails. I included part of the stack trace as an image.
assert (
    print_schema(lexicographic_sort_schema(graphql_schema)) ==
    print_schema(lexicographic_sort_schema(graphql_schema_copy))
)

I think I figured out the problem with using a deepcopy in this particular instance.

The GraphQLSchema __init__ function uses a TypeSet that checks if two GraphQL types are equal by comparing their python object references. The __init__ function includes the builtin __Schema type is not already included in this TypeSet.

When we use deepcopy we generate new object references for all of the copied objects. So when we use the types in a deep-copied schema to build a lexicographically sorted schema, we call the GraphQLSchema __init__ function which doubly adds the __Schema type since the deep-copied __Schema type has a different reference than the original __Schema type. This in turns leads to an error later in the __init__ function call when checking if there are multiple types with the same name.

I suspect that we might find similar issues when using other GraphQL core functions. We, however, understand that making GraphQLSchema objects "deep-copyable" might take a lot of upfront work and a lot of maintenance work thereafter. So we understand if you don't want to commit to this. We still wanted to bring this issue to light though.

As always, thanks for the amazing work of porting the GraphQL js library to python.

Screenshot from 2020-07-07 09-53-09

Metadata

Metadata

Assignees

Labels

investigateNeeds investigaton or experimentation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions