mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-11-04 09:57:41 +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 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user