Search code examples
pythoncherrypypydantic

CherryPy handle pydantic @validate_arguments


I have a CherryPy api server. I want to validate arguments using pydantic decorator @validate_arguments and if args don't right, function handle that and return

{'error': '*bad_argument* is wrong type', 'result': None}

But when I call the function with wrong args, pydantic raise ValidationError and I get response page:

500 server error
The server encountered an unexpected condition which prevented it from fulfilling the request.
traceback ( type str)
CherryPy version 

What I tried to do:

Add in Root class this:

_cp_config = {'error_page.500': handle_error}

#outside class
def handle_error(status, message, traceback, version):
    print(status)
    print(message)
    print(traceback)
    print(version)

Add this decorator to my api function:

@cherrypy.tools.logit()

#outside class
@cherrypy.tools.register('before_error_response')
def logit(*args, **kwargs):
    print(args)
    print(kwargs)

It didn't work


Solution

  • You need to write your own decorator. Here example of my decision:

    from functools import wraps
    from pydantic import validate_arguments, ValidationError
    
    
    def input_validator(func):
        func = validate_arguments(func)
    
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                func.validate(*args, **kwargs)
            except ValidationError as e:
                # cherrypy.response.status = 400
                return e.errors()
            return func(*args, **kwargs)
    
        return wrapper
    
    
    @input_validator
    def test(a: int):
        return a*2
    
    
    if __name__ == '__main__':
        print(test(2))    # 4
        print(test('2'))  # 4
        print(test('q'))  # [{'loc': ('a',), 'msg': 'value is not a valid integer', 'type': 'type_error.integer'}]