Skip to content

Commit 7b6dae7

Browse files
asodeurjkimbo
authored andcommitted
[863] DateTime, Date, and Time now accept datetime.datetime, datetime.date,… (#864)
* DateTime, Date, and Time now accept datetime.datetime, datetime.date, and datetime.time resp. inputs when used as variables * Added tests and improved resilience against bad DateTime, Date, and Time inputs. * Fixed string type checks too narrow for py2.7 * fixed some of pre-commit's complaints
1 parent c5b2281 commit 7b6dae7

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

graphene/types/datetime.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from aniso8601 import parse_date, parse_datetime, parse_time
66
from graphql.language import ast
7+
from six import string_types
78

89
from .scalars import Scalar
910

@@ -32,7 +33,10 @@ def parse_literal(cls, node):
3233
@staticmethod
3334
def parse_value(value):
3435
try:
35-
return parse_date(value)
36+
if isinstance(value, datetime.date):
37+
return value
38+
elif isinstance(value, string_types):
39+
return parse_date(value)
3640
except ValueError:
3741
return None
3842

@@ -59,7 +63,10 @@ def parse_literal(cls, node):
5963
@staticmethod
6064
def parse_value(value):
6165
try:
62-
return parse_datetime(value)
66+
if isinstance(value, datetime.datetime):
67+
return value
68+
elif isinstance(value, string_types):
69+
return parse_datetime(value)
6370
except ValueError:
6471
return None
6572

@@ -86,6 +93,9 @@ def parse_literal(cls, node):
8693
@classmethod
8794
def parse_value(cls, value):
8895
try:
89-
return parse_time(value)
96+
if isinstance(value, datetime.time):
97+
return value
98+
elif isinstance(value, string_types):
99+
return parse_time(value)
90100
except ValueError:
91101
return None

graphene/types/tests/test_datetime.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytz
44
from graphql import GraphQLError
5+
import pytest
56

67
from ..datetime import Date, DateTime, Time
78
from ..objecttype import ObjectType
@@ -88,6 +89,15 @@ def test_datetime_query_variable():
8889
now = datetime.datetime.now().replace(tzinfo=pytz.utc)
8990
isoformat = now.isoformat()
9091

92+
# test datetime variable provided as Python datetime
93+
result = schema.execute(
94+
"""query Test($date: DateTime){ datetime(in: $date) }""",
95+
variables={"date": now},
96+
)
97+
assert not result.errors
98+
assert result.data == {"datetime": isoformat}
99+
100+
# test datetime variable in string representation
91101
result = schema.execute(
92102
"""query Test($date: DateTime){ datetime(in: $date) }""",
93103
variables={"date": isoformat},
@@ -100,6 +110,14 @@ def test_date_query_variable():
100110
now = datetime.datetime.now().replace(tzinfo=pytz.utc).date()
101111
isoformat = now.isoformat()
102112

113+
# test date variable provided as Python date
114+
result = schema.execute(
115+
"""query Test($date: Date){ date(in: $date) }""", variables={"date": now}
116+
)
117+
assert not result.errors
118+
assert result.data == {"date": isoformat}
119+
120+
# test date variable in string representation
103121
result = schema.execute(
104122
"""query Test($date: Date){ date(in: $date) }""", variables={"date": isoformat}
105123
)
@@ -112,8 +130,57 @@ def test_time_query_variable():
112130
time = datetime.time(now.hour, now.minute, now.second, now.microsecond, now.tzinfo)
113131
isoformat = time.isoformat()
114132

133+
# test time variable provided as Python time
134+
result = schema.execute(
135+
"""query Test($time: Time){ time(at: $time) }""", variables={"time": time}
136+
)
137+
assert not result.errors
138+
assert result.data == {"time": isoformat}
139+
140+
# test time variable in string representation
115141
result = schema.execute(
116142
"""query Test($time: Time){ time(at: $time) }""", variables={"time": isoformat}
117143
)
118144
assert not result.errors
119145
assert result.data == {"time": isoformat}
146+
147+
148+
@pytest.mark.xfail(
149+
reason="creating the error message fails when un-parsable object is not JSON serializable."
150+
)
151+
def test_bad_variables():
152+
def _test_bad_variables(type, input):
153+
result = schema.execute(
154+
"""query Test($input: {}){{ {}(in: $input) }}""".format(type, type.lower()),
155+
variables={"input": input},
156+
)
157+
assert len(result.errors) == 1
158+
# when `input` is not JSON serializable formatting the error message in
159+
# `graphql.utils.is_valid_value` line 79 fails with a TypeError
160+
assert isinstance(result.errors[0], GraphQLError)
161+
print(result.errors[0])
162+
assert result.data is None
163+
164+
not_a_date = dict()
165+
not_a_date_str = "Some string that's not a date"
166+
today = datetime.date.today()
167+
now = datetime.datetime.now().replace(tzinfo=pytz.utc)
168+
time = datetime.time(now.hour, now.minute, now.second, now.microsecond, now.tzinfo)
169+
170+
bad_pairs = [
171+
("DateTime", not_a_date),
172+
("DateTime", not_a_date_str),
173+
("DateTime", today),
174+
("DateTime", time),
175+
("Date", not_a_date),
176+
("Date", not_a_date_str),
177+
("Date", now),
178+
("Date", time),
179+
("Time", not_a_date),
180+
("Time", not_a_date_str),
181+
("Time", now),
182+
("Time", today),
183+
]
184+
185+
for type, input in bad_pairs:
186+
_test_bad_variables(type, input)

0 commit comments

Comments
 (0)