from yattag.simpledoc import dict_to_attrs, html_escape, attr_escape, SimpleDoc, DocError
try:
range = xrange # for Python 2/3 compatibility
except NameError:
pass
__all__ = ['Doc']
class SimpleInput(object):
"""
class representing text inputs, password inputs, hidden inputs etc...
"""
def __init__(self, name, tpe, attrs):
self.name = name
self.tpe = tpe
self.attrs = attrs
def render(self, defaults, errors, error_wrapper, stag_end = ' />'):
lst = []
attrs = dict(self.attrs)
error = errors and self.name in errors
if error:
_add_class(attrs, 'error')
lst.append(error_wrapper[0])
lst.append(html_escape(errors[self.name]))
lst.append(error_wrapper[1])
if self.name in defaults:
attrs['value'] = str(defaults[self.name])
attrs['name'] = self.name
lst.append('' % (self.__class__.tag_name, dict_to_attrs(attrs)))
if self.name in defaults:
lst.append(html_escape(str(defaults[self.name])))
else:
lst.append(inner_content)
lst.append('%s>' % self.__class__.tag_name)
return ''.join(lst)
class Textarea(ContainerTag):
pass
class Select(ContainerTag):
tag_name = 'select'
class Option(object):
def __init__(self, name, multiple, value, attrs):
self.name = name
self.multiple = multiple
self.value = value
self.attrs = attrs
def render(self, defaults, errors, inner_content):
selected = False
if self.name in defaults:
if self.multiple:
if self.value in defaults[self.name]:
selected = True
else:
if self.value == defaults[self.name]:
selected = True
lst = ['')
return ''.join(lst)
def _attrs_from_args(required_keys, *args, **kwargs):
# need to do all this to allow specifying attributes as (key, value) pairs
# while maintaining backward compatibility with previous versions
# of yattag, which allowed 'name', 'type', and 'value' attributes
# as positional or as keyword arguments
def raise_exception(arg):
raise ValueError(
"Optional attributes should be passed as (key, value) pairs or as keyword arguments."
"Got %s (type %s)" % (repr(arg), repr(type(arg)))
)
limit = 0
for arg in args:
if isinstance(arg, tuple):
break
else:
limit += 1
if limit > len(required_keys):
raise_exception(args[limit-1])
attrs = dict(zip(required_keys[:limit],args[:limit]))
for arg in args[limit:]:
if isinstance(arg, tuple):
attrs[arg[0]] = arg[1]
else:
raise_exception(arg)
attrs.update(
(('class', value) if key == 'klass' else (key, value))
for key, value in kwargs.items()
)
required_attrs = []
for key in required_keys:
try:
required_attrs.append(attrs.pop(key))
except KeyError:
raise ValueError(
"the %s attribute is missing" % repr(key)
)
return required_attrs + [attrs]
class Doc(SimpleDoc):
"""
The Doc class extends the SimpleDoc class with form rendering capabilities.
Pass default values or errors as dictionnaries to the Doc constructor, and
use the `input`, `textarea`, `select`, `option` methods
to append form elements to the document.
"""
SimpleInput = SimpleInput
CheckboxInput = CheckboxInput
RadioInput = RadioInput
Textarea = Textarea
Select = Select
Option = Option
class TextareaTag(object):
def __init__(self, doc, name, attrs):
# name is the name attribute of the textarea, ex: 'contact_message'
# for