8000 Allows to add schema definition missing in the original schema · graphql-python/graphql-core@27d0ce3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 27d0ce3

Browse files
committed
Allows to add schema definition missing in the original schema
Replicates graphql/graphql-js@a1ee52a
1 parent 2d98c47 commit 27d0ce3

File tree

3 files changed

+61
-24
lines changed

3 files changed

+61
-24
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ a query language for APIs created by Facebook.
1313

1414
The current version 1.0.0rc2 of GraphQL-core-next is up-to-date with GraphQL.js
1515
version 14.0.0rc2. All parts of the API are covered by an extensive test
16-
suite of currently 1530 unit tests.
16+
suite of currently 1531 unit tests.
1717

1818

1919
## Documentation

graphql/utilities/extend_schema.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,19 @@ def extend_schema(schema: GraphQLSchema, document_ast: DocumentNode,
6464
# have the same name. For example, a type named "skip".
6565
directive_definitions: List[DirectiveDefinitionNode] = []
6666

67+
schema_def: Optional[SchemaDefinitionNode] = None
6768
# Schema extensions are collected which may add additional operation types.
6869
schema_extensions: List[SchemaExtensionNode] = []
6970

7071
for def_ in document_ast.definitions:
7172
if isinstance(def_, SchemaDefinitionNode):
72-
# Sanity check that a schema extension is not defining a new schema
73-
raise GraphQLError(
74-
'Cannot define a new schema within a schema extension.',
75-
[def_])
73+
# Sanity check that a schema extension is not overriding the schema
74+
if (schema.ast_node or schema.query_type or
75+
schema.mutation_type or schema.subscription_type):
76+
raise GraphQLError(
77+
'Cannot define a new schema within a schema extension.',
78+
[def_])
79+
schema_def = def_
7680
elif isinstance(def_, SchemaExtensionNode):
7781
schema_extensions.append(def_)
7882
elif isinstance(def_, (
@@ -121,7 +125,8 @@ def extend_schema(schema: GraphQLSchema, document_ast: DocumentNode,
121125
# If this document contains no new types, extensions, or directives then
122126
# return the same unmodified GraphQLSchema instance.
123127
if (not type_extensions_map and not type_definition_map
124-
and not directive_definitions and not schema_extensions):
128+
and not directive_definitions and not schema_extensions
129+
and not schema_def):
125130
return schema
126131

127132
# Below are functions used for producing this schema that have closed over
@@ -431,20 +436,33 @@ def resolve_type(type_ref: NamedTypeNode) -> GraphQLNamedType:
431436
OperationType.SUBSCRIPTION:
432437
extend_maybe_named_type(schema.subscription_type)}
433438

434-
# Then, incorporate all schema extensions.
439+
if schema_def:
440+
for operation_type in schema_def.operation_types:
441+
operation = operation_type.operation
442+
if operation_types[operation]:
443+
raise TypeError(
444+
f'Must provide only one {operation.value} type in schema.')
445+
# Note: While this could make early assertions to get the
446+
# correctly typed values, that would throw immediately while
447+
# type system validation with validate_schema() will produce
448+
# more actionable results.
449+
type_ = operation_type.type
450+
operation_types[operation] = ast_builder.build_type(type_)
451+
452+
# Then, incorporate schema definition and all schema extensions.
435453
for schema_extension in schema_extensions:
436454
if schema_extension.operation_types:
437455
for operation_type in schema_extension.operation_types:
438456
operation = operation_type.operation
439457
if operation_types[operation]:
440458
raise TypeError(f'Must provide only one {operation.value}'
441459
' type in schema.')
442-
type_ref = operation_type.type
443460
# Note: While this could make early assertions to get the
444461
# correctly typed values, that would throw immediately while
445462
# type system validation with validate_schema() will produce
446-
# more actionable results
447-
operation_types[operation] = ast_builder.build_type(type_ref)
463+
# more actionable results.
464+
type_ = operation_type.type
465+
operation_types[operation] = ast_builder.build_type(type_)
448466

449467
schema_extension_ast_nodes = (
450468
schema.extension_ast_nodes or cast(Tuple[SchemaExtensionNode], ())

tests/utilities/test_extend_schema.py

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,22 @@
5959
SomeInputType = GraphQLInputObjectType('SomeInput', lambda: {
6060
'fooArg': GraphQLInputField(GraphQLString)})
6161

62+
FooDirective = GraphQLDirective(
63+
name='foo',
64+
args={'input': GraphQLArgument(SomeInputType)},
65+
locations=[
66+
DirectiveLocation.SCHEMA,
67+
DirectiveLocation.SCALAR,
68+
DirectiveLocation.OBJECT,
69+
DirectiveLocation.FIELD_DEFINITION,
70+
DirectiveLocation.ARGUMENT_DEFINITION,
71+
DirectiveLocation.INTERFACE,
72+
DirectiveLocation.UNION,
73+
DirectiveLocation.ENUM,
74+
DirectiveLocation.ENUM_VALUE,
75+
DirectiveLocation.INPUT_OBJECT,
76+
DirectiveLocation.INPUT_FIELD_DEFINITION])
77+
6278
test_schema = GraphQLSchema(
6379
query=GraphQLObjectType(
6480
name='Query',
@@ -74,19 +90,7 @@
7490
GraphQLString,
7591
args={'input': GraphQLArgument(SomeInputType)})}),
7692
types=[FooType, BarType],
77-
directives=specified_directives + (GraphQLDirective(
78-
'foo', args={'input': GraphQLArgument(SomeInputType)}, locations=[
79-
DirectiveLocation.SCHEMA,
80-
DirectiveLocation.SCALAR,
81-
DirectiveLocation.OBJECT,
82-
DirectiveLocation.FIELD_DEFINITION,
83-
DirectiveLocation.ARGUMENT_DEFINITION,
84-
DirectiveLocation.INTERFACE,
85-
DirectiveLocation.UNION,
86-
DirectiveLocation.ENUM,
87-
DirectiveLocation.ENUM_VALUE,
88-
DirectiveLocation.INPUT_OBJECT,
89-
DirectiveLocation.INPUT_FIELD_DEFINITION]),))
93+
directives=specified_directives + (FooDirective,))
9094

9195

9296
def extend_test_schema(sdl, **options) -> GraphQLSchema:
@@ -1076,7 +1080,7 @@ def does_not_automatically_include_common_root_type_names():
10761080
""")
10771081
assert schema.mutation_type is None
10781082

1079-
def does_not_allow_new_schema_within_an_extension():
1083+
def does_not_allow_overriding_schema_within_an_extension():
10801084
sdl = """
10811085
schema {
10821086
mutation: Mutation
@@ -1091,6 +1095,21 @@ def does_not_allow_new_schema_within_an_extension():
10911095
assert str(exc_info.value).startswith(
10921096
'Cannot define a new schema within a schema extension.')
10931097

1098+
def adds_schema_definition_missing_in_the_original_schema():
1099+
schema = GraphQLSchema(
1100+
directives=[FooDirective],
1101+
types=[FooType])
1102+
assert schema.query_type is None
1103+
1104+
ast = parse("""
1105+
schema @foo {
1106+
query: Foo
1107+
}
1108+
""")
1109+
schema = extend_schema(schema, ast)
1110+
query_type = schema.query_type
1111+
assert query_type.name == 'Foo'
1112+
10941113
def adds_new_root_types_via_schema_extension():
10951114
schema = extend_test_schema("""
10961115
extend schema {

0 commit comments

Comments
 (0)
0