Source code for wheezy.html.ext.lexer

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

import os.path
import re
from warnings import warn

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


[docs]class Preprocessor(object): """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
[docs] def expression(self, text, expr_filter=""): """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, }
[docs] def join_attrs(self, kwargs): """Joins ``kwargs`` as html attributes.""" if kwargs: return " " + " ".join( [ '%s="%s"' % (k, self.expression(kwargs[k])) for k in sorted(kwargs.keys()) ] ) else: return ""
[docs] def error_class(self, name, class_): """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
[docs] def hidden(self, expr, params, expr_filter): """HTML element input hidden.""" name = parse_name(expr) return self.HIDDEN % { "name": name, "value": self.expression(expr, expr_filter), }
[docs] def multiple_hidden(self, expr, params, expr_filter): """Multiple HTML element input of type hidden.""" name = parse_name(expr) return self.MULTIPLE_HIDDEN % { "name": name, "value": expr, "expr_filter": expr_filter, }
[docs] def label(self, expr, params, expr_filter): """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_), }
[docs] def emptybox(self, expr, params, expr_filter): """HTML element input of type text. Value is rendered only if evaluated to boolean True. """ return self.input_helper(expr, params, expr_filter, "empty")
[docs] def textbox(self, expr, params, expr_filter): """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")
[docs] def password(self, expr, params, expr_filter): """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")
[docs] def input_helper(self, expr, params, expr_filter, input_type): """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_), }
[docs] def textarea(self, expr, params, expr_filter): """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_), }
[docs] def checkbox(self, expr, params, expr_filter): """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_), }
[docs] def multiple_checkbox(self, expr, params, expr_filter): """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_), }
[docs] def radio(self, expr, params, expr_filter): """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_), }
[docs] def dropdown(self, expr, params, expr_filter): """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_), }
[docs] def listbox(self, expr, params, expr_filter): """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_), }
[docs] def error(self, expr, params, expr_filter): """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, }
[docs] def info(self, expr, params, expr_filter): """General info message.""" return self.message_helper(expr, params, expr_filter, "info")
[docs] def warning(self, expr, params, expr_filter): """General warning message.""" return self.message_helper(expr, params, expr_filter, "warning")
[docs] def message_helper(self, expr, params, expr_filter, msg_class): """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), }
[docs]class WhitespacePreprocessor(object): """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
[docs]class InlinePreprocessor(object): """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 ""