From 4785db3dbe611f5ef2a3d6037350ba535d46f5e5 Mon Sep 17 00:00:00 2001 From: uncle-lv <88037946+uncle-lv@users.noreply.github.com> Date: Tue, 19 Mar 2024 03:04:26 +0800 Subject: [PATCH] fix(fields.py): fix `File` field bug when get an empty value (#301) * fix(fields.py): fix `File` field bug when get an empty value * perf(fields.py): compatible with `python3.8` * Update changelog --------- Co-authored-by: Steven Loria --- CHANGELOG.rst | 8 ++++++++ src/flask_marshmallow/fields.py | 12 ++++++++++++ tests/test_fields.py | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cd4370d..baf6248 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Changelog ========= +1.2.1 (unreleased) +****************** + +Bug fixes: + +* Fix `File` field when it receives an empty value (:pr:`301`, :issue:`apiflask/apiflask#551`). + Thanks :user:`uncle-lv`. + 1.2.0 (2024-02-05) ****************** diff --git a/src/flask_marshmallow/fields.py b/src/flask_marshmallow/fields.py index e111d1a..83d433f 100755 --- a/src/flask_marshmallow/fields.py +++ b/src/flask_marshmallow/fields.py @@ -10,6 +10,7 @@ import re import typing +from collections.abc import Sequence from flask import current_app, url_for from marshmallow import fields, missing @@ -225,6 +226,17 @@ def __init__(self, *args, **kwargs): default_error_messages = {"invalid": "Not a valid file."} + def deserialize( + self, + value: typing.Any, + attr: typing.Optional[str] = None, + data: typing.Optional[typing.Mapping[str, typing.Any]] = None, + **kwargs, + ): + if isinstance(value, Sequence) and len(value) == 0: + value = missing + return super().deserialize(value, attr, data, **kwargs) + def _deserialize(self, value, attr, data, **kwargs): from werkzeug.datastructures import FileStorage diff --git a/tests/test_fields.py b/tests/test_fields.py index f21d131..c7b9234 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -2,6 +2,7 @@ import pytest from flask import url_for +from marshmallow import missing from marshmallow.exceptions import ValidationError from werkzeug.datastructures import FileStorage from werkzeug.routing import BuildError @@ -150,6 +151,9 @@ def test_file_field(ma, mockauthor): result = field.deserialize(fs, mockauthor) assert result == fs + result = field.deserialize("", mockauthor) + assert result is missing + with pytest.raises(ValidationError, match="Field may not be null."): field.deserialize(None, mockauthor)