Skip to content

Commit 3ddb4b6

Browse files
committed
NaN values should be checked inside scalar's serialize method
The is_invalid and is_nullish functions now are not needed any more and have been removed from the pyutils package. Replicates graphql/graphql-js@c9850c1
1 parent 1a9a1da commit 3ddb4b6

File tree

12 files changed

+41
-134
lines changed

12 files changed

+41
-134
lines changed

docs/modules/pyutils.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ PyUtils
2020
.. autofunction:: inspect
2121
.. autofunction:: is_finite
2222
.. autofunction:: is_integer
23-
.. autofunction:: is_invalid
24-
.. autofunction:: is_nullish
2523
.. autoclass:: AwaitableOrValue
2624
:members:
2725
.. autofunction:: suggestion_list

src/graphql/execution/execute.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
)
2929
from ..pyutils import (
3030
inspect,
31-
is_invalid,
32-
is_nullish,
3331
AwaitableOrValue,
3432
FrozenList,
3533
Path,
@@ -756,8 +754,8 @@ def complete_value(
756754
)
757755
return completed
758756

759-
# If result value is null-ish (null, Undefined, or NaN) then return null.
760-
if is_nullish(result):
757+
# If result value is null or undefined then return null.
758+
if result is None or result is Undefined:
761759
return None
762760

763761
# If field type is List, complete each item in the list with inner type
@@ -852,7 +850,7 @@ def complete_leaf_value(return_type: GraphQLLeafType, result: Any) -> Any:
852850
serialization is not possible.
853851
"""
854852
serialized_result = return_type.serialize(result)
855-
if is_invalid(serialized_result):
853+
if serialized_result is Undefined:
856854
raise TypeError(
857855
f"Expected a value of type '{inspect(return_type)}'"
858856
f" but received: {inspect(result)}"

src/graphql/pyutils/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
from .is_collection import is_collection
2525
from .is_finite import is_finite
2626
from .is_integer import is_integer
27-
from .is_invalid import is_invalid
28-
from .is_nullish import is_nullish
2927
from .awaitable_or_value import AwaitableOrValue
3028
from .suggestion_list import suggestion_list
3129
from .frozen_error import FrozenError
@@ -52,8 +50,6 @@
5250
"is_collection",
5351
"is_finite",
5452
"is_integer",
55-
"is_invalid",
56-
"is_nullish",
5753
"AwaitableOrValue",
5854
"suggestion_list",
5955
"FrozenError",

src/graphql/pyutils/is_invalid.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/graphql/pyutils/is_nullish.py

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/graphql/utilities/ast_from_value.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from math import isfinite
21
import re
2+
from math import isfinite
33
from typing import Any, Iterable, Mapping, Optional, cast
44

55
from ..language import (
@@ -15,7 +15,7 @@
1515
StringValueNode,
1616
ValueNode,
1717
)
18-
from ..pyutils import FrozenList, inspect, is_nullish, is_invalid
18+
from ..pyutils import inspect, FrozenList, Undefined
1919
from ..type import (
2020
GraphQLID,
2121
GraphQLInputType,
@@ -67,8 +67,8 @@ def ast_from_value(value: Any, type_: GraphQLInputType) -> Optional[ValueNode]:
6767
if value is None:
6868
return NullValueNode()
6969

70-
# Undefined or NaN
71-
if is_invalid(value):
70+
# undefined
71+
if value is Undefined:
7272
return None
7373

7474
# Convert Python list to GraphQL list. If the GraphQLType is a list, but the value
@@ -104,7 +104,7 @@ def ast_from_value(value: Any, type_: GraphQLInputType) -> Optional[ValueNode]:
104104
# Since value is an internally represented value, it must be serialized to an
105105
# externally represented value before converting into an AST.
106106
serialized = type_.serialize(value) # type: ignore
107-
if is_nullish(serialized):
107+
if serialized is None or serialized is Undefined:
108108
return None
109109

110110
# Others serialize based on their corresponding Python scalar types.

src/graphql/utilities/value_from_ast.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
ValueNode,
88
VariableNode,
99
)
10-
from ..pyutils import inspect, is_invalid, Undefined
10+
from ..pyutils import inspect, Undefined
1111
from ..type import (
1212
GraphQLInputObjectType,
1313
GraphQLInputType,
@@ -88,12 +88,12 @@ def value_from_ast(
8888
append_value(None)
8989
else:
9090
item_value = value_from_ast(item_node, item_type, variables)
91-
if is_invalid(item_value):
91+
if item_value is Undefined:
9292
return Undefined
9393
append_value(item_value)
9494
return coerced_values
9595
coerced_value = value_from_ast(value_node, item_type, variables)
96-
if is_invalid(coerced_value):
96+
if coerced_value is Undefined:
9797
return Undefined
9898
return [coerced_value]
9999

@@ -114,7 +114,7 @@ def value_from_ast(
114114
return Undefined
115115
continue
116116
field_value = value_from_ast(field_node.value, field.type, variables)
117-
if is_invalid(field_value):
117+
if field_value is Undefined:
118118
return Undefined
119119
coerced_obj[field.out_name or field_name] = field_value
120120

@@ -143,5 +143,5 @@ def is_missing_variable(
143143
) -> bool:
144144
"""Check if `value_node` is a variable not defined in the `variables` dict."""
145145
return isinstance(value_node, VariableNode) and (
146-
not variables or is_invalid(variables.get(value_node.name.value, Undefined))
146+
not variables or variables.get(value_node.name.value, Undefined) is Undefined
147147
)

src/graphql/validation/rules/values_of_correct_type.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
ValueNode,
1515
print_ast,
1616
)
17-
from ...pyutils import did_you_mean, is_invalid, suggestion_list
17+
from ...pyutils import did_you_mean, suggestion_list, Undefined
1818
from ...type import (
1919
GraphQLScalarType,
2020
get_named_type,
@@ -130,7 +130,7 @@ def is_valid_value_node(self, node: ValueNode) -> None:
130130
type_ = cast(GraphQLScalarType, type_)
131131
try:
132132
parse_result = type_.parse_literal(node)
133-
if is_invalid(parse_result):
133+
if parse_result is Undefined:
134134
self.report_error(
135135
GraphQLError(
136136
f"Expected value of type '{location_type}',"

tests/pyutils/test_is_invalid.py

Lines changed: 0 additions & 30 deletions
This file was deleted.

tests/pyutils/test_is_nullish.py

Lines changed: 0 additions & 48 deletions
This file was deleted.

tests/utilities/test_ast_from_value.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ def converts_boolean_values_to_asts():
4040

4141
assert ast_from_value(Undefined, GraphQLBoolean) is None
4242

43-
assert ast_from_value(nan, GraphQLInt) is None
44-
4543
assert ast_from_value(None, GraphQLBoolean) == NullValueNode()
4644

4745
assert ast_from_value(0, GraphQLBoolean) == BooleanValueNode(value=False)
@@ -71,6 +69,11 @@ def converts_int_values_to_int_asts():
7169
msg = str(exc_info.value)
7270
assert msg == "Int cannot represent non 32-bit signed integer value: 1e+40"
7371

72+
with raises(GraphQLError) as exc_info:
73+
ast_from_value(nan, GraphQLInt)
74+
msg = str(exc_info.value)
75+
assert msg == "Int cannot represent non-integer value: nan"
76+
7477
def converts_float_values_to_float_asts():
7578
# luckily in Python we can discern between float and int
7679
assert ast_from_value(-1, GraphQLFloat) == FloatValueNode(value="-1")
@@ -134,7 +137,10 @@ def converts_using_serialize_from_a_custom_scalar_type():
134137
value="value"
135138
)
136139

137-
assert ast_from_value(nan, pass_through_scalar) is None
140+
with raises(TypeError) as exc_info:
141+
assert ast_from_value(nan, pass_through_scalar)
142+
assert str(exc_info.value) == "Cannot convert value to AST: nan."
143+
138144
with raises(TypeError) as exc_info:
139145
ast_from_value(inf, pass_through_scalar)
140146
assert str(exc_info.value) == "Cannot convert value to AST: inf."

tests/utilities/test_value_from_ast_untyped.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
1-
from math import isnan
1+
from math import nan
22

33
from graphql.language import parse_value, FloatValueNode, IntValueNode
44
from graphql.pyutils import Undefined
55
from graphql.utilities import value_from_ast_untyped
66

77

88
def describe_value_from_ast_untyped():
9+
def _compare_value(value, expected):
10+
if expected is None:
11+
assert value is None
12+
elif expected is Undefined:
13+
assert value is Undefined
14+
elif expected is nan:
15+
assert value is nan
16+
else:
17+
assert value == expected
18+
919
def _test_case(value_text, expected):
1020
value_node = parse_value(value_text)
11-
assert value_from_ast_untyped(value_node) == expected
21+
_compare_value(value_from_ast_untyped(value_node), expected)
1222

1323
def _test_case_with_vars(value_text, variables, expected):
1424
value_node = parse_value(value_text)
15-
assert value_from_ast_untyped(value_node, variables) == expected
25+
_compare_value(value_from_ast_untyped(value_node, variables), expected)
1626

1727
def parses_simple_values():
1828
_test_case("null", None)
@@ -43,10 +53,12 @@ def parses_variables():
4353
"{a:[$testVariable]}", {"testVariable": "foo"}, {"a": ["foo"]}
4454
)
4555
_test_case_with_vars("$testVariable", {"testVariable": None}, None)
56+
_test_case_with_vars("$testVariable", {"testVariable": nan}, nan)
4657
_test_case_with_vars("$testVariable", {}, Undefined)
58+
_test_case_with_vars("$testVariable", None, Undefined)
4759

4860
def parse_invalid_int_as_nan():
49-
assert isnan(value_from_ast_untyped(IntValueNode(value="invalid")))
61+
assert value_from_ast_untyped(IntValueNode(value="invalid")) is nan
5062

5163
def parse_invalid_float_as_nan():
52-
assert isnan(value_from_ast_untyped(FloatValueNode(value="invalid")))
64+
assert value_from_ast_untyped(FloatValueNode(value="invalid")) is nan

0 commit comments

Comments
 (0)