/usr/lib/python3/dist-packages/formencode/htmlfill_schemabuilder.py is in python3-formencode 1.3.0-0ubuntu5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | """
Extension to ``htmlfill`` that can parse out schema-defining
statements.
You can either pass ``SchemaBuilder`` to ``htmlfill.render`` (the
``listen`` argument), or call ``parse_schema`` to just parse out a
``Schema`` object.
"""
from . import validators
from . import schema
from . import compound
from . import htmlfill
__all__ = ['parse_schema', 'SchemaBuilder']
def parse_schema(form):
"""
Given an HTML form, parse out the schema defined in it and return
that schema.
"""
listener = SchemaBuilder()
p = htmlfill.FillingParser(
defaults={}, listener=listener)
p.feed(form)
p.close()
return listener.schema()
default_validators = dict(
[(name.lower(), getattr(validators, name))
for name in dir(validators)])
def get_messages(cls, message):
if not message:
return {}
else:
return dict([(k, message) for k in cls._messages])
def to_bool(value):
value = value.strip().lower()
if value in ('true', 't', 'yes', 'y', 'on', '1'):
return True
elif value in ('false', 'f', 'no', 'n', 'off', '0'):
return False
else:
raise ValueError("Not a boolean value: %r (use 'true'/'false')")
def force_list(v):
"""
Force single items into a list. This is useful for checkboxes.
"""
if isinstance(v, list):
return v
elif isinstance(v, tuple):
return list(v)
else:
return [v]
class SchemaBuilder(object):
def __init__(self, validators=default_validators):
self.validators = validators
self._schema = None
def reset(self):
self._schema = schema.Schema()
def schema(self):
return self._schema
def listen_input(self, parser, tag, attrs):
get_attr = parser.get_attr
name = get_attr(attrs, 'name')
if not name:
# @@: should warn if you try to validate unnamed fields
return
v = compound.All(validators.Identity())
add_to_end = None
# for checkboxes, we must set if_missing = False
if tag.lower() == "input":
type_attr = get_attr(attrs, "type").lower().strip()
if type_attr == "submit":
v.validators.append(validators.Bool())
elif type_attr == "checkbox":
v.validators.append(validators.Wrapper(to_python=force_list))
elif type_attr == "file":
add_to_end = validators.FieldStorageUploadConverter()
message = get_attr(attrs, 'form:message')
required = to_bool(get_attr(attrs, 'form:required', 'false'))
if required:
v.validators.append(
validators.NotEmpty(
messages=get_messages(validators.NotEmpty, message)))
else:
v.validators[0].if_missing = False
if add_to_end:
v.validators.append(add_to_end)
v_type = get_attr(attrs, 'form:validate', None)
if v_type:
pos = v_type.find(':')
if pos != -1:
# @@: should parse args
args = (v_type[pos + 1:],)
v_type = v_type[:pos]
else:
args = ()
v_type = v_type.lower()
v_class = self.validators.get(v_type)
if not v_class:
raise ValueError("Invalid validation type: %r" % v_type)
kw_args = {'messages': get_messages(v_class, message)}
v_inst = v_class(
*args, **kw_args)
v.validators.append(v_inst)
self._schema.add_field(name, v)
|