Repository: wtforms/wtforms (python)

Issue:
Documentation and tests for SelectField choices shortcuts
#526 allows `SelectField` to have choices that are not tuples. However, there is no documentation and [no test](https://coveralls.io/builds/30176772/source?filename=src/wtforms/fields/core.py#L524) about this feature.

Pull request description:
Bugfix, tests and documentation for SelectField choices shortcut
Fixes #572 and [this bug](https://github.com/wtforms/wtforms/pull/526#issuecomment-617675939) introduced with #526 

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 747709a..2564e64 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,5 +1,15 @@
 .. currentmodule:: wtforms
 
+
+Version 2.3.1
+-------------
+
+Unreleased
+
+-   Fixed a bug when :class:`~wtforms.fields.core.SelectField` choices
+    is ``None``. :issue:`572, 585`
+
+
 Version 2.3.0
 -------------
 
diff --git a/docs/fields.rst b/docs/fields.rst
index 4d3fcb7..9d67c80 100644
--- a/docs/fields.rst
+++ b/docs/fields.rst
@@ -268,10 +268,12 @@ refer to a single input from the form.
 
 .. class:: SelectField(default field arguments, choices=[], coerce=unicode, option_widget=None, validate_choice=True)
 
-    Select fields keep a `choices` property which is a sequence of `(value,
-    label)` pairs.  The value portion can be any type in theory, but as form
-    data is sent by the browser as strings, you will need to provide a function
-    which can coerce the string representation back to a comparable object.
+    Select fields take a ``choices`` parameter which is a list of
+    ``(value, label)`` pairs. It can also be a list of only values, in
+    which case the value is used as the label. The value can be any
+    type, but because form data is sent to the browser as strings, you
+    will need to provide a ``coerce`` function that converts a string
+    back to the expected type.
 
     **Select fields with static choice values**::
 
diff --git a/wtforms/fields/core.py b/wtforms/fields/core.py
index b31ca86..2fec40e 100644
--- a/wtforms/fields/core.py
+++ b/wtforms/fields/core.py
@@ -476,7 +476,9 @@ class SelectField(SelectFieldBase):
         self.validate_choice = validate_choice
 
     def iter_choices(self):
-        if isinstance(self.choices[0], (list, tuple)):
+        if not self.choices:
+            choices = []
+        elif isinstance(self.choices[0], (list, tuple)):
             choices = self.choices
         else:
             choices = zip(self.choices, self.choices)


Test patch:
diff --git a/tests/fields.py b/tests/fields.py
index 6587721..16f3234 100644
--- a/tests/fields.py
+++ b/tests/fields.py
@@ -337,6 +337,21 @@ class SelectFieldTest(TestCase):
         self.assertEqual(form.a.data, "b")
         self.assertEqual(len(form.a.errors), 0)
 
+    def test_choice_shortcut(self):
+        F = make_form(a=SelectField(choices=["foo", "bar"], validate_choice=False))
+        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_empty_choice(self):
+        F = make_form(a=SelectField(choices=[], validate_choice=False))
+        form = F(a="bar")
+        self.assertEqual(form.a(), """<select id="a" name="a"></select>""")
+
+    def test_none_choice(self):
+        F = make_form(a=SelectField(choices=None, validate_choice=False))
+        form = F(a="bar")
+        self.assertEqual(form.a(), """<select id="a" name="a"></select>""")
+
 
 class SelectMultipleFieldTest(TestCase):
     class F(Form):