Ejemplo n.º 1
0
    def __init__(self, keyword, attributes, **kwargs):
        expressions = ["buffered", "cached", "args"] + [
            c for c in attributes if c.startswith("cache_")
        ]

        super(BlockTag, self).__init__(
            keyword,
            attributes,
            expressions,
            ("name", "filter", "decorator"),
            (),
            **kwargs
        )
        name = attributes.get("name")
        if name and not re.match(r"^[\w_]+$", name):
            raise exceptions.CompileException(
                "%block may not specify an argument signature",
                **self.exception_kwargs
            )
        if not name and attributes.get("args", None):
            raise exceptions.CompileException(
                "Only named %blocks may specify args", **self.exception_kwargs
            )
        self.body_decl = ast.FunctionArgs(
            attributes.get("args", ""), **self.exception_kwargs
        )

        self.name = name
        self.decorator = attributes.get("decorator", "")
        self.filter_args = ast.ArgumentList(
            attributes.get("filter", ""), **self.exception_kwargs
        )
Ejemplo n.º 2
0
    def visitBlockTag(self, node):
        if node is not self.node and not node.is_anonymous:

            if isinstance(self.node, parsetree.DefTag):
                raise exceptions.CompileException(
                    "Named block '%s' not allowed inside of def '%s'" %
                    (node.name, self.node.name), **node.exception_kwargs)
            elif isinstance(self.node,
                            (parsetree.CallTag, parsetree.CallNamespaceTag)):
                raise exceptions.CompileException(
                    "Named block '%s' not allowed inside of <%%call> tag" %
                    (node.name, ), **node.exception_kwargs)

        for ident in node.undeclared_identifiers():
            if ident != "context" and ident not in self.declared.union(
                    self.locally_declared):
                self.undeclared.add(ident)

        if not node.is_anonymous:
            self._check_name_exists(self.topleveldefs, node)
            self.undeclared.add(node.funcname)
        elif node is not self.node:
            self._check_name_exists(self.closuredefs, node)
        for ident in node.declared_identifiers():
            self.argument_declared.add(ident)
        for n in node.nodes:
            n.accept_visitor(self)
Ejemplo n.º 3
0
    def __init__(self, code, allow_kwargs=True, **exception_kwargs):
        self.code = code
        expr = pyparser.parse(code, "exec", **exception_kwargs)

        f = pyparser.ParseFunc(self, **exception_kwargs)
        f.visit(expr)
        if not hasattr(self, "funcname"):
            raise exceptions.CompileException(
                "Code '%s' is not a function declaration" % code,
                **exception_kwargs)
        if not allow_kwargs and self.kwargs:
            raise exceptions.CompileException(
                "'**%s' keyword argument not allowed here" %
                self.kwargnames[-1], **exception_kwargs)
Ejemplo n.º 4
0
    def __init__(self, keyword, attributes, **kwargs):
        expressions = ["buffered", "cached"] + [
            c for c in attributes if c.startswith("cache_")
        ]

        super(DefTag, self).__init__(
            keyword,
            attributes,
            expressions,
            ("name", "filter", "decorator"),
            ("name",),
            **kwargs
        )
        name = attributes["name"]
        if re.match(r"^[\w_]+$", name):
            raise exceptions.CompileException(
                "Missing parenthesis in %def", **self.exception_kwargs
            )
        self.function_decl = ast.FunctionDecl(
            "def " + name + ":pass", **self.exception_kwargs
        )
        self.name = self.function_decl.funcname
        self.decorator = attributes.get("decorator", "")
        self.filter_args = ast.ArgumentList(
            attributes.get("filter", ""), **self.exception_kwargs
        )
Ejemplo n.º 5
0
 def visitDefOrBase(s, node):
     if node.is_anonymous:
         raise exceptions.CompileException(
             "Can't put anonymous blocks inside "
             "<%namespace>", **node.exception_kwargs)
     self.write_inline_def(node, identifiers, nested=False)
     export.append(node.funcname)
Ejemplo n.º 6
0
    def decode_raw_stream(self, text, decode_raw, known_encoding, filename):
        """given string/unicode or bytes/string, determine encoding
           from magic encoding comment, return body as unicode
           or raw if decode_raw=False

        """
        if isinstance(text, compat.text_type):
            m = self._coding_re.match(text)
            encoding = m and m.group(1) or known_encoding or "utf-8"
            return encoding, text

        if text.startswith(codecs.BOM_UTF8):
            text = text[len(codecs.BOM_UTF8):]
            parsed_encoding = "utf-8"
            m = self._coding_re.match(text.decode("utf-8", "ignore"))
            if m is not None and m.group(1) != "utf-8":
                raise exceptions.CompileException(
                    "Found utf-8 BOM in file, with conflicting "
                    "magic encoding comment of '%s'" % m.group(1),
                    text.decode("utf-8", "ignore"),
                    0,
                    0,
                    filename,
                )
        else:
            m = self._coding_re.match(text.decode("utf-8", "ignore"))
            if m:
                parsed_encoding = m.group(1)
            else:
                parsed_encoding = known_encoding or "utf-8"

        if decode_raw:
            try:
                text = text.decode(parsed_encoding)
            except UnicodeDecodeError:
                raise exceptions.CompileException(
                    "Unicode decode operation of encoding '%s' failed" %
                    parsed_encoding,
                    text.decode("utf-8", "ignore"),
                    0,
                    0,
                    filename,
                )

        return parsed_encoding, text
Ejemplo n.º 7
0
 def _check_name_exists(self, collection, node):
     existing = collection.get(node.funcname)
     collection[node.funcname] = node
     if (existing is not None and existing is not node
             and (node.is_block or existing.is_block)):
         raise exceptions.CompileException(
             "%%def or %%block named '%s' already "
             "exists in this template." % node.funcname,
             **node.exception_kwargs)
Ejemplo n.º 8
0
 def _parse_attributes(self, expressions, nonexpressions):
     undeclared_identifiers = set()
     self.parsed_attributes = {}
     for key in self.attributes:
         if key in expressions:
             expr = []
             for x in re.compile(r"(\${.+?})", re.S).split(
                 self.attributes[key]
             ):
                 m = re.compile(r"^\${(.+?)}$", re.S).match(x)
                 if m:
                     code = ast.PythonCode(
                         m.group(1).rstrip(), **self.exception_kwargs
                     )
                     # we aren't discarding "declared_identifiers" here,
                     # which we do so that list comprehension-declared
                     # variables aren't counted.   As yet can't find a
                     # condition that requires it here.
                     undeclared_identifiers = undeclared_identifiers.union(
                         code.undeclared_identifiers
                     )
                     expr.append("(%s)" % m.group(1))
                 else:
                     if x:
                         expr.append(repr(x))
             self.parsed_attributes[key] = " + ".join(expr) or repr("")
         elif key in nonexpressions:
             if re.search(r"\${.+?}", self.attributes[key]):
                 raise exceptions.CompileException(
                     "Attibute '%s' in tag '%s' does not allow embedded "
                     "expressions" % (key, self.keyword),
                     **self.exception_kwargs
                 )
             self.parsed_attributes[key] = repr(self.attributes[key])
         else:
             raise exceptions.CompileException(
                 "Invalid attribute for tag '%s': '%s'"
                 % (self.keyword, key),
                 **self.exception_kwargs
             )
     self.expression_undeclared_identifiers = undeclared_identifiers
Ejemplo n.º 9
0
    def parse(self):
        self.encoding, self.text = self.decode_raw_stream(
            self.text, not self.disable_unicode, self.encoding, self.filename)

        for preproc in self.preprocessor:
            self.text = preproc(self.text)

        # push the match marker past the
        # encoding comment.
        self.match_reg(self._coding_re)

        self.textlength = len(self.text)

        while True:
            if self.match_position > self.textlength:
                break

            if self.match_end():
                break
            if self.match_expression():
                continue
            if self.match_control_line():
                continue
            if self.match_comment():
                continue
            if self.match_tag_start():
                continue
            if self.match_tag_end():
                continue
            if self.match_python_block():
                continue
            if self.match_text():
                continue

            if self.match_position > self.textlength:
                break
            raise exceptions.CompileException("assertion failed")

        if len(self.tag):
            raise exceptions.SyntaxException(
                "Unclosed tag: <%%%s>" % self.tag[-1].keyword,
                **self.exception_kwargs)
        if len(self.control_line):
            raise exceptions.SyntaxException(
                "Unterminated control keyword: '%s'" %
                self.control_line[-1].keyword,
                self.text,
                self.control_line[-1].lineno,
                self.control_line[-1].pos,
                self.filename,
            )
        return self.template
Ejemplo n.º 10
0
    def __init__(self, keyword, attributes, **kwargs):
        super(NamespaceTag, self).__init__(
            keyword,
            attributes,
            ("file",),
            ("name", "inheritable", "import", "module"),
            (),
            **kwargs
        )

        self.name = attributes.get("name", "__anon_%s" % hex(abs(id(self))))
        if "name" not in attributes and "import" not in attributes:
            raise exceptions.CompileException(
                "'name' and/or 'import' attributes are required "
                "for <%namespace>",
                **self.exception_kwargs
            )
        if "file" in attributes and "module" in attributes:
            raise exceptions.CompileException(
                "<%namespace> may only have one of 'file' or 'module'",
                **self.exception_kwargs
            )
Ejemplo n.º 11
0
 def visit_ImportFrom(self, node):
     for name in node.names:
         if name.asname is not None:
             self._add_declared(name.asname)
         else:
             if name.name == "*":
                 raise exceptions.CompileException(
                     "'import *' is not supported, since all identifier "
                     "names must be explicitly declared.  Please use the "
                     "form 'from <modulename> import <name1>, <name2>, "
                     "...' instead.",
                     **self.exception_kwargs
                 )
             self._add_declared(name.name)
Ejemplo n.º 12
0
 def __init__(self, code, **exception_kwargs):
     m = re.match(r"^(\w+)(?:\s+(.*?))?:\s*(#|$)", code.strip(), re.S)
     if not m:
         raise exceptions.CompileException(
             "Fragment '%s' is not a partial control statement" % code,
             **exception_kwargs)
     if m.group(3):
         code = code[:m.start(3)]
     (keyword, expr) = m.group(1, 2)
     if keyword in ["for", "if", "while"]:
         code = code + "pass"
     elif keyword == "try":
         code = code + "pass\nexcept:pass"
     elif keyword == "elif" or keyword == "else":
         code = "if False:pass\n" + code + "pass"
     elif keyword == "except":
         code = "try:pass\n" + code + "pass"
     elif keyword == "with":
         code = code + "pass"
     else:
         raise exceptions.CompileException(
             "Unsupported control keyword: '%s'" % keyword,
             **exception_kwargs)
     super(PythonFragment, self).__init__(code, **exception_kwargs)
Ejemplo n.º 13
0
    def __call__(cls, keyword, attributes, **kwargs):
        if ":" in keyword:
            ns, defname = keyword.split(":")
            return type.__call__(
                CallNamespaceTag, ns, defname, attributes, **kwargs
            )

        try:
            cls = _TagMeta._classmap[keyword]
        except KeyError:
            raise exceptions.CompileException(
                "No such tag: '%s'" % keyword,
                source=kwargs["source"],
                lineno=kwargs["lineno"],
                pos=kwargs["pos"],
                filename=kwargs["filename"],
            )
        return type.__call__(cls, keyword, attributes, **kwargs)
Ejemplo n.º 14
0
    def __init__(
        self,
        keyword,
        attributes,
        expressions,
        nonexpressions,
        required,
        **kwargs
    ):
        r"""construct a new Tag instance.

        this constructor not called directly, and is only called
        by subclasses.

        :param keyword: the tag keyword

        :param attributes: raw dictionary of attribute key/value pairs

        :param expressions: a set of identifiers that are legal attributes,
         which can also contain embedded expressions

        :param nonexpressions: a set of identifiers that are legal
         attributes, which cannot contain embedded expressions

        :param \**kwargs:
         other arguments passed to the Node superclass (lineno, pos)

        """
        super(Tag, self).__init__(**kwargs)
        self.keyword = keyword
        self.attributes = attributes
        self._parse_attributes(expressions, nonexpressions)
        missing = [r for r in required if r not in self.parsed_attributes]
        if len(missing):
            raise exceptions.CompileException(
                "Missing attribute(s): %s"
                % ",".join([repr(m) for m in missing]),
                **self.exception_kwargs
            )
        self.parent = None
        self.nodes = []