Repository: wtforms/wtforms (python)

Issue:
Shortcut for SelectMultipleField choices
#526 brought a shortcut for `SelectField` choices, but this does not work with `SelectMultipleField`.

```python
>>> import wtforms
>>> class F(wtforms.Form):
...     single = wtforms.SelectField(choices=["foo", "bar", "baz"])
...     multiple = wtforms.SelectMultipleField(choices=["foo", "bar", "baz"])
>>> F().single()
Markup('<select id="single" name="single"><option value="foo">foo</option><option value="bar">bar</option><option value="baz">baz</option></select>')

>>> F().multiple()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/azmeuk/dev/wtforms/.tox/py38/lib/python3.8/site-packages/wtforms/fields/core.py", line 177, in __call__
    return self.meta.render_field(self, kwargs)
  File "/home/azmeuk/dev/wtforms/.tox/py38/lib/python3.8/site-packages/wtforms/meta.py", line 59, in render_field
    return field.widget(field, **render_kw)
  File "/home/azmeuk/dev/wtforms/.tox/py38/lib/python3.8/site-packages/wtforms/widgets/core.py", line 306, in __call__
    for val, label, selected in field.iter_choices():
  File "/home/azmeuk/dev/wtforms/.tox/py38/lib/python3.8/site-packages/wtforms/fields/core.py", line 559, in iter_choices
    for value, label in self.choices:
ValueError: too many values to unpack (expected 2)

too many values to unpack (expected 2)
```

### Environment

* Python version: 3.8
* wtforms version: 2.3.1


Pull request:
Choices shortcut for SelectMultipleField
Fixes #603
Port of #526 for `SelectMultipleField`.

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index a7ecb68..ad5b983 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -23,6 +23,8 @@ Unreleased
 -   :class:`~fields.SelectField`, :class:`~fields.SelectMultipleField` and
     :class:`~fields.RadioField` *choices* parameter can be a callable.
     :pr:`608`
+-   Choices shortcut for :class:`~fields.core.SelectMultipleField`.
+    :issue:`603` :pr:`605`
 
 
 Version 2.3.1
diff --git a/src/wtforms/fields/core.py b/src/wtforms/fields/core.py
index e5fdb7e..0fefcad 100644
--- a/src/wtforms/fields/core.py
+++ b/src/wtforms/fields/core.py
@@ -557,7 +557,14 @@ class SelectMultipleField(SelectField):
     widget = widgets.Select(multiple=True)
 
     def iter_choices(self):
-        for value, label in self.choices:
+        if not self.choices:
+            choices = []
+        elif isinstance(self.choices[0], (list, tuple)):
+            choices = self.choices
+        else:
+            choices = zip(self.choices, self.choices)
+
+        for value, label in choices:
             selected = self.data is not None and self.coerce(value) in self.data
             yield (value, label, selected)
 


Test patch:
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 965b951..15fb5e1 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -486,6 +486,19 @@ class TestSelectMultipleField:
             '<option selected value="bar">bar</option>',
         ]
 
+    def test_choice_shortcut(self):
+        F = make_form(
+            a=SelectMultipleField(choices=["foo", "bar"], validate_choice=False)
+        )
+        form = F(a="bar")
+        assert '<option value="foo">foo</option>' in form.a()
+
+    @pytest.mark.parametrize("choices", [[], None])
+    def test_empty_choice(self, choices):
+        F = make_form(a=SelectMultipleField(choices=choices, validate_choice=False))
+        form = F(a="bar")
+        assert form.a() == '<select id="a" multiple name="a"></select>'
+
 
 class TestRadioField:
     class F(Form):