Skip to content

Commit

Permalink
Fixed render for for_, class_ and class__
Browse files Browse the repository at this point in the history
  • Loading branch information
azmeuk committed May 28, 2020
1 parent 12020ba commit 0a18877
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Unreleased
- Choices shortcut for :class:`~fields.core.SelectMultipleField`.
:issue:`603` :pr:`605`
- Forms can have form-level errors. :issue:`55` :pr:`595`
- Fixed a bug related to `for` and `class` html parameter rendering.
:issue:`449` :pr:`596`


Version 2.3.1
Expand Down
5 changes: 5 additions & 0 deletions src/wtforms/meta.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from wtforms import i18n
from wtforms.utils import WebobInputWrapper
from wtforms.widgets.core import clean_key


class DefaultMeta:
Expand Down Expand Up @@ -53,8 +54,12 @@ def render_field(self, field, render_kw):
The default implementation calls ``field.widget(field, **render_kw)``
"""

render_kw = {clean_key(k): v for k, v in render_kw.items()}

other_kw = getattr(field, "render_kw", None)
if other_kw is not None:
other_kw = {clean_key(k): v for k, v in other_kw.items()}
render_kw = dict(other_kw, **render_kw)
return field.widget(field, **render_kw)

Expand Down
12 changes: 8 additions & 4 deletions src/wtforms/widgets/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
)


def clean_key(key):
key = key.rstrip("_")
if key.startswith("data_") or key.startswith("aria_"):
key = key.replace("_", "-")
return key


def html_params(**kwargs):
"""
Generate HTML attribute syntax from inputted keyword arguments.
Expand Down Expand Up @@ -53,10 +60,7 @@ def html_params(**kwargs):
"""
params = []
for k, v in sorted(kwargs.items()):
if k in ("class_", "class__", "for_"):
k = k[:-1]
elif k.startswith("data_") or k.startswith("aria_"):
k = k.replace("_", "-")
k = clean_key(k)
if v is True:
params.append(k)
elif v is False:
Expand Down
31 changes: 31 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,37 @@ def test_render_kw(self):
'type="text" value="hello">'
)

def test_render_special(self):
class F(Form):
s = StringField(render_kw={"class_": "foo"})

assert '<input class="foo" id="s" name="s" type="text" value="">' == F().s()
assert '<input class="bar" id="s" name="s" type="text" value="">' == F().s(
**{"class": "bar"}
)
assert '<input class="bar" id="s" name="s" type="text" value="">' == F().s(
**{"class_": "bar"}
)

class G(Form):
s = StringField(render_kw={"class__": "foo"})

assert '<input class="foo" id="s" name="s" type="text" value="">' == G().s()
assert '<input class="bar" id="s" name="s" type="text" value="">' == G().s(
**{"class__": "bar"}
)

class H(Form):
s = StringField(render_kw={"for_": "foo"})

assert '<input for="foo" id="s" name="s" type="text" value="">' == H().s()
assert '<input for="bar" id="s" name="s" type="text" value="">' == H().s(
**{"for": "bar"}
)
assert '<input for="bar" id="s" name="s" type="text" value="">' == H().s(
**{"for_": "bar"}
)

def test_select_field_copies_choices(self):
class F(Form):
items = SelectField(choices=[])
Expand Down
3 changes: 0 additions & 3 deletions tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
class TestHTMLParams:
def test_basic(self):
assert html_params(foo=9, k="wuuu") == 'foo="9" k="wuuu"'
assert html_params(class_="foo") == 'class="foo"'
assert html_params(class__="foo") == 'class_="foo"'
assert html_params(for_="foo") == 'for="foo"'
assert html_params(readonly=False, foo=9) == 'foo="9"'
assert (
html_params(accept="image/png, image/jpeg", required=True)
Expand Down

0 comments on commit 0a18877

Please sign in to comment.