Source code for wheezy.html.ext.lexer

""" ``lexer`` module
"""

import re
import os.path

from warnings import warn

from wheezy.html.ext.parser import parse_known_function
from wheezy.html.ext.parser import parse_name
from wheezy.html.ext.parser import parse_params
from wheezy.html.ext.parser import parse_str_or_int
from wheezy.html.utils import html_id


class Preprocessor(object):
[docs] """ Generic widget preprocessor. """ CHECKBOX = None ERROR = None ERROR_CLASS0 = None ERROR_CLASS1 = None EXPRESSION = None HIDDEN = '<input type="hidden" name="%(name)s" value="%(value)s" />' INPUT = None LABEL = '<label for="%(id)s"%(attrs)s%(class)s>%(value)s</label>' MESSAGE = None MULTIPLE_CHECKBOX = None MULTIPLE_HIDDEN = None PREPEND = None RADIO = None SELECT = None TEXTAREA = '<textarea id="%(id)s" name="%(name)s"%(attrs)s%(class)s>' \ '%(value)s</textarea>' # region: preprocessing def __init__(self, widgets_pattern): self.widgets = { 'checkbox': self.checkbox, 'dropdown': self.dropdown, 'emptybox': self.emptybox, 'error': self.error, 'hidden': self.hidden, 'info': self.info, 'label': self.label, 'listbox': self.listbox, 'multiple_checkbox': self.multiple_checkbox, 'multiple_hidden': self.multiple_hidden, 'multiple_select': self.listbox, 'password': self.password, 'radio': self.radio, 'select': self.dropdown, 'textarea': self.textarea, 'textbox': self.textbox, 'warning': self.warning, } assert '%(widgets)s' in widgets_pattern self.RE_WIDGETS = re.compile(widgets_pattern % { 'widgets': '|'.join(self.widgets.keys())}) def __call__(self, text, **kwargs): """ Preprocess input text. """ result = [] start = 0 for m in self.RE_WIDGETS.finditer(text): result.append(text[start:m.start()]) start = m.end() args = m.groupdict() widget = self.widgets[args.pop('widget')] result.append(widget(**args)) if start > 0 and self.PREPEND: result.insert(0, self.PREPEND) result.append(text[start:]) return ''.join(result) # region: helpers def expression(self, text, expr_filter=''):
[docs] """ Interpretate ``text`` as string expression or python expression. """ value = parse_str_or_int(text) return value or self.EXPRESSION % { 'expr': text, 'expr_filter': expr_filter} def join_attrs(self, kwargs):
[docs] """ Joins ``kwargs`` as html attributes. """ if kwargs: return ' ' + ' '.join([ '%s="%s"' % (k, self.expression(kwargs[k])) for k in sorted(kwargs.keys())]) else: return '' def error_class(self, name, class_):
[docs] """ Checks for error and add css class error. """ if class_: return self.ERROR_CLASS1 % { 'name': name, 'class': self.expression(class_)} else: return self.ERROR_CLASS0 % { 'name': name} # region: widgets def hidden(self, expr, params, expr_filter):
[docs] """ HTML element input hidden. """ name = parse_name(expr) return self.HIDDEN % { 'name': name, 'value': self.expression(expr, expr_filter)} def multiple_hidden(self, expr, params, expr_filter):
[docs] """ Multiple HTML element input of type hidden. """ name = parse_name(expr) return self.MULTIPLE_HIDDEN % { 'name': name, 'value': expr, 'expr_filter': expr_filter} def label(self, expr, params, expr_filter):
[docs] """ HTML element label. """ name = parse_name(expr) args, kwargs = parse_params(params) class_ = kwargs.pop('class', None) return self.LABEL % { 'id': html_id(name), 'name': name, 'value': self.expression(args[0], expr_filter), 'attrs': self.join_attrs(kwargs), 'class': self.error_class(name, class_)} def emptybox(self, expr, params, expr_filter):
[docs] """ HTML element input of type text. Value is rendered only if evaluated to boolean True. """ return self.input_helper(expr, params, expr_filter, 'empty') def textbox(self, expr, params, expr_filter):
[docs] """ HTML element input of type text. Value is rendered only if it is not None or ''. """ return self.input_helper(expr, params, expr_filter, 'text') def password(self, expr, params, expr_filter):
[docs] """ HTML element input of type password. Value is rendered only if it is not None or ''. """ return self.input_helper(expr, params, expr_filter, 'password') def input_helper(self, expr, params, expr_filter, input_type):
[docs] """ HTML element input of type input_type. """ name = parse_name(expr) args, kwargs = parse_params(params) class_ = kwargs.pop('class', None) if input_type == 'empty': input_type = 'text' condition = '' else: condition = " not in (None, '')" value, func = parse_known_function(expr) return self.INPUT % { 'id': html_id(name), 'name': name, 'type': input_type, 'value': value, 'condition': condition, 'func': func, 'expr_filter': expr_filter, 'attrs': self.join_attrs(kwargs), 'class': self.error_class(name, class_)} def textarea(self, expr, params, expr_filter):
[docs] """ HTML element textarea. """ name = parse_name(expr) args, kwargs = parse_params(params) kwargs.setdefault('rows', '"9"') kwargs.setdefault('cols', '"40"') class_ = kwargs.pop('class', None) return self.TEXTAREA % { 'id': html_id(name), 'name': name, 'value': self.expression(expr, expr_filter), 'attrs': self.join_attrs(kwargs), 'class': self.error_class(name, class_)} def checkbox(self, expr, params, expr_filter):
[docs] """ HTML element input of type checkbox. """ name = parse_name(expr) args, kwargs = parse_params(params) class_ = kwargs.pop('class', None) return self.CHECKBOX % { 'id': html_id(name), 'name': name, 'value': expr, 'attrs': self.join_attrs(kwargs), 'class': self.error_class(name, class_)} def multiple_checkbox(self, expr, params, expr_filter):
[docs] """ Multiple HTML element input of type checkbox. """ name = parse_name(expr) args, kwargs = parse_params(params) choices = kwargs.pop('choices') class_ = kwargs.pop('class', None) return self.MULTIPLE_CHECKBOX % { 'id': html_id(name), 'name': name, 'choices': choices, 'value': expr, 'expr_filter': expr_filter, 'attrs': self.join_attrs(kwargs), 'class': self.error_class(name, class_)} def radio(self, expr, params, expr_filter):
[docs] """ A group of HTML input elements of type radio. """ name = parse_name(expr) args, kwargs = parse_params(params) class_ = kwargs.pop('class', None) choices = kwargs.pop('choices') return self.RADIO % { 'id': html_id(name), 'name': name, 'choices': choices, 'value': expr, 'expr_filter': expr_filter, 'attrs': self.join_attrs(kwargs), 'class': self.error_class(name, class_)} def dropdown(self, expr, params, expr_filter):
[docs] """ HTML element select. """ name = parse_name(expr) args, kwargs = parse_params(params) class_ = kwargs.pop('class', None) choices = kwargs.pop('choices') return self.SELECT % { 'id': html_id(name), 'name': name, 'choices': choices, 'value': expr, 'expr_filter': expr_filter, 'attrs': self.join_attrs(kwargs), 'class': self.error_class(name, class_)} def listbox(self, expr, params, expr_filter):
[docs] """ HTML element select of type multiple. """ name = parse_name(expr) args, kwargs = parse_params(params) class_ = kwargs.pop('class', None) choices = kwargs.pop('choices') return self.MULTIPLE_SELECT % { 'id': html_id(name), 'name': name, 'choices': choices, 'value': expr, 'expr_filter': expr_filter, 'attrs': self.join_attrs(kwargs), 'class': self.error_class(name, class_)} def error(self, expr, params, expr_filter):
[docs] """ General error message or field error. """ name = parse_name(expr) args, kwargs = parse_params(params) class_ = kwargs.pop('class', '') if class_: class_ = ' ' + self.expression(class_) if '.' not in expr: name = '__ERROR__' kwargs['class'] = '"error-message' + class_ + '"' else: kwargs['class'] = '"error' + class_ + '"' return self.ERROR % { 'name': name, 'attrs': self.join_attrs(kwargs), 'expr_filter': expr_filter} def info(self, expr, params, expr_filter):
[docs] """ General info message. """ return self.message_helper(expr, params, expr_filter, 'info') def warning(self, expr, params, expr_filter):
[docs] """ General warning message. """ return self.message_helper(expr, params, expr_filter, 'warning') def message_helper(self, expr, params, expr_filter, msg_class):
[docs] """ General info message. """ args, kwargs = parse_params(params) class_ = kwargs.pop('class', '') if class_: class_ = ' ' + self.expression(class_) if '.' not in expr: class_ = '-message' + class_ kwargs['class'] = '"' + msg_class + class_ + '"' return self.MESSAGE % { 'value': expr, 'info': self.expression(expr, expr_filter), 'attrs': self.join_attrs(kwargs)} class WhitespacePreprocessor(object):
[docs] """ Whitespace preprocessor. """ def __init__(self, rules, ignore_rules=None): self.rules = rules self.ignore_rules = ignore_rules def __call__(self, text, **kwargs): if self.ignore_rules: for ignore_rule in self.ignore_rules: start = 0 result = [] for m in ignore_rule.finditer(text): result.append(self.cleanup(text[start:m.start()])) result.append(m.group()) start = m.end() else: result.append(self.cleanup(text[start:])) text = ''.join(result) return text else: return self.cleanup(text) def cleanup(self, text): for r, s in self.rules: text = r.sub(s, text) return text class InlinePreprocessor(object):
[docs] """ Inline preprocessor """ def __init__(self, pattern, directories, strategy=None): self.pattern = pattern self.directories = directories if strategy: self.strategy = strategy def __call__(self, text, **kwargs): result = [] start = 0 for m in self.pattern.finditer(text): result.append(text[start:m.start()]) start = m.end() path = m.group('path') result.append(self(self.strategy(path))) if start: result.append(text[start:]) return ''.join(result) else: return text def strategy(self, path): path = path.lstrip('/') for d in self.directories: abspath = os.path.abspath(os.path.join(d, path)) if os.path.exists(abspath) and os.path.isfile(abspath): f = open(abspath, 'r') try: return f.read() finally: f.close() warn('InlinePreprocessor: "%s" not found.' % path) return ''