diff --git a/docs/changelog.rst b/docs/changelog.rst index 74fc7f36..c8fac9eb 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,22 @@ Flask-WTF Changelog =================== +Version 0.14.1 +-------------- + +- Fix bug where the file validators would incorrectly identify an empty file as + valid data. (`#276`_, `#277`_) + + - ``FileField`` is no longer deprecated. The data is checked during + processing and only set if it's a valid file. + - ``has_file`` *is* deprecated; it's now equivalent to ``bool(field.data)``. + - ``FileRequired`` and ``FileAllowed`` work with both the Flask-WTF and + WTForms ``FileField`` classes. + - The ``Optional`` validator now works with ``FileField``. + +.. _#276: https://github.com/lepture/flask-wtf/issues/276 +.. _#277: https://github.com/lepture/flask-wtf/pull/277 + Version 0.14 ------------ diff --git a/flask_wtf/file.py b/flask_wtf/file.py index c196e56c..56099be2 100644 --- a/flask_wtf/file.py +++ b/flask_wtf/file.py @@ -1,34 +1,34 @@ import warnings - from collections import Iterable + from werkzeug.datastructures import FileStorage from wtforms import FileField as _FileField from wtforms.validators import DataRequired, StopValidation -from flask_wtf._compat import FlaskWTFDeprecationWarning +from ._compat import FlaskWTFDeprecationWarning class FileField(_FileField): - """ - Werkzeug-aware subclass of **wtforms.FileField** + """Werkzeug-aware subclass of **wtforms.FileField**""" - .. deprecated:: 0.14 - ``has_file`` was simplified and merged into the validators. - This subclass is no longer needed and will be removed in 1.0. - """ + def process_formdata(self, valuelist): + valuelist = (x for x in valuelist if isinstance(x, FileStorage) and x) + data = next(valuelist, None) - def __new__(cls, *args, **kwargs): - warnings.warn(FlaskWTFDeprecationWarning( - 'The "FileField" subclass is no longer necessary and will be ' - 'removed in 1.0. Use "wtforms.FileField" directly instead.' - ), stacklevel=2) - return super(FileField, cls).__new__(cls, *args, **kwargs) + if data is not None: + self.data = data + else: + self.raw_data = () def has_file(self): - """Return True if self.data is a + """Return ``True`` if ``self.data`` is a :class:`~werkzeug.datastructures.FileStorage` object.""" - return isinstance(self.data, FileStorage) + warnings.warn(FlaskWTFDeprecationWarning( + '"has_file" is deprecated and will be removed in 1.0. The data is ' + 'checked during processing instead.' + )) + return bool(self.data) class FileRequired(DataRequired): @@ -41,7 +41,7 @@ class FileRequired(DataRequired): """ def __call__(self, form, field): - if not isinstance(field.data, FileStorage): + if not (isinstance(field.data, FileStorage) and field.data): if self.message is None: message = field.gettext('This field is required.') else: @@ -68,7 +68,7 @@ def __init__(self, upload_set, message=None): self.message = message def __call__(self, form, field): - if not isinstance(field.data, FileStorage): + if not (isinstance(field.data, FileStorage) and field.data): return filename = field.data.filename.lower()