From 0a0ff7a0eca33fe414d61d23cb175d1ee8488dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Fri, 24 Apr 2020 12:35:45 +0200 Subject: [PATCH] Implemented MonthField --- CHANGES.rst | 7 +++++++ docs/fields.rst | 2 ++ src/wtforms/fields/core.py | 11 +++++++++++ src/wtforms/fields/html5.py | 8 ++++++++ tests/test_fields.py | 24 ++++++++++++++++++++++++ 5 files changed, 52 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 5d2fff998..f7eefc420 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,5 +1,12 @@ .. currentmodule:: wtforms +Version 2.x.x +------------- + +Unreleased + +- Implemented :class:`~wtforms.fields.core.MonthField`. :pr:`530` :pr:`593` + Version 3.0.0 ------------- diff --git a/docs/fields.rst b/docs/fields.rst index c7e3da7fa..86d30c767 100644 --- a/docs/fields.rst +++ b/docs/fields.rst @@ -582,6 +582,8 @@ namespace and can be overridden or modified just like any other widget. .. autoclass:: DateField(default field arguments, format='%Y-%m-%d') +.. autoclass:: MonthField(default field arguments, format='%Y-%m') + .. autoclass:: TimeField(default field arguments, format='%H:%M') .. autoclass:: DateTimeLocalField(default field arguments, format='%Y-%m-%d %H:%M:%S') diff --git a/src/wtforms/fields/core.py b/src/wtforms/fields/core.py index 9c4b46a87..a0ce0e062 100644 --- a/src/wtforms/fields/core.py +++ b/src/wtforms/fields/core.py @@ -26,6 +26,7 @@ "SelectMultipleField", "StringField", "TimeField", + "MonthField", ) @@ -889,6 +890,16 @@ def process_formdata(self, valuelist): raise ValueError(self.gettext("Not a valid time value")) +class MonthField(DateField): + """ + Same as DateField, except represents a month, stores a `datetime.date` + with `day = 1`. + """ + + def __init__(self, label=None, validators=None, format="%Y-%m", **kwargs): + super().__init__(label, validators, format, **kwargs) + + class FormField(Field): """ Encapsulate a form as a field in another form. diff --git a/src/wtforms/fields/html5.py b/src/wtforms/fields/html5.py index 177001fd8..26d7efac6 100644 --- a/src/wtforms/fields/html5.py +++ b/src/wtforms/fields/html5.py @@ -73,6 +73,14 @@ class TimeField(core.TimeField): widget = widgets.TimeInput() +class MonthField(core.MonthField): + """ + Represents an ````. + """ + + widget = widgets.MonthInput() + + class DateTimeLocalField(core.DateTimeField): """ Represents an ````. diff --git a/tests/test_fields.py b/tests/test_fields.py index 5cf7cd5f2..f62324edd 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -28,6 +28,7 @@ from wtforms.fields import IntegerField from wtforms.fields import IntegerRangeField from wtforms.fields import Label +from wtforms.fields import MonthField from wtforms.fields import MultipleFileField from wtforms.fields import PasswordField from wtforms.fields import RadioField @@ -756,6 +757,29 @@ def test_failure(self): assert form.a.process_errors[0] == "Not a valid date value" +class TestMonthField: + class F(Form): + a = MonthField() + b = MonthField(format="%m/%Y") + + def test_basic(self): + d = date(2008, 5, 1) + form = self.F(DummyPostData(a=["2008-05"], b=["05/2008"])) + + assert d == form.a.data + assert "2008-05" == form.a._value() + + assert d == form.b.data + + def test_failure(self): + form = self.F(DummyPostData(a=["2008-bb"])) + + assert not form.validate() + assert 1 == len(form.a.process_errors) + assert 1 == len(form.a.errors) + assert "Not a valid date value" == form.a.process_errors[0] + + class TestTimeField: class F(Form): a = TimeField()