From 7e1086e5a371d818a02237a3c5b4c5ee06efa3a4 Mon Sep 17 00:00:00 2001 From: E002411 Date: Mon, 25 Feb 2019 18:45:06 -0500 Subject: [PATCH 1/2] capture_invalid_data: (0) Added ``EnforceValidationFieldMixin.capture_failed_field`` to capture the optional fields that failed. --- AUTHORS.rst | 1 + HISTORY.rst | 5 +++++ drf_braces/__init__.py | 2 +- .../enforce_validation_serializer.py | 16 ++++++++++++++-- .../test_enforce_validation_serializer.py | 19 +++++++++++++++++++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index cd11169..00a80cd 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -14,3 +14,4 @@ Contributors * Agam Dua - https://github.com/agamdua * Marc Marta - https://github.com/mmarta * ClairePhila - https://github.com/ClairePhila +* Ndubisi Onuora - https://github.com/NdubisiOnuora diff --git a/HISTORY.rst b/HISTORY.rst index fcdd333..0d5ea1d 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,6 +3,11 @@ History ------- +0.3.4 (2019-02-25) +~~~~~~~~~~~~~~~~~~ + +* Added ``EnforceValidationFieldMixin.capture_failed_field`` to capture the optional fields that failed. + 0.3.3 (2019-02-21) ~~~~~~~~~~~~~~~~~~ diff --git a/drf_braces/__init__.py b/drf_braces/__init__.py index 7762f3f..5bab113 100755 --- a/drf_braces/__init__.py +++ b/drf_braces/__init__.py @@ -4,4 +4,4 @@ __author__ = 'Miroslav Shubernetskiy' __email__ = 'miroslav@miki725.com' -__version__ = '0.3.3' +__version__ = '0.3.4' diff --git a/drf_braces/serializers/enforce_validation_serializer.py b/drf_braces/serializers/enforce_validation_serializer.py index bf2ead6..f3c36ea 100644 --- a/drf_braces/serializers/enforce_validation_serializer.py +++ b/drf_braces/serializers/enforce_validation_serializer.py @@ -31,13 +31,25 @@ def run_validation(self, data=empty): if must_validate_fields is None or field_name in must_validate_fields: raise else: + self.capture_failed_field(field_name, data) raise fields.SkipField( 'This field "{}" is being skipped as per enforce validation logic.' ''.format(field_name) ) + def capture_failed_field(self, field_name, field_data): + """Hook for capturing invalid fields. This is used to track which fields have been skipped. + Args: + field_name (str): the name of the field whose data failed to validate + field_data (object): the data of the field that failed validation -def _create_enforce_validation_serializer(serializer, strict_mode_by_default=True): + Returns: + Not meant to return anything. + """ + pass + + +def _create_enforce_validation_serializer(serializer, strict_mode_by_default=True, validation_serializer_mixin_class=EnforceValidationFieldMixin): """ Recursively creates a copy of a given serializer which enforces ``must_validate_fields``. @@ -129,7 +141,7 @@ def _create_enforce_validation_serializer(serializer, strict_mode_by_default=Tru elif isinstance(field, serializers.Field): replacement = add_base_class_to_instance( field, - EnforceValidationFieldMixin, + validation_serializer_mixin_class, new_name=get_class_name_with_new_suffix( field.__class__, 'Field', diff --git a/drf_braces/tests/serializers/test_enforce_validation_serializer.py b/drf_braces/tests/serializers/test_enforce_validation_serializer.py index 415d093..ff5ec46 100644 --- a/drf_braces/tests/serializers/test_enforce_validation_serializer.py +++ b/drf_braces/tests/serializers/test_enforce_validation_serializer.py @@ -31,10 +31,19 @@ class TestManySerializer(serializers.Serializer): many = TestSerializer(many=True) +class CaptureFailedFieldValidationFieldMixin(EnforceValidationFieldMixin): + + def capture_failed_field(self, field_name, field_data): + self._failed_validation = {field_name: field_data} + + class TestEnforceValidationFieldMixin(unittest.TestCase): class Field(EnforceValidationFieldMixin, fields.IntegerField): pass + class CaptureFailedField(CaptureFailedFieldValidationFieldMixin, fields.TimeField): + pass + def test_run_validation_must_validate(self): field = self.Field() field.field_name = 'field' @@ -66,6 +75,16 @@ def test_run_validation_must_validate_ignore(self): with self.assertRaises(serializers.SkipField): field.run_validation('hello') + def test_run_validation_must_validate_ignore_capture(self): + field = self.CaptureFailedField() + field.field_name = 'field' + field.parent = mock.MagicMock(must_validate_fields=['field']) + + with self.assertRaises(serializers.SkipField): + field.run_validation('Bad Time') + + self.assertDictEqual({'field': 'Bad Time'}, field._failed_validation) + class TestUtils(unittest.TestCase): def test_add_base_class_to_instance(self): From 3dcb0ffa4b407454887c4c52f6894313fe96714b Mon Sep 17 00:00:00 2001 From: E002411 Date: Mon, 25 Feb 2019 18:52:00 -0500 Subject: [PATCH 2/2] capture_invalid_data: (0) Fixed dumb mistake in test. --- .../tests/serializers/test_enforce_validation_serializer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drf_braces/tests/serializers/test_enforce_validation_serializer.py b/drf_braces/tests/serializers/test_enforce_validation_serializer.py index ff5ec46..780530d 100644 --- a/drf_braces/tests/serializers/test_enforce_validation_serializer.py +++ b/drf_braces/tests/serializers/test_enforce_validation_serializer.py @@ -78,7 +78,7 @@ def test_run_validation_must_validate_ignore(self): def test_run_validation_must_validate_ignore_capture(self): field = self.CaptureFailedField() field.field_name = 'field' - field.parent = mock.MagicMock(must_validate_fields=['field']) + field.parent = mock.MagicMock(must_validate_fields=['']) with self.assertRaises(serializers.SkipField): field.run_validation('Bad Time')