Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Enable web.form doctest and add form.GroupedDropdown #152

Merged
merged 2 commits into from

2 participants

@jzellman

Hi,

I enabled the doctests for web.form. Some were failing due to the tests expecting a unicode type which I fixed. I also added GroupedDropdown which is a subclass of Dropdown that adds support for the tag.

Thanks!

Jeff

@aaronsw aaronsw merged commit a832cb2 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 57 additions and 23 deletions.
  1. +2 −1  test/doctests.py
  2. +55 −22 web/form.py
View
3  test/doctests.py
@@ -5,7 +5,8 @@
def suite():
modules = [
"web.application",
- "web.db",
+ "web.db",
+ "web.form",
"web.http",
"web.net",
"web.session",
View
77 web/form.py
@@ -25,7 +25,7 @@ class Form(object):
>>> f = Form(Textbox("x"))
>>> f.render()
- '<table>\n <tr><th><label for="x">x</label></th><td><input type="text" id="x" name="x"/></td></tr>\n</table>'
+ u'<table>\n <tr><th><label for="x">x</label></th><td><input type="text" id="x" name="x"/></td></tr>\n</table>'
"""
def __init__(self, *inputs, **kw):
self.inputs = inputs
@@ -194,9 +194,9 @@ class Textbox(Input):
"""Textbox input.
>>> Textbox(name='foo', value='bar').render()
- '<input type="text" id="foo" value="bar" name="foo"/>'
+ u'<input type="text" id="foo" value="bar" name="foo"/>'
>>> Textbox(name='foo', value=0).render()
- '<input type="text" id="foo" value="0" name="foo"/>'
+ u'<input type="text" id="foo" value="0" name="foo"/>'
"""
def get_type(self):
return 'text'
@@ -205,7 +205,7 @@ class Password(Input):
"""Password input.
>>> Password(name='password', value='secret').render()
- '<input type="password" id="password" value="secret" name="password"/>'
+ u'<input type="password" id="password" value="secret" name="password"/>'
"""
def get_type(self):
@@ -215,7 +215,7 @@ class Textarea(Input):
"""Textarea input.
>>> Textarea(name='foo', value='bar').render()
- '<textarea id="foo" name="foo">bar</textarea>'
+ u'<textarea id="foo" name="foo">bar</textarea>'
"""
def render(self):
attrs = self.attrs.copy()
@@ -227,9 +227,9 @@ class Dropdown(Input):
r"""Dropdown/select input.
>>> Dropdown(name='foo', args=['a', 'b', 'c'], value='b').render()
- '<select id="foo" name="foo">\n <option value="a">a</option>\n <option selected="selected" value="b">b</option>\n <option value="c">c</option>\n</select>\n'
+ u'<select id="foo" name="foo">\n <option value="a">a</option>\n <option selected="selected" value="b">b</option>\n <option value="c">c</option>\n</select>\n'
>>> Dropdown(name='foo', args=[('a', 'aa'), ('b', 'bb'), ('c', 'cc')], value='b').render()
- '<select id="foo" name="foo">\n <option value="a">aa</option>\n <option selected="selected" value="b">bb</option>\n <option value="c">cc</option>\n</select>\n'
+ u'<select id="foo" name="foo">\n <option value="a">aa</option>\n <option selected="selected" value="b">bb</option>\n <option value="c">cc</option>\n</select>\n'
"""
def __init__(self, name, args, *validators, **attrs):
self.args = args
@@ -242,15 +242,48 @@ def render(self):
x = '<select %s>\n' % attrs
for arg in self.args:
- if isinstance(arg, (tuple, list)):
- value, desc= arg
- else:
- value, desc = arg, arg
+ x += self._render_option(arg)
+
+ x += '</select>\n'
+ return x
+
+ def _render_option(self, arg, indent=' '):
+ if isinstance(arg, (tuple, list)):
+ value, desc= arg
+ else:
+ value, desc = arg, arg
+
+ if self.value == value or (isinstance(self.value, list) and value in self.value):
+ select_p = ' selected="selected"'
+ else:
+ select_p = ''
+ return indent + '<option%s value="%s">%s</option>\n' % (select_p, net.websafe(value), net.websafe(desc))
+
+
+class GroupedDropdown(Dropdown):
+ r"""Grouped Dropdown/select input.
+
+ >>> GroupedDropdown(name='car_type', args=(('Swedish Cars', ('Volvo', 'Saab')), ('German Cars', ('Mercedes', 'Audi'))), value='Audi').render()
+ u'<select id="car_type" name="car_type">\n <optgroup label="Swedish Cars">\n <option value="Volvo">Volvo</option>\n <option value="Saab">Saab</option>\n </optgroup>\n <optgroup label="German Cars">\n <option value="Mercedes">Mercedes</option>\n <option selected="selected" value="Audi">Audi</option>\n </optgroup>\n</select>\n'
+ >>> GroupedDropdown(name='car_type', args=(('Swedish Cars', (('v', 'Volvo'), ('s', 'Saab'))), ('German Cars', (('m', 'Mercedes'), ('a', 'Audi')))), value='a').render()
+ u'<select id="car_type" name="car_type">\n <optgroup label="Swedish Cars">\n <option value="v">Volvo</option>\n <option value="s">Saab</option>\n </optgroup>\n <optgroup label="German Cars">\n <option value="m">Mercedes</option>\n <option selected="selected" value="a">Audi</option>\n </optgroup>\n</select>\n'
- if self.value == value or (isinstance(self.value, list) and value in self.value):
- select_p = ' selected="selected"'
- else: select_p = ''
- x += ' <option%s value="%s">%s</option>\n' % (select_p, net.websafe(value), net.websafe(desc))
+ """
+ def __init__(self, name, args, *validators, **attrs):
+ self.args = args
+ super(Dropdown, self).__init__(name, *validators, **attrs)
+
+ def render(self):
+ attrs = self.attrs.copy()
+ attrs['name'] = self.name
+
+ x = '<select %s>\n' % attrs
+
+ for label, options in self.args:
+ x += ' <optgroup label="%s">\n' % net.websafe(label)
+ for arg in options:
+ x += self._render_option(arg, indent = ' ')
+ x += ' </optgroup>\n'
x += '</select>\n'
return x
@@ -281,14 +314,14 @@ class Checkbox(Input):
"""Checkbox input.
>>> Checkbox('foo', value='bar', checked=True).render()
- '<input checked="checked" type="checkbox" id="foo_bar" value="bar" name="foo"/>'
+ u'<input checked="checked" type="checkbox" id="foo_bar" value="bar" name="foo"/>'
>>> Checkbox('foo', value='bar').render()
- '<input type="checkbox" id="foo_bar" value="bar" name="foo"/>'
+ u'<input type="checkbox" id="foo_bar" value="bar" name="foo"/>'
>>> c = Checkbox('foo', value='bar')
>>> c.validate('on')
True
>>> c.render()
- '<input checked="checked" type="checkbox" id="foo_bar" value="bar" name="foo"/>'
+ u'<input checked="checked" type="checkbox" id="foo_bar" value="bar" name="foo"/>'
"""
def __init__(self, name, *validators, **attrs):
self.checked = attrs.pop('checked', False)
@@ -318,9 +351,9 @@ class Button(Input):
"""HTML Button.
>>> Button("save").render()
- '<button id="save" name="save">save</button>'
+ u'<button id="save" name="save">save</button>'
>>> Button("action", value="save", html="<b>Save Changes</b>").render()
- '<button id="action" value="save" name="action"><b>Save Changes</b></button>'
+ u'<button id="action" value="save" name="action"><b>Save Changes</b></button>'
"""
def __init__(self, name, *validators, **attrs):
super(Button, self).__init__(name, *validators, **attrs)
@@ -338,7 +371,7 @@ class Hidden(Input):
"""Hidden Input.
>>> Hidden(name='foo', value='bar').render()
- '<input type="hidden" id="foo" value="bar" name="foo"/>'
+ u'<input type="hidden" id="foo" value="bar" name="foo"/>'
"""
def is_hidden(self):
return True
@@ -350,7 +383,7 @@ class File(Input):
"""File input.
>>> File(name='f').render()
- '<input type="file" id="f" name="f"/>'
+ u'<input type="file" id="f" name="f"/>'
"""
def get_type(self):
return 'file'
Something went wrong with that request. Please try again.