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('' % 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