strange validation behavior with `datetime` in sub object in python eve

788 views Asked by At

I am seeing some very strange validation behavior while testing my python eve API.

  • Eve 0.7.4
  • Mongod v3.2.10

Simplified summary: I have a domain endpoint test with a schema containing an object props which has two sub properties time and wetBulb

DOMAIN = {

    # test end point
    'test': {
        'schema': {
            'props': {
                'type': 'dict',
                'schema': { 
                    'time':     {'type': 'datetime'},           # datetime fails to validate
                    'wetBulb':  {'type': ['string', 'float']} # only see issue while key is camel case and contains two type options
                }
            }
        },
        'resource_methods': ['GET', 'POST']
    }
}

DATE_FORMAT = '%Y-%m-%d %H:%M:%S'   # date format seems to be irrelevant

When I define wetBulb as a camel case key ( i.e. wetBulb instead of wet_bulb) AND/OR define it as one of two potential types (i.e. 'type': ['string', 'float']), eve/cerberus fails to interpret my time value as a datetime .

Example:

Running locally with all other defaults, I test this API point using the requests library:

import requests 

post = {
    'properties': {
        'time': '2017-09-05 20:17:40',
        'wetBulb': '21.200000000000003' 
    }
}

r = requests.post('http://127.0.0.1:5000/test', data=json.dumps(post), headers={'content-type': 'application/json'})

# print response
print('Status {0}'.format(r.status_code))
print(r.text)

and I get the response

Status 422
{"_status": "ERR", "_issues": {"properties": {"time": "must be of datetime type"}}, "_error": {"message": "Insertion failure: 1 document(s) contain(s) error(s)", "code": 422}}

If i change my schema definition to have the key wet_bulb AND/OR I change its type to 'type': 'string' it will properly validate:

DOMAIN = {

    # test end point
    'test': {
        'schema': {
            'props': {
                'type': 'dict',
                'schema': { 
                    'time':     {'type': 'datetime'},       
                    'wet_bulb': {'type': 'string'}
                }
            }
        },
        'resource_methods': ['GET', 'POST']
    }
}

then post the object with the updated object:

post = {
    'properties': {
        'time': '2017-09-05 20:17:40',
        'wet_bulb': '21.200000000000003' 
    }
}

r = requests.post('http://127.0.0.1:5000/test', data=json.dumps(post), headers={'content-type': 'application/json'})

# print response
print('Status {0}'.format(r.status_code))
print(r.text)

Status 201
{"_updated": "2017-09-06 12:30:18", "_links": {"self": {"href": "vos/59afea5aa8a548256898cc40", "title": "Vo"}}, "_created": "2017-09-06 12:30:18", "_status": "OK", "_id": "59afea5aa8a548256898cc40", "_etag": "f1b918a2fe688941f84f4d00bc1b400abddab446"}

Question:

Has anyone seen other behavior like this or can help clarify what may be controlling this validation behavior? I have probed around to try and define what causes the validation but haven't been successful.


EDIT

I believe part of the explanation lies within the two notes below type in the cerberus documentation, but I still haven't figured out the cause:

http://docs.python-cerberus.org/en/stable/validation-rules.html#type

I am having the same datetime validation problem in a different schema. In this case I worked around it by either removing the 'type' declaration or setting 'type' to be a string instead of a list (i.e. 'type': 'number' instead of 'type': ['number', 'list']. Unfortunately this schema won't work for the application so I've removed the 'type' declaration for now.

1

There are 1 answers

0
Julienm On

You are not sending an actual Python datetime in your JSON. Cerberus date type is to check that the property value is a Python datetime object. So you want to validate a json string and then convert it to a Python datetime. You have two approaches as described here: https://stackoverflow.com/a/61320357/1417256.