[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
This commit is contained in:
Andreas Sodeur 2019-03-31 12:57:34 +02:00 committed by Jonathan Kim
parent c5b2281e22
commit 7b6dae7fa3
2 changed files with 80 additions and 3 deletions

View File

@ -4,6 +4,7 @@ import datetime
from aniso8601 import parse_date, parse_datetime, parse_time
from graphql.language import ast
from six import string_types
from .scalars import Scalar
@ -32,7 +33,10 @@ class Date(Scalar):
@staticmethod
def parse_value(value):
try:
return parse_date(value)
if isinstance(value, datetime.date):
return value
elif isinstance(value, string_types):
return parse_date(value)
except ValueError:
return None
@ -59,7 +63,10 @@ class DateTime(Scalar):
@staticmethod
def parse_value(value):
try:
return parse_datetime(value)
if isinstance(value, datetime.datetime):
return value
elif isinstance(value, string_types):
return parse_datetime(value)
except ValueError:
return None
@ -86,6 +93,9 @@ class Time(Scalar):
@classmethod
def parse_value(cls, value):
try:
return parse_time(value)
if isinstance(value, datetime.time):
return value
elif isinstance(value, string_types):
return parse_time(value)
except ValueError:
return None

View File

@ -2,6 +2,7 @@ import datetime
import pytz
from graphql import GraphQLError
import pytest
from ..datetime import Date, DateTime, Time
from ..objecttype import ObjectType
@ -88,6 +89,15 @@ def test_datetime_query_variable():
now = datetime.datetime.now().replace(tzinfo=pytz.utc)
isoformat = now.isoformat()
# test datetime variable provided as Python datetime
result = schema.execute(
"""query Test($date: DateTime){ datetime(in: $date) }""",
variables={"date": now},
)
assert not result.errors
assert result.data == {"datetime": isoformat}
# test datetime variable in string representation
result = schema.execute(
"""query Test($date: DateTime){ datetime(in: $date) }""",
variables={"date": isoformat},
@ -100,6 +110,14 @@ def test_date_query_variable():
now = datetime.datetime.now().replace(tzinfo=pytz.utc).date()
isoformat = now.isoformat()
# test date variable provided as Python date
result = schema.execute(
"""query Test($date: Date){ date(in: $date) }""", variables={"date": now}
)
assert not result.errors
assert result.data == {"date": isoformat}
# test date variable in string representation
result = schema.execute(
"""query Test($date: Date){ date(in: $date) }""", variables={"date": isoformat}
)
@ -112,8 +130,57 @@ def test_time_query_variable():
time = datetime.time(now.hour, now.minute, now.second, now.microsecond, now.tzinfo)
isoformat = time.isoformat()
# test time variable provided as Python time
result = schema.execute(
"""query Test($time: Time){ time(at: $time) }""", variables={"time": time}
)
assert not result.errors
assert result.data == {"time": isoformat}
# test time variable in string representation
result = schema.execute(
"""query Test($time: Time){ time(at: $time) }""", variables={"time": isoformat}
)
assert not result.errors
assert result.data == {"time": isoformat}
@pytest.mark.xfail(
reason="creating the error message fails when un-parsable object is not JSON serializable."
)
def test_bad_variables():
def _test_bad_variables(type, input):
result = schema.execute(
"""query Test($input: {}){{ {}(in: $input) }}""".format(type, type.lower()),
variables={"input": input},
)
assert len(result.errors) == 1
# when `input` is not JSON serializable formatting the error message in
# `graphql.utils.is_valid_value` line 79 fails with a TypeError
assert isinstance(result.errors[0], GraphQLError)
print(result.errors[0])
assert result.data is None
not_a_date = dict()
not_a_date_str = "Some string that's not a date"
today = datetime.date.today()
now = datetime.datetime.now().replace(tzinfo=pytz.utc)
time = datetime.time(now.hour, now.minute, now.second, now.microsecond, now.tzinfo)
bad_pairs = [
("DateTime", not_a_date),
("DateTime", not_a_date_str),
("DateTime", today),
("DateTime", time),
("Date", not_a_date),
("Date", not_a_date_str),
("Date", now),
("Date", time),
("Time", not_a_date),
("Time", not_a_date_str),
("Time", now),
("Time", today),
]
for type, input in bad_pairs:
_test_bad_variables(type, input)