Example #1
0
class ExtensionExpr(ContextExprMixin, StringExpr):
    """tales: TALES expression

    This expression can be used to call a custom named adapter providing ITALESExtension interface.
    """

    transform = Symbol(render_extension)
Example #2
0
def transform_attribute(node):
    info = "\n".join(ASTCodeGenerator(node).lines)
    return template("lookup(object, name, info, __filename)",
                    lookup=Symbol(lookup_attr),
                    object=node.value,
                    name=ast.Str(s=node.attr),
                    info=ast.Str(s=info),
                    mode="eval")
Example #3
0
 def compiler(target, engine):
     value = template(
         "EXECUTE(NAME,econtext,rcontext)",
         EXECUTE=Symbol(execute),
         NAME=ast.Str(s=command),
         mode="eval",
     )
     return [ast.Assign(targets=[target], value=value)]
Example #4
0
 def _leave_assignment(self, names):
     for name in names:
         for stmt in template(
                 "deleteitem(econtext, KEY, BACKUP, __marker)",
                 deleteitem=Symbol(deleteitem),
                 BACKUP=identifier("backup_%s" % name, id(names)),
                 KEY=ast.Str(s=native_string(name)),
         ):
             yield stmt
Example #5
0
class TileExpression(StringExpr):
    render_tile = Static(
        template("cls()", cls=Symbol(TileProviderTraverser), mode='eval'))

    def __call__(self, target, engine):
        assignment = super(TileExpression, self).__call__(target, engine)
        return assignment + template(
            'target = render_tile(context, request, target.strip())',
            target=target,
            render_tile=self.render_tile)
Example #6
0
def emit_convert_and_escape(target,
                            quote=None,
                            quote_entity=None,
                            str=unicode_string,
                            long=long,
                            type=type,
                            encoded=byte_string,
                            default_marker=None,
                            default=None,
                            convert=Symbol(convert_str)):  # pragma: no cover
    if target is not None:
        if target is default_marker:
            target = default
        else:
            target = convert(target)
Example #7
0
    def __call__(self, node):
        name = node.id

        # Don't rewrite names that begin with an underscore; they are
        # internal and can be assumed to be locally defined. This
        # policy really should be part of the template program, not
        # defined here in the compiler.

        if isinstance(node.ctx, ast.Load):
            if self.validate_model and name.startswith("__model_"):
                name = node.id[8:]
                if not name in self.defined_models:
                    err = ParseError(
                        "Cannot find model",
                        Token(name,
                              pos=node.lineno,
                              source=self.source,
                              filename=self.filename))
                    raise err
                node.id = self.defined_models[name]
                return node

        if name.startswith('__') or name in self.internals:
            return node

        if name == "el":
            return Builtin("None")

        if isinstance(node.ctx, ast.Store):
            return store_econtext(name)

        aliased = self.aliases.get(name)
        if aliased is not None:
            return load(aliased)

        # If the name is a Python global, first try acquiring it from
        # the dynamic context, then fall back to the global.
        if name in self.builtins:
            return template(
                "getitem(econtext, key, name)",
                getitem=Symbol(getitem),
                mode="eval",
                key=ast.Str(s=name),
                name=load(name),
            )

        # Otherwise, simply acquire it from the dynamic context.
        return load_econtext(name)
Example #8
0
    def visit_BindRepeat(self, node):
        body = []

        body.append(Comment("start model-repeat-binding"))

        new_stack = identifier("stack", id(node))
        old_stack = self._current_stack
        body += template("CAPTURED_STACK = STACK.capture_for_repeat()",
                         CAPTURED_STACK=new_stack,
                         STACK=old_stack)

        new_stack = identifier("stack", id(node))

        self._current_stack = new_stack
        self._aliases.append(self._aliases[-1].copy())

        model_name = identifier("model_%s" % node.alias, id(node))
        self._defined_models[node.alias] = model_name

        inner_on_add = []
        inner_on_add += self.visit(node.node)
        inner_on_add += template("return STACK.repeat_el",
                                 STACK=self._current_stack)

        on_add_name = identifier("on_add", id(node))
        on_add_func = [
            ast.FunctionDef(name=on_add_name,
                            args=ast.arguments(
                                args=[load(model_name)],
                                defaults=(),
                            ),
                            body=inner_on_add)
        ]
        body += on_add_func

        collection = "__collection"
        initializer = self._engine(node.expression, store(collection))
        initializer += template("BIND_REPEAT(COLLECTION, ON_ADD)",
                                BIND_REPEAT=Symbol(bind_repeat),
                                COLLECTION=load(collection),
                                ON_ADD=on_add_name)
        body += initializer

        self._aliases.pop()
        self._current_stack = old_stack

        body.append(Comment("end model-repeat-binding"))
        return body
Example #9
0
    def visit_BindChange(self, node):
        body = []

        body.append(Comment("start model-binding"))

        new_stack = identifier("stack", id(node))
        old_stack = self._current_stack
        body += template("CAPTURED_STACK = STACK.capture()",
                         CAPTURED_STACK=new_stack,
                         STACK=old_stack)

        self._current_stack = new_stack
        self._aliases.append(self._aliases[-1].copy())

        inner = self.visit(node.node)

        self._aliases.pop()
        self._current_stack = old_stack

        on_change_name = identifier("on_change", id(node))
        on_change_func = [
            ast.FunctionDef(name=on_change_name,
                            args=ast.arguments(
                                args=[],
                                defaults=(),
                            ),
                            body=inner)
        ]
        if node.model_name not in self._defined_models:
            raise TranslationError(
                "Cannot find bind model on current context.", node.model_name)

        body += on_change_func
        bind_attrs = ast.Tuple(
            elts=[ast.Str(s=attr) for attr in node.bind_attrs], ctx=ast.Load())
        bind_ons = ast.Tuple(elts=[ast.Str(s=attr) for attr in node.bind_ons],
                             ctx=ast.Load())
        body += template("BIND_CHANGE(MODEL, BIND_ONS, BIND_ATTRS, ON_CHANGE)",
                         BIND_CHANGE=Symbol(bind_change),
                         MODEL=load(self._defined_models[node.model_name]),
                         BIND_ATTRS=bind_attrs,
                         BIND_ONS=bind_ons,
                         ON_CHANGE=on_change_name)

        body.append(Comment("end model-binding"))
        return body
Example #10
0
    def visit_BindReplay(self, node):
        body = []

        body.append(Comment("start replay-binding"))

        new_stack = identifier("stack", id(node))
        old_stack = self._current_stack
        body += template("CAPTURED_STACK = STACK.capture()",
                         CAPTURED_STACK=new_stack,
                         STACK=old_stack)

        self._current_stack = new_stack
        self._aliases.append(self._aliases[-1].copy())

        inner = self.visit(node.node)

        self._aliases.pop()
        self._current_stack = old_stack

        on_event_name = identifier("on_event", id(node))
        on_event_func = [
            ast.FunctionDef(name=on_event_name,
                            args=ast.arguments(
                                args=[],
                                defaults=(),
                            ),
                            body=inner)
        ]

        body += on_event_func

        bindable = "__bindable"
        body += self._engine(node.expression, store(bindable))
        events = ast.Tuple(elts=[ast.Str(s=attr) for attr in node.events],
                           ctx=ast.Load())

        body += template("BIND_REPLAY(BINDABLE, EVENTS, ON_EVENT)",
                         BIND_REPLAY=Symbol(bind_replay),
                         BINDABLE=bindable,
                         EVENTS=events,
                         ON_EVENT=on_event_name)

        body.append(Comment("end model-binding"))
        return body
Example #11
0
def set_error(token, exception):
    try:
        line, column = token.location
        filename = token.filename
    except AttributeError:
        line, column = 0, 0
        filename = "<string>"

    string = safe_native(token)

    return template(
        "rcontext.setdefault('__error__', [])."
        "append((string, line, col, src, exc))",
        string=ast.Str(s=string),
        line=ast.Num(n=line),
        col=ast.Num(n=column),
        src=ast.Str(s=filename),
        sys=Symbol(sys),
        exc=exception,
    )
Example #12
0
 class ProviderExpr(expressions.ProviderExpr):
     transform = Symbol(render_content_provider)
Example #13
0
class ProviderExpr(ContextExprMixin, StringExpr):
    """provider: TALES expression"""

    transform = Symbol(render_content_provider)
Example #14
0
class TrustedPathExpr(PathExpr):
    traverser = Static(
        template("cls()",
                 cls=Symbol(TrustedBoboAwareZopeTraverse),
                 mode="eval"))
Example #15
0
    def visit_Name(self, node):
        value = self.secured.get(node.id)
        if value is not None:
            return Symbol(value)

        return node
Example #16
0
def static(obj):
    return Static(template("obj", obj=Symbol(obj), mode="eval"))
Example #17
0
class PathExpr(expressions.PathExpr):
    exceptions = zope2_exceptions

    traverser = Static(
        template("cls()", cls=Symbol(BoboAwareZopeTraverse), mode="eval"))
Example #18
0
class ExpressionTransform(object):
    """Internal wrapper to transform expression nodes into assignment
    statements.

    The node input may use the provided expression engine, but other
    expression node types are supported such as ``Builtin`` which
    simply resolves a built-in name.

    Used internally be the compiler.
    """

    loads_symbol = Symbol(pickle.loads)

    def __init__(self, engine_factory, cache, visitor, strict=True):
        self.engine_factory = engine_factory
        self.cache = cache
        self.strict = strict
        self.visitor = visitor

    def __call__(self, expression, target):
        if isinstance(target, string_type):
            target = store(target)

        try:
            stmts = self.translate(expression, target)
        except ExpressionError:
            if self.strict:
                raise

            exc = sys.exc_info()[1]
            p = pickle.dumps(exc)

            stmts = template("__exc = loads(p)",
                             loads=self.loads_symbol,
                             p=ast.Str(s=p))

            token = Token(exc.token, exc.offset, filename=exc.filename)

            stmts += set_error(token, load("__exc"))
            stmts += [ast.Raise(exc=load("__exc"))]

        # Apply visitor to each statement
        for stmt in stmts:
            self.visitor(stmt)

        return stmts

    def translate(self, expression, target):
        if isinstance(target, string_type):
            target = store(target)

        cached = self.cache.get(expression)

        if cached is not None:
            stmts = [ast.Assign(targets=[target], value=cached)]
        elif isinstance(expression, ast.expr):
            stmts = [ast.Assign(targets=[target], value=expression)]
        else:
            # The engine interface supports simple strings, which
            # default to expression nodes
            if isinstance(expression, string_type):
                expression = Value(expression, True)

            kind = type(expression).__name__
            visitor = getattr(self, "visit_%s" % kind)
            stmts = visitor(expression, target)

            # Add comment
            target_id = getattr(target, "id", target)
            comment = Comment(" %r -> %s" % (expression, target_id))
            stmts.insert(0, comment)

        return stmts

    def visit_Value(self, node, target):
        engine = self.engine_factory()
        compiler = engine.parse(node.value)
        return compiler.assign_value(target)

    def visit_Default(self, node, target):
        value = annotated(node.marker)
        return [ast.Assign(targets=[target], value=value)]

    def visit_Substitution(self, node, target):
        engine = self.engine_factory(
            char_escape=node.char_escape,
            default=node.default,
        )
        compiler = engine.parse(node.value)
        return compiler.assign_text(target)

    def visit_Negate(self, node, target):
        return self.translate(node.value, target) + \
               template("TARGET = not TARGET", TARGET=target)

    def visit_Identity(self, node, target):
        expression = self.translate(node.expression, "__expression")
        value = self.translate(node.value, "__value")

        return expression + value + \
               template("TARGET = __expression is __value", TARGET=target)

    def visit_Equality(self, node, target):
        expression = self.translate(node.expression, "__expression")
        value = self.translate(node.value, "__value")

        return expression + value + \
               template("TARGET = __expression == __value", TARGET=target)

    def visit_Boolean(self, node, target):
        engine = self.engine_factory()
        compiler = engine.parse(node.value)
        return compiler.assign_bool(target, node.s)

    def visit_Interpolation(self, node, target):
        expr = node.value
        if isinstance(expr, Substitution):
            engine = self.engine_factory(
                char_escape=expr.char_escape,
                default=expr.default,
            )
        elif isinstance(expr, Value):
            engine = self.engine_factory()
        else:
            raise RuntimeError("Bad value: %r." % node.value)

        interpolator = Interpolator(expr.value, node.braces_required,
                                    node.translation)

        compiler = engine.get_compiler(interpolator, expr.value)
        return compiler(target, engine)

    def visit_Translate(self, node, target):
        if node.msgid is not None:
            msgid = ast.Str(s=node.msgid)
        else:
            msgid = target
        return self.translate(node.node, target) + \
               emit_translate(target, msgid, default=target)

    def visit_Static(self, node, target):
        value = annotated(node)
        return [ast.Assign(targets=[target], value=value)]

    def visit_Builtin(self, node, target):
        value = annotated(node)
        return [ast.Assign(targets=[target], value=value)]
    The compilation result is cached in ``_zt_expr_registry``.
    """
    if engine is None:
        engine = econtext["__zt_engine__"]
    key = id(engine), type, expression
    # cache lookup does not need to be protected by locking
    #  (but we could potentially prevent unnecessary computations)
    expr = _zt_expr_registry.get(key)
    if expr is None:
        expr = engine.types[type](type, expression, engine)
        _zt_expr_registry[key] = expr
    return expr


_compile_zt_expr_node = Static(Symbol(_compile_zt_expr))


class _C2ZContextWrapper(Context):
    """Behaves like "zope" context with vars from "chameleon" context."""
    def __init__(self, c_context):
        self.__c_context = c_context
        self.__z_context = c_context["__zt_context__"]

    # delegate to ``__c_context``
    @property
    def vars(self):
        return self

    def __getitem__(self, key):
        try:
Example #20
0
class ProviderExpr(ContextExpressionMixin, StringExpr):
    transform = Symbol(render_content_provider)
Example #21
0
class I18nExpr(ContextExprMixin, StringExpr):
    """i18n:context.attribute TALES expression"""

    transform = Symbol(render_i18n_expression)
Example #22
0
    The compilation result is cached in ``_zt_expr_registry``.
    """
    if engine is None:
        engine = econtext["__zt_engine__"]
    key = id(engine), type, expression
    # cache lookup does not need to be protected by locking
    #  (but we could potentially prevent unnecessary computations)
    expr = _zt_expr_registry.get(key)
    if expr is None:
        expr = engine.types[type](type, expression, engine)
        _zt_expr_registry[key] = expr
    return expr


_compile_zt_expr_node = Static(Symbol(_compile_zt_expr))

# map context class to context wrapper class
_context_class_registry = {}


def _with_vars_from_chameleon(context):
    """prepare *context* to get its ``vars`` from ``chameleon``."""
    cc = context.__class__
    wc = _context_class_registry.get(cc)
    if wc is None:

        class ContextWrapper(_C2ZContextWrapperBase, cc):
            pass

        wc = _context_class_registry[cc] = ContextWrapper
Example #23
0
class PathExpr(TalesExpr):
    path_regex = re.compile(
        r'^(?:(nocall|not):\s*)*((?:[A-Za-z0-9_][A-Za-z0-9_:]*)' +
        r'(?:/[?A-Za-z0-9_@\-+][?A-Za-z0-9_@\-\.+/:]*)*)$')

    interpolation_regex = re.compile(r'\?[A-Za-z][A-Za-z0-9_]+')

    traverser = Symbol(path_traverse)

    def translate(self, string, target):
        """
        >>> from chameleon.tales import test
        >>> test(PathExpr('None')) is None
        True
        """
        string = string.strip()

        if not string:
            return template("target = None", target=target)

        m = self.path_regex.match(string)
        if m is None:
            raise ExpressionError("Not a valid path-expression.", string)

        nocall, path = m.groups()

        # note that unicode paths are not allowed
        parts = str(path).split('/')

        components = []
        for part in parts[1:]:
            interpolation_args = []

            def replace(match):
                start, end = match.span()
                interpolation_args.append(part[start + 1:end])
                return "%s"

            while True:
                part, count = self.interpolation_regex.subn(replace, part)
                if count == 0:
                    break

            if len(interpolation_args):
                component = template("format % args",
                                     format=ast.Str(part),
                                     args=ast.Tuple(
                                         list(map(load, interpolation_args)),
                                         ast.Load()),
                                     mode="eval")
            else:
                component = ast.Str(part)

            components.append(component)

        base = parts[0]

        if not components:
            if len(parts) == 1 and (nocall or base == 'None'):
                return template("target = base", base=base, target=target)
            else:
                components = ()

        call = template(
            "traverse(base, econtext, call, path_items)",
            traverse=self.traverser,
            base=load(base),
            call=load(str(not nocall)),
            path_items=ast.Tuple(elts=components),
            mode="eval",
        )

        return template("target = value", target=target, value=call)
Example #24
0
 def __call__(self, target, engine):
     assignment = super(PermissionExpr, self).__call__(target, engine)
     return assignment + template(
         'target = check_permission(context, target)',
         target=target,
         check_permission=Symbol(checkPermission))