Skip to content

Commit

Permalink
Merge pull request #152 from jzellman/master
Browse files Browse the repository at this point in the history
Enable web.form doctest and add form.GroupedDropdown
  • Loading branch information
aaronsw committed May 22, 2012
2 parents c542f9b + fe8c9da commit a832cb2
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 23 deletions.
3 changes: 2 additions & 1 deletion test/doctests.py
Expand Up @@ -5,7 +5,8 @@
def suite():
modules = [
"web.application",
"web.db",
"web.db",
"web.form",
"web.http",
"web.net",
"web.session",
Expand Down
77 changes: 55 additions & 22 deletions web/form.py
Expand Up @@ -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
Expand Down Expand Up @@ -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'
Expand All @@ -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):
Expand All @@ -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()
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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'
Expand Down

0 comments on commit a832cb2

Please sign in to comment.