2
Extension to ``htmlfill`` that can parse out schema-defining
5
You can either pass ``SchemaBuilder`` to ``htmlfill.render`` (the
6
``listen`` argument), or call ``parse_schema`` to just parse out a
10
import validators, schema, compound
12
__all__ = ['parse_schema', 'SchemaBuilder']
14
def parse_schema(form):
16
Given an HTML form, parse out the schema defined in it and return
19
listener = htmlfill_schemabuilder.SchemaBuilder()
20
p = htmlfill.FillingParser(
21
defaults={}, listener=listener)
24
return listener.schema()
26
default_validators = dict(
27
[(name.lower(), getattr(validators, name))
28
for name in dir(validators)])
30
def get_messages(cls, message):
34
return dict([(k, message) for k in cls._messages.keys()])
37
value = value.strip().lower()
38
if value in ('true', 't', 'yes', 'y', 'on', '1'):
40
elif value in ('false', 'f', 'no', 'n', 'off', '0'):
43
raise ValueError("Not a boolean value: %r (use 'true'/'false')")
47
Force single items into a list. This is useful for checkboxes.
49
if isinstance(v, list):
51
elif isinstance(v, tuple):
56
class SchemaBuilder(object):
58
def __init__(self, validators=default_validators):
59
self.validators = validators
63
self._schema = schema.Schema()
68
def listen_input(self, parser, tag, attrs):
69
get_attr = parser.get_attr
70
name = get_attr(attrs, 'name')
72
# @@: should warn if you try to validate unnamed fields
74
v = compound.All(validators.Identity())
76
# for checkboxes, we must set if_missing = False
77
if tag.lower() == "input":
78
type_attr = get_attr(attrs, "type").lower().strip()
79
if type_attr == "submit":
80
v.validators.append(validators.Bool())
81
elif type_attr == "checkbox":
82
v.validators.append(validators.Wrapper(to_python = force_list))
83
elif type_attr == "file":
84
add_to_end = validators.FieldStorageUploadConverter()
85
message = get_attr(attrs, 'form:message')
86
required = to_bool(get_attr(attrs, 'form:required', 'false'))
90
messages=get_messages(validators.NotEmpty, message)))
92
v.validators[0].if_missing = False
94
v.validators.append(add_to_end)
95
v_type = get_attr(attrs, 'form:validate', None)
97
pos = v_type.find(':')
99
# @@: should parse args
100
args = (v_type[pos+1:],)
101
v_type = v_type[:pos]
104
v_type = v_type.lower()
105
v_class = self.validators.get(v_type)
107
raise ValueError("Invalid validation type: %r" % v_type)
108
kw_args={'messages': get_messages(v_class, message)}
111
v.validators.append(v_inst)
112
self._schema.add_field(name, v)