nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: wtforms/wtforms
Pull request #451 (2018-11-08 06:02:51)

IntegerField should check type when process data
Core fields like `IntegerField` will check type on `process_formdata` by reload from base `Field`, but not check on `process_data` in current version. If we pass unsupported type in `data` for `Form`, like a string 'x', the form won't raise any error and will pass the origin string as value for user, it doesn't make sense for this case.

As `BooleanField` did in `process_data`, `IntegerField` should do the same thing, so I add the progress and test case for `IntegerField`.

Maybe other fields in `fields/core.py` like `FloatField` should do type check in `progress_data` also.


Patch:
diff --git a/src/wtforms/fields/core.py b/src/wtforms/fields/core.py
index 0832797..56b7eed 100644
--- a/src/wtforms/fields/core.py
+++ b/src/wtforms/fields/core.py
@@ -666,6 +666,16 @@ class IntegerField(Field):
         else:
             return ""
 
+    def process_data(self, value):
+        if value is not None and value is not unset_value:
+            try:
+                self.data = int(value)
+            except (ValueError, TypeError):
+                self.data = None
+                raise ValueError(self.gettext("Not a valid integer value"))
+        else:
+            self.data = None
+
     def process_formdata(self, valuelist):
         if valuelist:
             try:


Test patch:
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 64ed69f..2458628 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -617,6 +617,13 @@ class IntegerFieldTest(TestCase):
         self.assertEqual(form.b.data, 9)
         self.assertEqual(form.a._value(), "")
         self.assertEqual(form.b._value(), "9")
+        form = self.F(DummyPostData(), data=dict(b="v"))
+        self.assertEqual(form.b.data, None)
+        self.assertEqual(form.a._value(), "")
+        self.assertEqual(form.b._value(), "")
+        self.assertTrue(not form.validate())
+        self.assertEqual(len(form.b.process_errors), 1)
+        self.assertEqual(len(form.b.errors), 1)
 
 
 class DecimalFieldTest(TestCase):
Repository: wtforms/wtforms
Pull request #463 (2019-02-02 00:40:15)

Allow underscores in wtforms.validators.HostnameValidation.
Example patch for #462


Patch:
diff --git a/src/wtforms/validators.py b/src/wtforms/validators.py
index 3bfd7af..58d12b6 100644
--- a/src/wtforms/validators.py
+++ b/src/wtforms/validators.py
@@ -609,7 +609,7 @@ class HostnameValidation(object):
     This is not a validator in and of itself, and as such is not exported.
     """
 
-    hostname_part = re.compile(r"^(xn-|[a-z0-9]+)(-[a-z0-9]+)*$", re.IGNORECASE)
+    hostname_part = re.compile(r"^(xn-|[a-z0-9_]+)(-[a-z0-9_]+)*$", re.IGNORECASE)
     tld_part = re.compile(r"^([a-z]{2,20}|xn--([a-z0-9]+-)*[a-z0-9]+)$", re.IGNORECASE)
 
     def __init__(self, require_tld=True, allow_ip=False):


Test patch:
diff --git a/tests/test_validators.py b/tests/test_validators.py
index ade5dd1..8ef8324 100644
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -380,6 +380,8 @@ def test_equal_to_raises(
     [
         u"http://foobar.dk",
         u"http://foobar.dk/",
+        u"http://foo-bar.dk/",
+        u"http://foo_bar.dk/",
         u"http://foobar.museum/foobar",
         u"http://192.168.0.1/foobar",
         u"http://192.168.0.1:9000/fake",
@@ -412,6 +414,8 @@ def test_valid_url_notld_passes(url_val, dummy_form, dummy_field):
     "url_val",
     [
         u"http://foobar",
+        u"http://-foobar.dk/",
+        u"http://foobar-.dk/",
         u"foobar.dk",
         u"http://127.0.0/asdf",
         u"http://foobar.d",
Repository: wtforms/wtforms
Pull request #598 (2020-04-26 09:08:53)

SelectField will throw ValueError when using list of strings
This may assist with #464 (at least the behavior described by @ftm in that ticket.)

In the validation phase, we use iter_choices now instead of trying to iterate on choices directly.  This will mean that regardless of list of tuples or the shortcut list of strings, we always have 3 values when we iterate the list.  We use the match result from iter_choices instead of doing the comparison again to save the operation.

If you are using the shortcut list of strings and getting `'too many values to unpack (expected 2)'`, this is the fix.

I'm doing the following to work around this right now:
```python
class TimeZoneForm(FlaskForm):
    timezone = SelectField('Timezone', choices=list(zip(listTimezones(), listTimezones())))
```
`list(zip(` is required to prevent `choices` from being an iterator.  `listTimezones()` is a singleton function that returns a cached list of strings.  Without the `list(zip(` or this patch, this will will always fail to validate.


Patch:
diff --git a/src/wtforms/fields/core.py b/src/wtforms/fields/core.py
index 9c4b46a..b8d0e7f 100644
--- a/src/wtforms/fields/core.py
+++ b/src/wtforms/fields/core.py
@@ -538,8 +538,8 @@ class SelectField(SelectFieldBase):
             raise TypeError(self.gettext("Choices cannot be None"))
 
         if self.validate_choice:
-            for v, _ in self.choices:
-                if self.data == v:
+            for _, _, match in self.iter_choices():
+                if match:
                     break
             else:
                 raise ValidationError(self.gettext("Not a valid choice"))


Test patch:
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 5cf7cd5..4f31db2 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -413,6 +413,13 @@ class TestSelectField:
         form = F(a="bar")
         assert '<option value="foo">foo</option>' in form.a()
 
+    def test_choice_shortcut_post(self):
+        F = make_form(a=SelectField(choices=["foo", "bar"]))
+        form = F(DummyPostData(a=["foo"]))
+        assert form.validate()
+        assert form.a.data == "foo"
+        assert len(form.a.errors) == 0
+
     @pytest.mark.parametrize("choices", [[], None])
     def test_empty_choice(self, choices):
         F = make_form(a=SelectField(choices=choices, validate_choice=False))
Repository: wtforms/wtforms
Pull request #639 (2020-07-29 15:27:17)

Backported #598
Backport of #598 for the v2 branch as suggested in https://github.com/lepture/flask-wtf/issues/417.


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index bf6aee6..5e3a0f0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,13 @@
 .. currentmodule:: wtforms
 
 
+Unreleased
+----------
+
+-   Fixed a bug with :class:`~fields.SelectField` choices shortcut at
+    form submission. :pr:`598, 639`
+
+
 Version 2.3.1
 -------------
 
diff --git a/wtforms/fields/core.py b/wtforms/fields/core.py
index 2fec40e..644efdf 100644
--- a/wtforms/fields/core.py
+++ b/wtforms/fields/core.py
@@ -506,8 +506,8 @@ class SelectField(SelectFieldBase):
 
     def pre_validate(self, form):
         if self.validate_choice:
-            for v, _ in self.choices:
-                if self.data == v:
+            for _, _, match in self.iter_choices():
+                if match:
                     break
             else:
                 raise ValueError(self.gettext("Not a valid choice"))


Test patch:
diff --git a/tests/fields.py b/tests/fields.py
index 16f3234..f163095 100644
--- a/tests/fields.py
+++ b/tests/fields.py
@@ -342,6 +342,13 @@ class SelectFieldTest(TestCase):
         form = F(a="bar")
         self.assertEqual(form.a(), """<select id="a" name="a"><option value="foo">foo</option><option selected value="bar">bar</option></select>""")
 
+    def test_choice_shortcut_post(self):
+        F = make_form(a=SelectField(choices=["foo", "bar"]))
+        form = F(DummyPostData(a=["foo"]))
+        assert form.validate()
+        assert form.a.data == "foo"
+        assert len(form.a.errors) == 0
+
     def test_empty_choice(self):
         F = make_form(a=SelectField(choices=[], validate_choice=False))
         form = F(a="bar")
Repository: wtforms/wtforms
Pull request #642 (2020-07-31 21:58:35)

#606 Make SelectMultipleField respect validate_choice
Solution of: https://github.com/wtforms/wtforms/issues/606
Added tests by contrast to https://github.com/wtforms/wtforms/pull/607


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index a9b66c7..d4e9f00 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -40,25 +40,6 @@ Unreleased
     are list of strings. :pr:`598`
 -   Error messages standardization. :issue:`613` :pr:`620` :pr:`626` :pr:`627`
 
-
-Version 2.3.3
--------------
-
-Released 2020-07-30
-
--   This release includes the translation files that were missing in the
-    2.3.2 release. :issue:`641`
-
-
-Version 2.3.2
--------------
-
-Released 2020-07-29
-
--   Fixed a bug with :class:`~fields.SelectField` choices shortcut at
-    form submission. :pr:`598, 639`
-
-
 Version 2.3.1
 -------------
 
diff --git a/src/wtforms/fields/core.py b/src/wtforms/fields/core.py
index 2a96d80..cebc5d8 100644
--- a/src/wtforms/fields/core.py
+++ b/src/wtforms/fields/core.py
@@ -609,7 +609,10 @@ class SelectMultipleField(SelectField):
             )
 
     def pre_validate(self, form):
-        if self.data:
+        if self.choices is None:
+            raise TypeError(self.gettext("Choices cannot be None."))
+
+        if self.validate_choice and self.data:
             values = list(c[0] for c in self.choices)
             for d in self.data:
                 if d not in values:


Test patch:
diff --git a/tests/test_fields.py b/tests/test_fields.py
index fe8afae..eb43e30 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -610,6 +610,29 @@ class TestSelectMultipleField:
         form = F(a="bar")
         assert form.a() == '<select id="a" multiple name="a"></select>'
 
+    def test_validate_choices_when_empty(self):
+        F = make_form(a=SelectMultipleField(choices=[]))
+        form = F(DummyPostData(a=["b"]))
+        assert not form.validate()
+        assert form.a.data == ["b"]
+        assert len(form.a.errors) == 1
+        assert form.a.errors[0] == "'b' is not a valid choice for this field."
+
+    def test_validate_choices_when_none(self):
+        F = make_form(a=SelectMultipleField())
+        form = F(DummyPostData(a="b"))
+        with pytest.raises(TypeError, match="Choices cannot be None"):
+            form.validate()
+
+    def test_dont_validate_choices(self):
+        F = make_form(
+            a=SelectMultipleField(choices=[("a", "Foo")], validate_choice=False)
+        )
+        form = F(DummyPostData(a=["b"]))
+        assert form.validate()
+        assert form.a.data == ["b"]
+        assert len(form.a.errors) == 0
+
 
 class TestRadioField:
     class F(Form):
Repository: wtforms/wtforms
Pull request #675 (2020-12-28 19:00:28)

Always call setattr in FormField.populate
I'm writing a flask website that communicates with an API gateway using json. I wrote a some ORM models using python dataclasses that convert json to objects and vice versa and hide all data manipulation stuff.

The problem is that i could receive a nested json: `{"foo": 42, "nested": {"bar": "baz"}}`. And i map it to something like
```python
@dataclass
class B(BaseModel):
    bar: str = None

@dataclass
class A(BaseModel):
    foo: str = None
    nested: dict = None
    
    @property
    def nested_(self):
          return B.from_dict(self.nested)
    
    @property
    def nested_(self, value):
        self.nested = value.to_dict
```

And form is:
```python
class NestedForm(FlaskForm):
   bar = StringField('Bar')

class MyForm(FlaskForm):
   foo = StringField('Foo')
   nested_ = FormField(NestedForm, 'Nested')
````

In routes I have code like this:
```python
def update_a():
    form = MyForm()
    if form.validate_on_submit:
         obj = A()
         form.populate_obj(obj)
         obj.save()
```
`FormField` will not modify `obj.nested` (it won't write temporary `candidate` object to `obj` attribute).

<!--
Commit checklist:

* add tests that fail without the patch
* ensure all tests pass with ``pytest``
* add documentation to the relevant docstrings or pages
* add ``versionadded`` or ``versionchanged`` directives to relevant docstrings
* add a changelog entry if this patch changes code
-->



Patch:
diff --git a/src/wtforms/fields/core.py b/src/wtforms/fields/core.py
index ce862dc..e480f50 100644
--- a/src/wtforms/fields/core.py
+++ b/src/wtforms/fields/core.py
@@ -1032,9 +1032,9 @@ class FormField(Field):
                     " the provided obj or input data/defaults"
                 )
             candidate = self._obj
-            setattr(obj, name, candidate)
 
         self.form.populate_obj(candidate)
+        setattr(obj, name, candidate)
 
     def __iter__(self):
         return iter(self.form)


Test patch:
diff --git a/tests/fields/test_form.py b/tests/fields/test_form.py
index aa0f73a..9315261 100644
--- a/tests/fields/test_form.py
+++ b/tests/fields/test_form.py
@@ -12,6 +12,16 @@ class AttrDict:
         self.__dict__.update(*args, **kw)
 
 
+class ClassWithProperty(AttrDict):
+    @property
+    def a(self):
+        return AttrDict(self.a_) if getattr(self, "a_", None) else AttrDict()
+
+    @a.setter
+    def a(self, value):
+        self.a_ = vars(value)
+
+
 def make_form(name="F", **fields):
     return type(str(name), (Form,), fields)
 
@@ -106,3 +116,13 @@ def test_populate_missing_obj(F1):
     with pytest.raises(TypeError):
         form.populate_obj(obj)
     form.populate_obj(obj2)
+
+
+def test_populate_property(F1):
+    obj1 = ClassWithProperty(a_={"a": "old_a", "b": "old_b"})
+    form = F1(DummyPostData({"a-a": "new_a", "a-b": "new_b"}))
+    form.populate_obj(obj1)
+    assert obj1.a_ == {"a": "new_a", "b": "new_b"}
+    obj2 = ClassWithProperty()
+    form.populate_obj(obj2)
+    assert obj1.a_ == {"a": "new_a", "b": "new_b"}
Repository: wtforms/wtforms
Pull request #755 (2022-08-28 12:53:49)

ColorField implementation
Describe the issue you are attempting to fix.

Implement support for ColorField

Link to any relevant issues or pull requests.

https://github.com/wtforms/wtforms/issues/725

Describe what this patch does to fix the issue.

Implements it


Patch:
diff --git a/docs/fields.rst b/docs/fields.rst
index 40773cd..c695caa 100644
--- a/docs/fields.rst
+++ b/docs/fields.rst
@@ -380,6 +380,8 @@ Convenience Fields
 
         {{ form.textarea(rows=7, cols=90) }}
 
+.. autoclass:: ColorField(default field arguments)
+
 
 Field Enclosures
 ----------------
diff --git a/src/wtforms/fields/simple.py b/src/wtforms/fields/simple.py
index 8feff4f..910ff96 100644
--- a/src/wtforms/fields/simple.py
+++ b/src/wtforms/fields/simple.py
@@ -14,6 +14,7 @@ __all__ = (
     "TelField",
     "URLField",
     "EmailField",
+    "ColorField",
 )
 
 
@@ -162,3 +163,11 @@ class EmailField(StringField):
     """
 
     widget = widgets.EmailInput()
+
+
+class ColorField(StringField):
+    """
+    Represents an ``<input type="color">``.
+    """
+
+    widget = widgets.ColorInput()


Test patch:
diff --git a/tests/fields/test_color.py b/tests/fields/test_color.py
new file mode 100644
index 0000000..c563e88
--- /dev/null
+++ b/tests/fields/test_color.py
@@ -0,0 +1,16 @@
+from wtforms import widgets
+from wtforms.fields import ColorField
+from wtforms.form import Form
+
+
+class F(Form):
+    a = ColorField(
+        widget=widgets.ColorInput(), default="#ff0000"
+    )
+    b = ColorField(default="#00ff00")
+
+
+def test_color_field():
+    form = F()
+    assert form.a() == """<input id="a" name="a" type="color" value="#ff0000">"""
+    assert form.b() == """<input id="b" name="b" type="color" value="#00ff00">"""
diff --git a/tests/test_widgets.py b/tests/test_widgets.py
index a9b7cd3..93ee535 100644
--- a/tests/test_widgets.py
+++ b/tests/test_widgets.py
@@ -2,6 +2,7 @@ import pytest
 from markupsafe import Markup
 
 from wtforms.widgets.core import CheckboxInput
+from wtforms.widgets.core import ColorInput
 from wtforms.widgets.core import FileInput
 from wtforms.widgets.core import HiddenInput
 from wtforms.widgets.core import html_params
@@ -147,6 +148,14 @@ class TestBasicWidgets:
             == '<input id="id" multiple name="bar" type="file">'
         )
 
+    def test_color_input(self, basic_widget_dummy_field):
+        assert 'type="color"' in ColorInput()(basic_widget_dummy_field)
+        assert 'value="foo"' in ColorInput()(basic_widget_dummy_field)
+        basic_widget_dummy_field.data = "#ff0000"
+        assert 'value="#ff0000"' in ColorInput()(
+            basic_widget_dummy_field
+        )
+
 
 class TestSelect:
     def test_select(self, select_dummy_field):