From 3c68ba2526a43a8f4eb447238399178fcec94ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Larra=C3=ADn?= Date: Fri, 3 May 2019 22:38:31 -0400 Subject: [PATCH] libs.mm_utils: add `validate_no_unexpected_input_fields` --- cl_sii/libs/mm_utils.py | 42 +++++++++++++++++++++++++++++++++++++ tests/test_libs_mm_utils.py | 13 ++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/cl_sii/libs/mm_utils.py b/cl_sii/libs/mm_utils.py index 52d33411..8f319bea 100644 --- a/cl_sii/libs/mm_utils.py +++ b/cl_sii/libs/mm_utils.py @@ -6,6 +6,48 @@ import marshmallow.utils +############################################################################### +# validators +############################################################################### + +def validate_no_unexpected_input_fields( + schema: marshmallow.Schema, + data: dict, + original_data: dict, +) -> None: + """ + Fail validation if there was an unexpected input field. + + Usage:: + + class MySchema(marshmallow.Schema): + + class Meta: + strict = True + + folio = marshmallow.fields.Integer() + + @marshmallow.validates_schema(pass_original=True) + def validate_schema(self, data: dict, original_data: dict) -> None: + validate_no_unexpected_input_fields(self, data, original_data) + + """ + # Original inspiration from + # https://marshmallow.readthedocs.io/en/2.x-line/extending.html#validating-original-input-data + fields_name_or_load_from = { + field.name if field.load_from is None else field.load_from + for field_key, field in schema.fields.items() + } + unexpected_input_fields = set(original_data) - fields_name_or_load_from + if unexpected_input_fields: + raise marshmallow.ValidationError( + "Unexpected input field.", field_names=list(unexpected_input_fields)) + + +############################################################################### +# fields +############################################################################### + class CustomMarshmallowDateField(marshmallow.fields.Field): """ A formatted date string. diff --git a/tests/test_libs_mm_utils.py b/tests/test_libs_mm_utils.py index d1a0c8b3..6957a42c 100644 --- a/tests/test_libs_mm_utils.py +++ b/tests/test_libs_mm_utils.py @@ -1,10 +1,19 @@ import unittest -from cl_sii.libs.mm_utils import CustomMarshmallowDateField # noqa: F401 +from cl_sii.libs.mm_utils import ( # noqa: F401 + CustomMarshmallowDateField, validate_no_unexpected_input_fields, +) class CustomMarshmallowDateFieldTest(unittest.TestCase): def test_x(self) -> None: - # TODO: implement! + # TODO: implement for 'CustomMarshmallowDateField'. + pass + + +class FunctionsTest(unittest.TestCase): + + def test_validate_no_unexpected_input_fields(self): + # TODO: implement for 'validate_no_unexpected_input_fields'. pass