Skip to content

Commit bc66414

Browse files
committed
Improve coverage in type package
1 parent 224bb07 commit bc66414

File tree

6 files changed

+136
-30
lines changed

6 files changed

+136
-30
lines changed

Diff for: src/graphql/pyutils/inspect.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,21 @@ def inspect_recursive(value: Any, seen_values: List) -> str:
120120
type_ = "generator"
121121
else:
122122
# stringify (only) the well-known GraphQL types
123-
from ..type import GraphQLNamedType, GraphQLScalarType, GraphQLWrappingType
123+
from ..type import (
124+
GraphQLDirective,
125+
GraphQLNamedType,
126+
GraphQLScalarType,
127+
GraphQLWrappingType,
128+
)
124129

125130
if isinstance(
126-
value, (GraphQLNamedType, GraphQLScalarType, GraphQLWrappingType)
131+
value,
132+
(
133+
GraphQLDirective,
134+
GraphQLNamedType,
135+
GraphQLScalarType,
136+
GraphQLWrappingType,
137+
),
127138
):
128139
return str(value)
129140
try:

Diff for: src/graphql/type/scalars.py

+6-9
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,7 @@ def serialize_int(output_value: Any) -> int:
4747
output_value = ""
4848
raise ValueError
4949
else:
50-
num = int(output_value)
51-
float_value = float(output_value)
52-
if num != float_value:
53-
raise ValueError
50+
num = int(output_value) # raises ValueError if not an integer
5451
except (OverflowError, ValueError, TypeError):
5552
raise GraphQLError(
5653
"Int cannot represent non-integer value: " + inspect(output_value)
@@ -245,11 +242,11 @@ def serialize_id(output_value: Any) -> str:
245242

246243

247244
def coerce_id(input_value: Any) -> str:
248-
if not isinstance(input_value, str) and not is_integer(input_value):
249-
raise GraphQLError("ID cannot represent value: " + inspect(input_value))
250-
if isinstance(input_value, float):
251-
input_value = int(input_value)
252-
return str(input_value)
245+
if isinstance(input_value, str):
246+
return input_value
247+
if is_integer(input_value):
248+
return str(input_value)
249+
raise GraphQLError("ID cannot represent value: " + inspect(input_value))
253250

254251

255252
def parse_id_literal(value_node, _variables=None) -> str:

Diff for: src/graphql/type/validate.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def validate_name(self, node: Any, name: Optional[str] = None) -> None:
171171
name = node.name
172172
name = cast(str, name)
173173
ast_node = node.ast_node
174-
except AttributeError:
174+
except AttributeError: # pragma: no cover
175175
pass
176176
else:
177177
error = is_valid_name_error(name, ast_node)
@@ -185,8 +185,8 @@ def validate_types(self) -> None:
185185
# Ensure all provided types are in fact GraphQL type.
186186
if not is_named_type(type_):
187187
self.report_error(
188-
f"Expected GraphQL named type but got: {inspect(type)}.",
189-
type_.ast_node if type_ else None,
188+
f"Expected GraphQL named type but got: {inspect(type_)}.",
189+
type_.ast_node if is_named_type(type_) else None,
190190
)
191191
continue
192192

@@ -543,7 +543,7 @@ def get_all_sub_nodes(
543543
result: List[Node] = []
544544
for ast_node in get_all_nodes(obj):
545545
sub_nodes = getter(ast_node)
546-
if sub_nodes:
546+
if sub_nodes: # pragma: no cover
547547
result.extend(sub_nodes)
548548
return result
549549

Diff for: tests/pyutils/test_inspect.py

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from graphql.pyutils import inspect, Undefined
99
from graphql.type import (
10+
GraphQLDirective,
1011
GraphQLField,
1112
GraphQLInt,
1213
GraphQLList,
@@ -328,6 +329,8 @@ def inspect_graphql_types():
328329
"TestObjectType", {"test": GraphQLField(GraphQLString)}
329330
)
330331
assert inspect(test_object_type) == "TestObjectType"
332+
test_directive = GraphQLDirective("TestDirective", [])
333+
assert inspect(test_directive) == "@TestDirective"
331334

332335
def custom_inspect():
333336
class TestClass:

Diff for: tests/type/test_schema.py

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
from pytest import raises # type: ignore
22

3-
from graphql.language import DirectiveLocation, TypeDefinitionNode, TypeExtensionNode
4-
from graphql.pyutils import dedent
3+
from graphql.language import (
4+
DirectiveLocation,
5+
SchemaDefinitionNode,
6+
SchemaExtensionNode,
7+
TypeDefinitionNode,
8+
TypeExtensionNode,
9+
)
10+
from graphql.pyutils import dedent, FrozenList
511
from graphql.type import (
612
GraphQLArgument,
713
GraphQLBoolean,
@@ -312,6 +318,26 @@ def configures_the_schema_to_have_no_errors():
312318
assert GraphQLSchema(assume_valid=True).validation_errors == []
313319

314320
def describe_ast_nodes():
321+
def accepts_a_scalar_type_with_ast_node_and_extension_ast_nodes():
322+
ast_node = SchemaDefinitionNode()
323+
extension_ast_nodes = [SchemaExtensionNode()]
324+
schema = GraphQLSchema(
325+
GraphQLObjectType("Query", {}),
326+
ast_node=ast_node,
327+
extension_ast_nodes=extension_ast_nodes,
328+
)
329+
assert schema.ast_node is ast_node
330+
assert isinstance(schema.extension_ast_nodes, FrozenList)
331+
assert schema.extension_ast_nodes == extension_ast_nodes
332+
extension_ast_nodes = schema.extension_ast_nodes
333+
schema = GraphQLSchema(
334+
GraphQLObjectType("Query", {}),
335+
ast_node=None,
336+
extension_ast_nodes=extension_ast_nodes,
337+
)
338+
assert schema.ast_node is None
339+
assert schema.extension_ast_nodes is extension_ast_nodes
340+
315341
def rejects_a_schema_with_an_incorrect_ast_node():
316342
with raises(TypeError) as exc_info:
317343
# noinspection PyTypeChecker

Diff for: tests/type/test_validation.py

+82-13
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
fields={"val": GraphQLInputField(GraphQLString, default_value="hello")},
5555
)
5656

57+
SomeDirective = GraphQLDirective("SomeDirective", [DirectiveLocation.QUERY])
58+
5759

5860
def with_modifiers(
5961
types: List[GraphQLNamedType],
@@ -392,22 +394,51 @@ def rejects_a_schema_extended_with_invalid_root_types():
392394
},
393395
]
394396

397+
def rejects_a_schema_whose_types_are_incorrectly_type():
398+
# invalid schema cannot be built with Python
399+
with raises(TypeError) as exc_info:
400+
# noinspection PyTypeChecker
401+
GraphQLSchema(
402+
SomeObjectType,
403+
types=[{"name": "SomeType"}, SomeDirective], # type: ignore
404+
)
405+
assert str(exc_info.value) == (
406+
"Schema types must be specified"
407+
" as a collection of GraphQLNamedType instances."
408+
)
409+
# construct invalid schema manually
410+
schema = GraphQLSchema(SomeObjectType)
411+
schema.type_map = {
412+
"SomeType": {"name": "SomeType"}, # type: ignore
413+
"SomeDirective": SomeDirective, # type: ignore
414+
}
415+
assert validate_schema(schema) == [
416+
{"message": "Expected GraphQL named type but got: {'name': 'SomeType'}."},
417+
{"message": "Expected GraphQL named type but got: @SomeDirective."},
418+
]
419+
395420
def rejects_a_schema_whose_directives_are_incorrectly_typed():
396421
# invalid schema cannot be built with Python
397422
with raises(TypeError) as exc_info:
423+
# noinspection PyTypeChecker
398424
GraphQLSchema(
399-
SomeObjectType, directives=[cast(GraphQLDirective, "SomeDirective")]
425+
SomeObjectType,
426+
directives=[None, "SomeDirective", SomeScalarType], # type: ignore
400427
)
401428
assert str(exc_info.value) == (
402429
"Schema directives must be specified"
403430
" as a collection of GraphQLDirective instances."
404431
)
405-
432+
# construct invalid schema manually
406433
schema = GraphQLSchema(SomeObjectType)
407-
schema.directives = FrozenList([cast(GraphQLDirective, "SomeDirective")])
408-
409-
msg = validate_schema(schema)[0].message
410-
assert msg == "Expected directive but got: 'SomeDirective'."
434+
schema.directives = FrozenList(
435+
[None, "SomeDirective", SomeScalarType] # type: ignore
436+
)
437+
assert validate_schema(schema) == [
438+
{"message": "Expected directive but got: None."},
439+
{"message": "Expected directive but got: 'SomeDirective'."},
440+
{"message": "Expected directive but got: SomeScalar."},
441+
]
411442

412443

413444
def describe_type_system_objects_must_have_fields():
@@ -532,6 +563,7 @@ def rejects_a_union_type_with_empty_types():
532563
union BadUnion
533564
"""
534565
)
566+
535567
schema = extend_schema(
536568
schema,
537569
parse(
@@ -542,10 +574,10 @@ def rejects_a_union_type_with_empty_types():
542574
"""
543575
),
544576
)
577+
545578
assert validate_schema(schema) == [
546579
{
547-
"message": "Union type BadUnion must define one or more"
548-
" member types.",
580+
"message": "Union type BadUnion must define one or more member types.",
549581
"locations": [(6, 13), (4, 17)],
550582
}
551583
]
@@ -931,12 +963,12 @@ def rejects_with_relevant_locations_for_a_non_output_type():
931963

932964
def describe_type_system_objects_can_only_implement_unique_interfaces():
933965
def rejects_an_object_implementing_a_non_type_values():
934-
schema = GraphQLSchema(
935-
query=GraphQLObjectType(
936-
"BadObject", {"f": GraphQLField(GraphQLString)}, interfaces=[]
937-
)
966+
query_type = GraphQLObjectType(
967+
"BadObject", {"f": GraphQLField(GraphQLString)}, interfaces=[]
938968
)
939-
schema.query_type.interfaces.append(None) # type: ignore
969+
# noinspection PyTypeChecker
970+
query_type.interfaces.append(None)
971+
schema = GraphQLSchema(query_type)
940972

941973
assert validate_schema(schema) == [
942974
{
@@ -1921,6 +1953,24 @@ def rejects_an_interface_with_a_differently_typed_interface_field():
19211953
}
19221954
]
19231955

1956+
def accepts_an_interface_with_a_subtyped_interface_field_interface():
1957+
schema = build_schema(
1958+
"""
1959+
type Query {
1960+
test: ChildInterface
1961+
}
1962+
1963+
interface ParentInterface {
1964+
field: ParentInterface
1965+
}
1966+
1967+
interface ChildInterface implements ParentInterface {
1968+
field: ChildInterface
1969+
}
1970+
"""
1971+
)
1972+
assert validate_schema(schema) == []
1973+
19241974
def accepts_an_interface_with_a_subtyped_interface_field_union():
19251975
schema = build_schema(
19261976
"""
@@ -1967,6 +2017,25 @@ def rejects_an_interface_implementing_a_non_interface_type():
19672017
"BadInterface interfaces must be specified as a collection"
19682018
" of GraphQLInterfaceType instances."
19692019
)
2020+
# therefore we construct the invalid schema manually
2021+
some_input_obj = GraphQLInputObjectType(
2022+
"SomeInputObject", {"field": GraphQLInputField(GraphQLString)}
2023+
)
2024+
bad_interface = GraphQLInterfaceType(
2025+
"BadInterface", {"field": GraphQLField(GraphQLString)}
2026+
)
2027+
# noinspection PyTypeChecker
2028+
bad_interface.interfaces.append(some_input_obj)
2029+
schema = GraphQLSchema(
2030+
GraphQLObjectType("Query", {"field": GraphQLField(GraphQLString)}),
2031+
types=[bad_interface],
2032+
)
2033+
assert validate_schema(schema) == [
2034+
{
2035+
"message": "Type BadInterface must only implement Interface types,"
2036+
" it cannot implement SomeInputObject.",
2037+
}
2038+
]
19702039

19712040
def rejects_an_interface_missing_an_interface_argument():
19722041
schema = build_schema(

0 commit comments

Comments
 (0)