mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-22 09:36:44 +03:00
[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:
parent
c5b2281e22
commit
7b6dae7fa3
|
@ -4,6 +4,7 @@ import datetime
|
||||||
|
|
||||||
from aniso8601 import parse_date, parse_datetime, parse_time
|
from aniso8601 import parse_date, parse_datetime, parse_time
|
||||||
from graphql.language import ast
|
from graphql.language import ast
|
||||||
|
from six import string_types
|
||||||
|
|
||||||
from .scalars import Scalar
|
from .scalars import Scalar
|
||||||
|
|
||||||
|
@ -32,7 +33,10 @@ class Date(Scalar):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_value(value):
|
def parse_value(value):
|
||||||
try:
|
try:
|
||||||
return parse_date(value)
|
if isinstance(value, datetime.date):
|
||||||
|
return value
|
||||||
|
elif isinstance(value, string_types):
|
||||||
|
return parse_date(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -59,7 +63,10 @@ class DateTime(Scalar):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_value(value):
|
def parse_value(value):
|
||||||
try:
|
try:
|
||||||
return parse_datetime(value)
|
if isinstance(value, datetime.datetime):
|
||||||
|
return value
|
||||||
|
elif isinstance(value, string_types):
|
||||||
|
return parse_datetime(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -86,6 +93,9 @@ class Time(Scalar):
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_value(cls, value):
|
def parse_value(cls, value):
|
||||||
try:
|
try:
|
||||||
return parse_time(value)
|
if isinstance(value, datetime.time):
|
||||||
|
return value
|
||||||
|
elif isinstance(value, string_types):
|
||||||
|
return parse_time(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -2,6 +2,7 @@ import datetime
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
from graphql import GraphQLError
|
from graphql import GraphQLError
|
||||||
|
import pytest
|
||||||
|
|
||||||
from ..datetime import Date, DateTime, Time
|
from ..datetime import Date, DateTime, Time
|
||||||
from ..objecttype import ObjectType
|
from ..objecttype import ObjectType
|
||||||
|
@ -88,6 +89,15 @@ def test_datetime_query_variable():
|
||||||
now = datetime.datetime.now().replace(tzinfo=pytz.utc)
|
now = datetime.datetime.now().replace(tzinfo=pytz.utc)
|
||||||
isoformat = now.isoformat()
|
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(
|
result = schema.execute(
|
||||||
"""query Test($date: DateTime){ datetime(in: $date) }""",
|
"""query Test($date: DateTime){ datetime(in: $date) }""",
|
||||||
variables={"date": isoformat},
|
variables={"date": isoformat},
|
||||||
|
@ -100,6 +110,14 @@ def test_date_query_variable():
|
||||||
now = datetime.datetime.now().replace(tzinfo=pytz.utc).date()
|
now = datetime.datetime.now().replace(tzinfo=pytz.utc).date()
|
||||||
isoformat = now.isoformat()
|
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(
|
result = schema.execute(
|
||||||
"""query Test($date: Date){ date(in: $date) }""", variables={"date": isoformat}
|
"""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)
|
time = datetime.time(now.hour, now.minute, now.second, now.microsecond, now.tzinfo)
|
||||||
isoformat = time.isoformat()
|
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(
|
result = schema.execute(
|
||||||
"""query Test($time: Time){ time(at: $time) }""", variables={"time": isoformat}
|
"""query Test($time: Time){ time(at: $time) }""", variables={"time": isoformat}
|
||||||
)
|
)
|
||||||
assert not result.errors
|
assert not result.errors
|
||||||
assert result.data == {"time": isoformat}
|
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)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user