Skip to content

Commit 23ca978

Browse files
authored
Merge pull request #1414 from loft-orbital/issue-#1413_fix-invalid-input-type
Providing an invalid value to an input type will now provoke an exception. For example if the input as the type `UUID` and that you provide the value `2` it will now fail.
2 parents 97abb9d + 3bdc67c commit 23ca978

File tree

11 files changed

+428
-25
lines changed

11 files changed

+428
-25
lines changed

docs/types/scalars.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ The following is an example for creating a DateTime scalar:
270270
return dt.isoformat()
271271
272272
@staticmethod
273-
def parse_literal(node):
273+
def parse_literal(node, _variables=None):
274274
if isinstance(node, ast.StringValue):
275275
return datetime.datetime.strptime(
276276
node.value, "%Y-%m-%dT%H:%M:%S.%f")

graphene/tests/issues/test_1419.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
(ID, "1"),
2525
(DateTime, '"2022-02-02T11:11:11"'),
2626
(UUID, '"cbebbc62-758e-4f75-a890-bc73b5017d81"'),
27-
(Decimal, "1.1"),
28-
(JSONString, '{key:"foo",value:"bar"}'),
27+
(Decimal, '"1.1"'),
28+
(JSONString, '"{\\"key\\":\\"foo\\",\\"value\\":\\"bar\\"}"'),
2929
(Base64, '"Q2hlbG8gd29ycmxkCg=="'),
3030
],
3131
)

graphene/types/decimal.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from decimal import Decimal as _Decimal
44

5+
from graphql import Undefined
56
from graphql.language.ast import StringValueNode, IntValueNode
67

78
from .scalars import Scalar
@@ -25,10 +26,11 @@ def serialize(dec):
2526
def parse_literal(cls, node, _variables=None):
2627
if isinstance(node, (StringValueNode, IntValueNode)):
2728
return cls.parse_value(node.value)
29+
return Undefined
2830

2931
@staticmethod
3032
def parse_value(value):
3133
try:
3234
return _Decimal(value)
33-
except ValueError:
34-
return None
35+
except Exception:
36+
return Undefined

graphene/types/json.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import json
44

5+
from graphql import Undefined
56
from graphql.language.ast import StringValueNode
67

78
from .scalars import Scalar
@@ -22,7 +23,11 @@ def serialize(dt):
2223
@staticmethod
2324
def parse_literal(node, _variables=None):
2425
if isinstance(node, StringValueNode):
25-
return json.loads(node.value)
26+
try:
27+
return json.loads(node.value)
28+
except Exception as error:
29+
raise ValueError(f"Badly formed JSONString: {str(error)}")
30+
return Undefined
2631

2732
@staticmethod
2833
def parse_value(value):

graphene/types/scalars.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import Any
22

3+
from graphql import Undefined
34
from graphql.language.ast import (
45
BooleanValueNode,
56
FloatValueNode,
@@ -67,9 +68,10 @@ def coerce_int(value):
6768
try:
6869
num = int(float(value))
6970
except ValueError:
70-
return None
71+
return Undefined
7172
if MIN_INT <= num <= MAX_INT:
7273
return num
74+
return Undefined
7375

7476
serialize = coerce_int
7577
parse_value = coerce_int
@@ -80,6 +82,7 @@ def parse_literal(ast, _variables=None):
8082
num = int(ast.value)
8183
if MIN_INT <= num <= MAX_INT:
8284
return num
85+
return Undefined
8386

8487

8588
class BigInt(Scalar):
@@ -97,7 +100,7 @@ def coerce_int(value):
97100
try:
98101
num = int(float(value))
99102
except ValueError:
100-
return None
103+
return Undefined
101104
return num
102105

103106
serialize = coerce_int
@@ -107,6 +110,7 @@ def coerce_int(value):
107110
def parse_literal(ast, _variables=None):
108111
if isinstance(ast, IntValueNode):
109112
return int(ast.value)
113+
return Undefined
110114

111115

112116
class Float(Scalar):
@@ -122,7 +126,7 @@ def coerce_float(value):
122126
try:
123127
return float(value)
124128
except ValueError:
125-
return None
129+
return Undefined
126130

127131
serialize = coerce_float
128132
parse_value = coerce_float
@@ -131,6 +135,7 @@ def coerce_float(value):
131135
def parse_literal(ast, _variables=None):
132136
if isinstance(ast, (FloatValueNode, IntValueNode)):
133137
return float(ast.value)
138+
return Undefined
134139

135140

136141
class String(Scalar):
@@ -153,6 +158,7 @@ def coerce_string(value):
153158
def parse_literal(ast, _variables=None):
154159
if isinstance(ast, StringValueNode):
155160
return ast.value
161+
return Undefined
156162

157163

158164
class Boolean(Scalar):
@@ -167,6 +173,7 @@ class Boolean(Scalar):
167173
def parse_literal(ast, _variables=None):
168174
if isinstance(ast, BooleanValueNode):
169175
return ast.value
176+
return Undefined
170177

171178

172179
class ID(Scalar):
@@ -185,3 +192,4 @@ class ID(Scalar):
185192
def parse_literal(ast, _variables=None):
186193
if isinstance(ast, (StringValueNode, IntValueNode)):
187194
return ast.value
195+
return Undefined

graphene/types/tests/test_decimal.py

+17
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,25 @@ def test_bad_decimal_query():
3939
not_a_decimal = "Nobody expects the Spanish Inquisition!"
4040

4141
result = schema.execute("""{ decimal(input: "%s") }""" % not_a_decimal)
42+
assert result.errors
4243
assert len(result.errors) == 1
4344
assert result.data is None
45+
assert (
46+
result.errors[0].message
47+
== "Expected value of type 'Decimal', found \"Nobody expects the Spanish Inquisition!\"."
48+
)
49+
50+
result = schema.execute("{ decimal(input: true) }")
51+
assert result.errors
52+
assert len(result.errors) == 1
53+
assert result.data is None
54+
assert result.errors[0].message == "Expected value of type 'Decimal', found true."
55+
56+
result = schema.execute("{ decimal(input: 1.2) }")
57+
assert result.errors
58+
assert len(result.errors) == 1
59+
assert result.data is None
60+
assert result.errors[0].message == "Expected value of type 'Decimal', found 1.2."
4461

4562

4663
def test_decimal_string_query_integer():

graphene/types/tests/test_json.py

+52
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ def test_jsonstring_query():
2121
assert not result.errors
2222
assert result.data == {"json": json_value}
2323

24+
result = schema.execute("""{ json(input: "{}") }""")
25+
assert not result.errors
26+
assert result.data == {"json": "{}"}
27+
2428

2529
def test_jsonstring_query_variable():
2630
json_value = '{"key": "value"}'
@@ -31,3 +35,51 @@ def test_jsonstring_query_variable():
3135
)
3236
assert not result.errors
3337
assert result.data == {"json": json_value}
38+
39+
40+
def test_jsonstring_optional_uuid_input():
41+
"""
42+
Test that we can provide a null value to an optional input
43+
"""
44+
result = schema.execute("{ json(input: null) }")
45+
assert not result.errors
46+
assert result.data == {"json": None}
47+
48+
49+
def test_jsonstring_invalid_query():
50+
"""
51+
Test that if an invalid type is provided we get an error
52+
"""
53+
result = schema.execute("{ json(input: 1) }")
54+
assert result.errors
55+
assert len(result.errors) == 1
56+
assert result.errors[0].message == "Expected value of type 'JSONString', found 1."
57+
58+
result = schema.execute("{ json(input: {}) }")
59+
assert result.errors
60+
assert len(result.errors) == 1
61+
assert result.errors[0].message == "Expected value of type 'JSONString', found {}."
62+
63+
result = schema.execute('{ json(input: "a") }')
64+
assert result.errors
65+
assert len(result.errors) == 1
66+
assert result.errors[0].message == (
67+
"Expected value of type 'JSONString', found \"a\"; "
68+
"Badly formed JSONString: Expecting value: line 1 column 1 (char 0)"
69+
)
70+
71+
result = schema.execute("""{ json(input: "{\\'key\\': 0}") }""")
72+
assert result.errors
73+
assert len(result.errors) == 1
74+
assert (
75+
result.errors[0].message
76+
== "Syntax Error: Invalid character escape sequence: '\\''."
77+
)
78+
79+
result = schema.execute("""{ json(input: "{\\"key\\": 0,}") }""")
80+
assert result.errors
81+
assert len(result.errors) == 1
82+
assert result.errors[0].message == (
83+
'Expected value of type \'JSONString\', found "{\\"key\\": 0,}"; '
84+
"Badly formed JSONString: Expecting property name enclosed in double quotes: line 1 column 11 (char 10)"
85+
)

0 commit comments

Comments
 (0)