Skip to content

Commit c585e34

Browse files
committed
Generate error per duplicate schema def + Extend tests
Replicates graphql/graphql-js@3217802
1 parent 06b0a26 commit c585e34

File tree

8 files changed

+191
-65
lines changed

8 files changed

+191
-65
lines changed

README.md

+1-1
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 1539 unit tests.
16+
suite of currently 1547 unit tests.
1717

1818

1919
## Documentation

graphql/type/introspection.py

+2
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ def name(type_, _info):
216216
def description(type_, _info):
217217
return getattr(type_, 'description', None)
218218

219+
# noinspection PyPep8Naming
219220
@staticmethod
220221
def fields(type_, _info, includeDeprecated=False):
221222
if is_object_type(type_) or is_interface_type(type_):
@@ -235,6 +236,7 @@ def possible_types(type_, info):
235236
if is_abstract_type(type_):
236237
return info.schema.get_possible_types(type_)
237238

239+
# noinspection PyPep8Naming
238240
@staticmethod
239241
def enum_values(type_, _info, includeDeprecated=False):
240242
if is_enum_type(type_):

graphql/utilities/extend_schema.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,8 @@ def resolve_type(type_ref: NamedTypeNode) -> GraphQLNamedType:
446446
# correctly typed values, that would throw immediately while
447447
# type system validation with validate_schema() will produce
448448
# more actionable results.
449-
type_ = operation_type.type
450-
operation_types[operation] = ast_builder.build_type(type_)
449+
operation_types[operation] = ast_builder.build_type(
450+
operation_type.type)
451451

452452
# Then, incorporate schema definition and all schema extensions.
453453
for schema_extension in schema_extensions:
@@ -461,8 +461,8 @@ def resolve_type(type_ref: NamedTypeNode) -> GraphQLNamedType:
461461
# correctly typed values, that would throw immediately while
462462
# type system validation with validate_schema() will produce
463463
# more actionable results.
464-
type_ = operation_type.type
465-
operation_types[operation] = ast_builder.build_type(type_)
464+
operation_types[operation] = ast_builder.build_type(
465+
operation_type.type)
466466

467467
schema_extension_ast_nodes = (
468468
schema.extension_ast_nodes or cast(Tuple[SchemaExtensionNode], ())
@@ -472,8 +472,7 @@ def resolve_type(type_ref: NamedTypeNode) -> GraphQLNamedType:
472472
# that any type not directly referenced by a value will get created.
473473
types = list(map(extend_named_type, schema.type_map.values()))
474474
# do the same with new types
475-
types.extend(ast_builder.build_type(type_)
476-
for type_ in type_definition_map.values())
475+
types.extend(map(ast_builder.build_type, type_definition_map.values()))
477476

478477
# Then produce and return a Schema with these types.
479478
return GraphQLSchema( # type: ignore
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
from typing import List
2-
31
from ...error import GraphQLError
42
from ...language import SchemaDefinitionNode
53
from . import SDLValidationRule, SDLValidationContext
64

75
__all__ = [
86
'LoneSchemaDefinition',
9-
'schema_definition_alone_message', 'cannot_define_schema_within_extension']
7+
'schema_definition_not_alone_message',
8+
'cannot_define_schema_within_extension_message']
109

1110

12-
def schema_definition_alone_message():
11+
def schema_definition_not_alone_message():
1312
return 'Must provide only one schema definition.'
1413

1514

16-
def cannot_define_schema_within_extension():
15+
def cannot_define_schema_within_extension_message():
1716
return 'Cannot define a new schema within a schema extension.'
1817

1918

@@ -29,16 +28,14 @@ def __init__(self, context: SDLValidationContext) -> None:
2928
self.already_defined = old_schema and (
3029
old_schema.ast_node or old_schema.query_type or
3130
old_schema.mutation_type or old_schema.subscription_type)
32-
self.schema_nodes: List[SchemaDefinitionNode] = []
31+
self.schema_definitions_count = 0
3332

3433
def enter_schema_definition(self, node: SchemaDefinitionNode, *_args):
3534
if self.already_defined:
3635
self.report_error(GraphQLError(
37-
cannot_define_schema_within_extension(), [node]))
36+
cannot_define_schema_within_extension_message(), node))
3837
else:
39-
self.schema_nodes.append(node)
40-
41-
def leave_document(self, *_args):
42-
if len(self.schema_nodes) > 1:
43-
self.report_error(GraphQLError(
44-
schema_definition_alone_message(), self.schema_nodes))
38+
if self.schema_definitions_count:
39+
self.report_error(GraphQLError(
40+
schema_definition_not_alone_message(), node))
41+
self.schema_definitions_count += 1

tests/utilities/test_build_ast_schema.py

+3-23
Original file line numberDiff line numberDiff line change
@@ -726,26 +726,6 @@ def allows_to_disable_sdl_validation():
726726

727727
def describe_failures():
728728

729-
def allows_only_a_single_schema_definition():
730-
body = dedent("""
731-
schema {
732-
query: Hello
733-
}
734-
735-
schema {
736-
query: Hello
737-
}
738-
739-
type Hello {
740-
bar: Bar
741-
}
742-
""")
743-
doc = parse(body)
744-
with raises(TypeError) as exc_info:
745-
build_ast_schema(doc)
746-
msg = str(exc_info.value)
747-
assert msg == 'Must provide only one schema definition.'
748-
749729
def allows_only_a_single_query_type():
750730
body = dedent("""
751731
schema {
@@ -754,7 +734,7 @@ def allows_only_a_single_query_type():
754734
}
755735
756736
type Hello {
757-
bar: Bar
737+
bar: String
758738
}
759739
760740
type Yellow {
@@ -776,7 +756,7 @@ def allows_only_a_single_mutation_type():
776756
}
777757
778758
type Hello {
779-
bar: Bar
759+
bar: String
780760
}
781761
782762
type Yellow {
@@ -797,7 +777,7 @@ def allows_only_a_single_subscription_type():
797777
subscription: Yellow
798778
}
799779
type Hello {
800-
bar: Bar
780+
bar: String
801781
}
802782
803783
type Yellow {

tests/utilities/test_extend_schema.py

-15
Original file line numberDiff line numberDiff line change
@@ -1096,21 +1096,6 @@ def does_not_automatically_include_common_root_type_names():
10961096
""")
10971097
assert schema.mutation_type is None
10981098

1099-
def does_not_allow_overriding_schema_within_an_extension():
1100-
sdl = """
1101-
schema {
1102-
mutation: Mutation
1103-
}
1104-
1105-
type Mutation {
1106-
doSomething: String
1107-
}
1108-
"""
1109-
with raises(TypeError) as exc_info:
1110-
extend_test_schema(sdl)
1111-
assert str(exc_info.value).startswith(
1112-
'Cannot define a new schema within a schema extension.')
1113-
11141099
def adds_schema_definition_missing_in_the_original_schema():
11151100
schema = GraphQLSchema(
11161101
directives=[FooDirective],

tests/validation/test_known_directives.py

+39-7
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def with_misplaced_directives():
130130
def describe_within_sdl():
131131

132132
def with_directive_defined_inside_sdl():
133-
expect_sdl_errors("""
133+
assert expect_sdl_errors("""
134134
type Query {
135135
foo: String @test
136136
}
@@ -139,23 +139,56 @@ def with_directive_defined_inside_sdl():
139139
""") == []
140140

141141
def with_standard_directive():
142-
expect_sdl_errors("""
142+
assert expect_sdl_errors("""
143143
type Query {
144144
foo: String @deprecated
145145
}
146146
""") == []
147147

148148
def with_overridden_standard_directive():
149-
expect_sdl_errors("""
149+
assert expect_sdl_errors("""
150150
schema @deprecated {
151151
query: Query
152152
}
153153
directive @deprecated on SCHEMA
154154
""") == []
155155

156-
# noinspection PyShadowingNames
156+
def with_directive_defined_in_schema_extension():
157+
schema = build_schema("""
158+
type Query {
159+
foo: String
160+
}
161+
""")
162+
assert expect_sdl_errors("""
163+
directive @test on OBJECT
164+
165+
extend type Query @test
166+
""", schema) == []
167+
168+
def with_directive_used_in_schema_extension():
169+
schema = build_schema("""
170+
directive @test on OBJECT
171+
172+
type Query {
173+
foo: String
174+
}
175+
""")
176+
assert expect_sdl_errors("""
177+
extend type Query @test
178+
""", schema) == []
179+
180+
def with_unknown_directive_in_schema_extension():
181+
schema = build_schema("""
182+
type Query {
183+
foo: String
184+
}
185+
""")
186+
assert expect_sdl_errors("""
187+
extend type Query @unknown
188+
""", schema) == [unknown_directive('unknown', 2, 35)]
189+
157190
def with_well_placed_directives():
158-
expect_sdl_errors("""
191+
assert expect_sdl_errors("""
159192
type MyObj implements MyInterface @onObject {
160193
myField(myArg: Int @onArgumentDefinition): String @onFieldDefinition
161194
}
@@ -196,9 +229,8 @@ def with_well_placed_directives():
196229
""", # noqa
197230
schema_with_sdl_directives) == []
198231

199-
# noinspection PyShadowingNames
200232
def with_misplaced_directives():
201-
expect_sdl_errors("""
233+
assert expect_sdl_errors("""
202234
type MyObj implements MyInterface @onInterface {
203235
myField(myArg: Int @onInputFieldDefinition): String @onInputFieldDefinition
204236
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
from functools import partial
2+
3+
from graphql.utilities import build_schema
4+
from graphql.validation.rules.lone_schema_definition import (
5+
LoneSchemaDefinition, schema_definition_not_alone_message,
6+
cannot_define_schema_within_extension_message)
7+
8+
from .harness import expect_sdl_errors_from_rule
9+
10+
expect_sdl_errors = partial(
11+
expect_sdl_errors_from_rule, LoneSchemaDefinition)
12+
13+
14+
def schema_definition_not_alone(line, column):
15+
return {
16+
'message': schema_definition_not_alone_message(),
17+
'locations': [(line, column)]}
18+
19+
20+
def cannot_define_schema_within_extension(line, column):
21+
return {
22+
'message': cannot_define_schema_within_extension_message(),
23+
'locations': [(line, column)]}
24+
25+
26+
def describe_validate_schema_definition_should_be_alone():
27+
28+
def no_schema():
29+
assert expect_sdl_errors("""
30+
type Query {
31+
foo: String
32+
}
33+
""") == []
34+
35+
def one_schema_definition():
36+
assert expect_sdl_errors("""
37+
schema {
38+
query: Foo
39+
}
40+
41+
type Foo {
42+
foo: String
43+
}
44+
""") == []
45+
46+
def multiple_schema_definitions():
47+
assert expect_sdl_errors("""
48+
schema {
49+
query: Foo
50+
}
51+
52+
type Foo {
53+
foo: String
54+
}
55+
56+
schema {
57+
mutation: Foo
58+
}
59+
60+
schema {
61+
subscription: Foo
62+
}
63+
""") == [
64+
schema_definition_not_alone(10, 13),
65+
schema_definition_not_alone(14, 13)]
66+
67+
def define_schema_in_schema_extension():
68+
schema = build_schema("""
69+
type Foo {
70+
foo: String
71+
}
72+
""")
73+
74+
assert expect_sdl_errors("""
75+
schema {
76+
query: Foo
77+
}
78+
""", schema) == []
79+
80+
def redefine_schema_in_schema_extension():
81+
schema = build_schema("""
82+
schema {
83+
query: Foo
84+
}
85+
86+
type Foo {
87+
foo: String
88+
}
89+
""")
90+
91+
assert expect_sdl_errors("""
92+
schema {
93+
mutation: Foo
94+
}
95+
""", schema) == [
96+
cannot_define_schema_within_extension(2, 13)]
97+
98+
def redefine_implicit_schema_in_schema_extension():
99+
schema = build_schema("""
100+
type Query {
101+
fooField: Foo
102+
}
103+
104+
type Foo {
105+
foo: String
106+
}
107+
""")
108+
109+
assert expect_sdl_errors("""
110+
schema {
111+
mutation: Foo
112+
}
113+
""", schema) == [
114+
cannot_define_schema_within_extension(2, 13)]
115+
116+
def extend_schema_in_schema_extension():
117+
schema = build_schema("""
118+
type Query {
119+
fooField: Foo
120+
}
121+
122+
type Foo {
123+
foo: String
124+
}
125+
""")
126+
127+
assert expect_sdl_errors("""
128+
extend schema {
129+
mutation: Foo
130+
}
131+
""", schema) == []

0 commit comments

Comments
 (0)