def validation_exception_handler(request: Request, exc: ValidationError) -> JSONAPIResponse: """Handle a general pydantic validation error The pydantic `ValidationError` usually contains a list of errors, this function extracts them and wraps them in the OPTIMADE specific error resource. Parameters: request: The HTTP request resulting in the exception being raised. exc: The exception being raised. Returns: A JSON HTTP response through [`general_exception()`][optimade.server.exception_handlers.general_exception]. """ status = 500 title = "ValidationError" errors = set() for error in exc.errors(): pointer = "/" + "/".join([str(_) for _ in error["loc"]]) source = ErrorSource(pointer=pointer) code = error["type"] detail = error["msg"] errors.add( OptimadeError(detail=detail, status=status, title=title, source=source, code=code)) return general_exception(request, exc, status_code=status, errors=list(errors))
async def catch_validation_error( self, exception: ValidationError ) -> typing.Union[Response, typing.Tuple]: """ Used to handle request parsing errors """ return {"error": exception.errors()}, 400
def _add_validations_errors(err: ValidationError, errors: list[APIError]) -> list[APIError]: _error = errors[0] _error.code = 'invalid_request_validation' errors = [] for error in err.errors(): errors.append( APIError( **{ **_error.dict(), 'id': Id.generate().value(), 'title': error['msg'], 'detail': dumps({ 'field': list(error['loc'])[1:], 'message': f'{error["msg"]}: {error["type"]}', }).decode('utf-8'), 'source': { 'pointer': error['loc'][0] }, 'meta': { 'error_correlation_id': _error.id }, })) return errors
def _is_failed_due_to_extra_field(exc: pydantic.ValidationError): inner_errors = exc.errors() return (len(inner_errors) == 1 and inner_errors[0]['type'] == 'value_error.extra' and len(inner_errors[0]['loc']) == 1 # Require the extra field to be on the top level )
def get_formatted_error_message( validation_error: pydantic.ValidationError, error_message_prefix: Optional[bool] = True) -> str: """ Return formatted message about validation errors. :param validation_error: error that was raised on validation :type validation_error: pydantic.ValidationError :param error_message_prefix: `Incorrect input!` prefix on the start is included by :type error_message_prefix: Optional[bool] :return: formatted, user readable message :rtype: str """ error_messages = ['💿 Please, correct your input:' ] if error_message_prefix else [] for error in validation_error.errors(): error_location: str = error['loc'][0] # ruined attr name error_message: str = error['msg'] formatted_error_location = ' '.join( error_location.split('_')).capitalize() formatted_error_message = f'{formatted_error_location}: {error_message}' error_messages.append(formatted_error_message) message = '\n'.join(error_messages) return message
def error_handler( cls, json_data: dict, validation_error: ValidationError, id_key: str, items_key: str, ) -> dict: bad_data_ids = [] errors_data = [] if json_data[ "data"]: # нам могут отправить пустой список (вообще не могу, но пусть будет) for error in validation_error.errors(): errors_data.append({ "location": error["loc"], "msg": error["msg"], "type": error["type"], }) element_number = error["loc"][1] element_id = json_data["data"][element_number][id_key] if element_id not in bad_data_ids: bad_data_ids.append(element_id) response_bad_data = { "validation_error": { items_key: [{ "id": element_id } for element_id in bad_data_ids], "errors_data": errors_data, } } return response_bad_data
def simplify_validation_error(e: ValidationError): """Validation errors are long and messy. Return a simplified version Because we do so much overloading, ValidationErrors thrown by parse_raw can cover between 2 and 5+ fields/schemas, explaining how the model wouldn't fit each one individually. The client probably doesn't want to sit through parsing that kind of error, so we work to return a simplified version. TODO: This is a quick and dirty function. Come up with something a bit more comprehensive and 'better'. """ pattern_err_set: Set[_PatternError] = set() other_err_set: Set[_OtherError] = set() for err in e.errors(): em = _ErrorModel(**err) pm = _try_pattern_error_from(em) if pm: pattern_err_set.add(pm) continue other_err_set.add(_other_error_from(em)) pattern_err_strings = list("\t'%s': '%s'" % (p_em.loc, p_em.regex) for p_em in pattern_err_set) other_err_strings = list("\t%s(%s): '%s'" % (o_em.type, o_em.loc, o_em.msg) for o_em in other_err_set) msg = "Message failed validation." if pattern_err_strings: msg += "\n 'Regex' type failures: {\n%s\n}" % ( ",\n".join(pattern_err_strings), ) if other_err_strings: msg += "\n 'Other' type failures: {\n%s\n}" % ( ",\n".join(other_err_strings), ) return msg
def handle_validation_error(error: ValidationError) -> Response: """Convert a ValidationError from parsing JSON input to a error response.""" response = jsonify({ "reason": "validation_failed", "errors": error.errors() }) response.status_code = 400 return cast(Response, response)
def convert_error(err: ValidationError) -> Error: errors = [] for error in err.errors(): if isinstance(error["loc"], tuple): name = ".".join([str(x) for x in error["loc"]]) else: name = str(error["loc"]) errors.append("%s: %s" % (name, error["msg"])) return Error(code=ErrorCode.INVALID_REQUEST, errors=errors)
async def validation_exception_handler(request: Request, exc: ValidationError) -> JSONResponse: return JSONResponse(status_code=HTTP_422_UNPROCESSABLE_ENTITY, content={ "detail": jsonable_encoder(exc.errors()), "body": jsonable_encoder(exc.body) if exc.body else None })
async def validation_exception_handler(request: Request, exc: ValidationError): return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content=jsonable_encoder({ "code": "30012", "detail": exc.errors(), "message": ERR_MSG["30012"], "response_id": request.state.request_tag }), )
async def validation_error_handler(request: Request, e: ValidationError): return JSONResponse( status_code=400, content={ 'message': '数据格式非法', 'name': 'ValidationError', 'code': 4000, 'detail': e.errors(), }, )
def __init__(self, e: ValidationError, message: str = 'Validation Error'): payload = dict({ 'message': 'validation errors', 'errors': [{ 'field': error['loc'][0], 'message': error['msg'] } for error in e.errors()] }) super().__init__(message=message, payload=payload)
def error_list_from_pydantic_error(error: ValidationError) -> list[Error]: res = [] for err in error.errors(): res.append( Error( path=err['loc'], type=err['type'], context=err.get('ctx'), )) return res
def format_errors(error: ValidationError) -> dict: """Structure pydantic validation errors into a dict.""" return { 'msgType': 'Errors', 'errors': [{ 'loc': err['loc'], 'msg': err['msg'], 'type': err['type'], } for err in error.errors()] }
def invalid_params_from_validation_error(exc: ValidationError) -> InvalidParams: errors = [] for err in exc.errors(): if err['loc'][:1] == ('body', ): err['loc'] = err['loc'][1:] else: assert err['loc'] err['loc'] = (f"<{err['loc'][0]}>", ) + err['loc'][1:] errors.append(err) return InvalidParams(data={'errors': errors})
def transform_to_json_api_errors(validation_error: ValidationError) -> dict: def transform_error(error): return { 'detail': error.get('msg'), 'title': error.get('type'), 'source': { 'pointer': '/' + '/'.join(error['loc']), }, } error_response = ErrorResponse( errors=[transform_error(error) for error in validation_error.errors()]) return filter_none(error_response.dict())
def from_validation_error(cls, validation_error: pydantic.ValidationError): errors = validation_error.errors() payload = {} for error in errors: field = error["loc"][0] message = error["msg"] error_type = error["type"] errors = payload.setdefault(field, []) errors.append(FieldError(message=message, type=error_type)) return cls(errors=type_(**payload))
def _raise_formatted_validation_error(err: pydantic.ValidationError): error_list = err.errors() if len(error_list) != 1: return error = error_list[0] loc = error.get("loc") msg = error.get("msg") if not (loc and msg) or not isinstance(loc, tuple): return varname = ".".join((x for x in loc if isinstance(x, str))) raise errors.SnapcraftError(f"error setting {varname}: {msg}")
async def on_validation_error( self, exception: ValidationError, context: CONTEXT ) -> StreamResponse: """ This method is a hook to intercept ValidationError. This hook can be redefined to return a custom HTTP response error. The exception is a pydantic.ValidationError and the context is "body", "headers", "path" or "query string" """ errors = exception.errors() for error in errors: error["in"] = context return json_response(data=errors, status=400)
def validation_exception_handler(request: Request, exc: ValidationError): status = 500 title = "ValidationError" errors = set() for error in exc.errors(): pointer = "/" + "/".join([str(_) for _ in error["loc"]]) source = ErrorSource(pointer=pointer) code = error["type"] detail = error["msg"] errors.add( OptimadeError( detail=detail, status=status, title=title, source=source, code=code ) ) return general_exception(request, exc, status_code=status, errors=list(errors))
def transform_validation_error_to_json_api_errors( status_code: int, exception: ValidationError) -> ErrorResponse: """ Object marshalling for validation errors. format pydantic validation errors to expected json:api response shape. """ def transform_error(error): return Error( status=str(status_code), detail=error.get('msg'), source=ErrorSource(pointer='/' + '/'.join(str(node) for node in error['loc'])), title=error.get('type')) return ErrorResponse( errors=[transform_error(error) for error in exception.errors()])
def error_handler( cls, validation_error: ValidationError, ): errors_data = [] for error in validation_error.errors(): errors_data.append({ "location": error["loc"], "msg": error["msg"], "type": error["type"], }) response_bad_data = { "validation_error": { "errors_data": errors_data, } } return response_bad_data
def get_formatted_error_message( validation_error: pydantic.ValidationError) -> str: """ Return formatted message about validation errors. :param validation_error: error that was raised on validation :type validation_error: pydantic.ValidationError :return: formatted, user readable message :rtype: str """ message = '\n'.join([ f"{error['loc'][0]:<10} - {error['msg']}" for error in validation_error.errors() ]) return message
def validation_exception_handler(request: Request, exc: ValidationError): from optimade.models import Error, ErrorSource status = 500 title = "ValidationError" errors = [] for error in exc.errors(): pointer = "/" + "/".join([str(_) for _ in error["loc"]]) source = ErrorSource(pointer=pointer) code = error["type"] detail = error["msg"] errors.append( Error(detail=detail, status=status, title=title, source=source, code=code)) return general_exception(request, exc, status_code=status, errors=errors)
def format_validation_error(prefix: str, exc: ValidationError) -> str: errors = [ ( prefix + "".join( json.dumps([item]) for item in error["loc"] if item != "__root__" ), error["msg"] if error["msg"][0].isupper() else error["msg"][0].capitalize() + error["msg"][1:], ) for error in exc.errors() ] width = max(len(loc) for loc, _ in errors) + 1 return "\n".join( "{loc:<{width}} => {msg}".format( loc=loc, width=width, msg=msg + "." * (not msg.endswith(".")), ) for loc, msg in errors )
async def validation_exception_handler(request: Request, exc: ValidationError): return JSONResponse(status_code=400, content=exc.errors())
def __init__(self, error: ValidationError): super().__init__( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=jsonable_encoder(error.errors()), )
def unpack_error_details(error: ValidationError) -> str: return error.errors()
def invalid_request_from_validation_error(exc: ValidationError) -> InvalidRequest: return InvalidRequest(data={'errors': exc.errors()})