"""Helpers methods for marshalling.""" from marshmallow.fields import Field class MarshmallowSchemaFactory: """Factory for the Marshmellow schema.""" def __init__(self, schema, many=False) -> None: """Initialize the Factory.""" self.schema = schema(many=many) def dump(self, data) -> dict: """Dump the data. Raises: ValidationError: If the data is invalid. Returns: dict: The dumped data. """ if errors := self.schema.validate(data): raise ValueError(errors) return self.schema.dump(data) def patch_default_validation_status(): """Patch the Marshmallow library.""" from flask import abort from webargs.flaskparser import FlaskParser FlaskParser.DEFAULT_VALIDATION_STATUS = 400 FlaskParser.handle_error = ( lambda self, error, req, schema, *, error_status_code, error_headers: abort( code=error_status_code or self.DEFAULT_VALIDATION_STATUS, description=error.normalized_messages(), ) ) def create_custom_field(base_class, custom_validations=(), error_messages=None): """Build a custom field extending a Marshmallow built-in.""" if not issubclass(base_class, Field): raise ValueError('base_class should be a subclass of marshmallow.Field') class _CustomField(base_class): def __init__(self, *args, **kwargs): """Init method.""" extended_kwargs = dict(**kwargs) extended_kwargs['validate'] = kwargs.get('validate', []) + list( custom_validations ) super().__init__(*args, **extended_kwargs) if error_messages: setattr(_CustomField, 'default_error_messages', error_messages) return _CustomField