Example #1
0
    def parse(self, parser):
        lineno = next(parser.stream).lineno

        next_token = parser.stream.look()
        # if there are parameters
        if next_token.type == "comma":
            args = [parser.parse_expression()]
            if parser.stream.skip_if('comma'):
                args.append(parser.parse_expression())
            else:
                raise TemplateSyntaxError("Missing Lorem Ipsum generator parameter: kind", lineno)

            if args[1].value not in self.GENERATORS:
                raise TemplateSyntaxError(
                    "Supported Lorem Ipsum generator kinds are: %s" % ", ".join(self.GENERATORS.keys()),
                    lineno
                )
        else:
            # if no parameters were supplied
            args = [nodes.Const(1), nodes.Const("paragraphs")]

        return nodes.Output(
            [self.call_method("_lipsum", args)],
            lineno=lineno
        )
Example #2
0
    def parse(self, parser):
        # Store the first lineno for the actual function call
        lineno = parser.stream.current.lineno
        next(parser.stream)
        args = []

        kindarg = const(parser.parse_expression())

        if kindarg.value in self.compressors:
            args.append(kindarg)
        else:
            raise TemplateSyntaxError(
                'Compress kind may be one of: %r, got: %r' %
                (self.compressors.keys(), kindarg.value),
                parser.stream.current.lineno)

        # For legacy support, allow for a commma but simply ignore it
        parser.stream.skip_if('comma')

        # Some sane defaults for file output
        namearg = nodes.Const(None)
        modearg = nodes.Const('file')

        # If we're not at the "%}" part yet we must have a output mode argument
        if parser.stream.current.type != 'block_end':
            modearg = const(parser.parse_expression())
            args.append(modearg)

            if modearg.value == compress.OUTPUT_FILE:
                # The file mode optionally accepts a name
                if parser.stream.current.type != 'block_end':
                    namearg = const(parser.parse_expression())
            elif modearg.value == compress.OUTPUT_INLINE or modearg.value == compress.OUTPUT_PRELOAD:
                pass
            else:
                raise TemplateSyntaxError(
                    'Compress mode may be one of: %r, got %r' %
                    (compress.OUTPUT_MODES, modearg.value),
                    parser.stream.current.lineno)

        # Parse everything between the compress and endcompress tags
        body = parser.parse_statements(['name:endcompress'], drop_needle=True)

        # Skip the kind if used in the endblock, by using the kind in the
        # endblock the templates are slightly more readable.
        parser.stream.skip_if('name:' + kindarg.value)

        return nodes.CallBlock(
            self.call_method('_compress_normal', [kindarg, modearg, namearg]),
            [], [], body).set_lineno(lineno)
Example #3
0
    def _save_compound(self, compound, system_name, forcefield, ast_node, caller):

        import mbuild as mb
        if isinstance(compound, mb.Compound):
            system_name = os.path.join(self.environment.globals['output_dir'], system_name)
            mkdirs.mkdirs(system_name, exists_ok=True)
            compound.save(system_name, forcefield=forcefield, overwrite=True)
        else:
            if isinstance(compound, string_types) and re.match(r'^\s*\{\{\s*\w+\s*\}\}\s*$', compound, 0):
                raise TemplateSyntaxError("Context is not an mBuild Compound, but '{}'".format(compound), lineno=0)
            else:
                raise TemplateSyntaxError("Context is not an mBuild Compound, but of type {}".format(type(compound)), lineno=0)

        return ''
Example #4
0
 def expect(self, expr):
     if not self.current.test(expr):
         expr = describe_token_expr(expr)
         if self.current.type is TOKEN_EOF:
             raise TemplateSyntaxError(
                 'unexpected end of template, expected %r.' % expr,
                 self.current.lineno, self.name, self.filename)
         raise TemplateSyntaxError(
             'expected token %r, got %r' %
             (expr, describe_token(self.current)), self.current.lineno,
             self.name, self.filename)
     try:
         return self.current
     finally:
         next(self)
Example #5
0
        def parse_formrow(self, parser, tag):
            lineno = tag.lineno
            field = parser.parse_expression()
            template_name = None
            if not parser.stream.current.test('block_end'):
                template_name = parser.parse_expression()
            else:
                template_name = nodes.Call(
                    nodes.Name('get_formrow_template', 'load'),
                    [],
                    [
                        nodes.Keyword('caller_template',
                                      nodes.Const(parser.name)),
                        nodes.Keyword('form',
                                      nodes.Name('form_utils_form', 'load'))
                    ],
                    None,
                    None,
                )
            if not parser.stream.current.test('block_end'):
                raise TemplateSyntaxError("Too many arguments", lineno)

            node = nodes.Scope(lineno=lineno)
            assignments = [nodes.Assign(nodes.Name('field', 'store'), field)]
            node.body = assignments + [
                nodes.Include(template_name, True, False)
            ]
            return node.set_lineno(lineno)
Example #6
0
    def parse(self, parser):
        lineno = next(parser.stream).lineno
        kindarg = parser.parse_expression()
        # Allow kind to be defined as jinja2 name node
        if isinstance(kindarg, nodes.Name):
            kindarg = nodes.Const(kindarg.name)
        args = [kindarg]
        if args[0].value not in self.compressors:
            raise TemplateSyntaxError(
                "compress kind may be one of: %s" %
                (", ".join(self.compressors.keys())),
                lineno,
            )
        if parser.stream.skip_if("comma"):
            modearg = parser.parse_expression()
            # Allow mode to be defined as jinja2 name node
            if isinstance(modearg, nodes.Name):
                modearg = nodes.Const(modearg.name)
                args.append(modearg)
        else:
            args.append(nodes.Const("file"))

        body = parser.parse_statements(["name:endcompress"], drop_needle=True)

        # Skip the kind if used in the endblock, by using the kind in the
        # endblock the templates are slightly more readable.
        parser.stream.skip_if("name:" + kindarg.value)
        return nodes.CallBlock(self.call_method("_compress_normal", args), [],
                               [], body).set_lineno(lineno)
Example #7
0
    def parse(self, parser):
        lineno = parser.stream.__next__().lineno
        value = parser.parse_expression()

        items_per_page_obj = parser.stream.next_if('integer')
        items_per_page = items_per_page_obj.value if items_per_page_obj else DEFAULT_PAGINATION

        if parser.stream.skip_if('name:as'):
            name = parser.stream.expect('name').value
        elif hasattr(value, 'name'):
            name = value.name
        else:
            raise TemplateSyntaxError("Cannot determine the name of objects you want to paginate, use 'as foobar' syntax", lineno)

        while not parser.stream.current.type == 'block_end':
            parser.stream.skip()

        return [
            nodes.Assign(nodes.Name(name + '_pages', 'store'),
                self.call_method('_render_pages', [value, nodes.Name('request', 'load'), nodes.Const(items_per_page)])
            ).set_lineno(lineno),

            nodes.Assign(nodes.Name(name, 'store'),
                nodes.Getattr(nodes.Name(name + '_pages', 'load'), 'object_list', nodes.Impossible())
            ).set_lineno(lineno),
        ]
Example #8
0
 def expect(self, expr):
     """Expect a given token type and return it.  This accepts the same
     argument as :meth:`jinja2.lexer.Token.test`.
     """
     if not self.current.test(expr):
         expr = describe_token_expr(expr)
         if self.current.type is TOKEN_EOF:
             raise TemplateSyntaxError(
                 'unexpected end of template, expected %r.' % expr,
                 self.current.lineno, self.name, self.filename)
         raise TemplateSyntaxError(
             'expected token %r, got %r' %
             (expr, describe_token(self.current)), self.current.lineno,
             self.name, self.filename)
     try:
         return self.current
     finally:
         next(self)
Example #9
0
    def parse(self, parser):
        lineno = parser.stream.next().lineno
        object_list = parser.parse_expression()
        if parser.stream.skip_if('name:as'):
            name = parser.stream.expect('name').value
        elif hasattr(object_list, 'name'):
            name = object_list.name
        else:
            raise TemplateSyntaxError(
                "Cannot determine the name of objects " \
                    "you want to paginate, use 'as foobar' syntax", lineno)

        kwargs = [] # wait... what?
        loops = 0
        while parser.stream.current.type != 'block_end':
            lineno = parser.stream.current.lineno
            if loops:
                parser.stream.expect('comma')
            key = parser.parse_assign_target().name
            if key not in self.default_kwargs.keys():
                raise TemplateSyntaxError(
                    "Unknown keyword argument for autopaginate. "\
                        "Your options are: %s" % (
                            ", ".join(self.default_kwargs.keys())
                            ))
            parser.stream.expect('assign')
            value = parser.parse_expression()
            kwargs.append(nodes.Keyword(key, value))
            loops += 1

        return [
            nodes.Assign(nodes.Name(name + '_pages', 'store'),
                         self.call_method('_render_pages',
                                          [object_list, nodes.Name('request', 'load')],
                                          kwargs)
                         ).set_lineno(lineno),

            nodes.Assign(nodes.Name(name, 'store'),
                         nodes.Getattr(nodes.Name(name + '_pages', 'load'),
                                       'object_list',
                                       nodes.Impossible())
                         ).set_lineno(lineno),
            ]
Example #10
0
 def expect(self, expr):
     """Expect a given token type and return it.  This accepts the same
     argument as :meth:`jinja2.lexer.Token.test`.
     """
     if not self.current.test(expr):
         if ':' in expr:
             expr = expr.split(':')[1]
         if self.current.type is TOKEN_EOF:
             raise TemplateSyntaxError(
                 'unexpected end of template, '
                 'expected %r.' % expr, self.current.lineno, self.name,
                 self.filename)
         raise TemplateSyntaxError(
             "expected token %r, got %r" % (expr, str(self.current)),
             self.current.lineno, self.name, self.filename)
     try:
         return self.current
     finally:
         self.next()
Example #11
0
 def parse_formrow_template(self, parser, tag):
     lineno = tag.lineno
     template_name = parser.parse_expression()
     if not parser.stream.current.test('block_end'):
         raise TemplateSyntaxError("Too many arguments", lineno)
     call = self.call_method('_process', [
         template_name,
         nodes.Name('form_utils_form', 'load', lineno=lineno)
     ])
     return nodes.Output([nodes.MarkSafe(call)]).set_lineno(lineno)
Example #12
0
 def wrap(self, stream, name=None, filename=None):
     """This is called with the stream as returned by `tokenize` and wraps
     every token in a :class:`Token` and converts the value.
     """
     for lineno, token, value in stream:
         if token in ignored_tokens:
             continue
         elif token == "linestatement_begin":
             token = "block_begin"
         elif token == "linestatement_end":
             token = "block_end"
         # we are not interested in those tokens in the parser
         elif token in ("raw_begin", "raw_end"):
             continue
         elif token == "data":
             value = self._normalize_newlines(value)
         elif token == "keyword":
             token = value
         elif token == "name":
             value = str(value)
             if check_ident and not value.isidentifier():
                 raise TemplateSyntaxError(
                     "Invalid character in identifier", lineno, name, filename
                 )
         elif token == "string":
             # try to unescape string
             try:
                 value = (
                     self._normalize_newlines(value[1:-1])
                     .encode("ascii", "backslashreplace")
                     .decode("unicode-escape")
                 )
             except Exception as e:
                 msg = str(e).split(":")[-1].strip()
                 raise TemplateSyntaxError(msg, lineno, name, filename)
         elif token == "integer":
             value = int(value)
         elif token == "float":
             value = float(value)
         elif token == "operator":
             token = operators[value]
         yield Token(lineno, token, value)
Example #13
0
    def parse(self, parser):
        stream = parser.stream

        tag = stream.next()

        # get view name
        if stream.current.test('string'):
            viewname = parser.parse_primary()
        else:
            # parse valid tokens and manually build a string from them
            bits = []
            name_allowed = True
            while True:
                if stream.current.test_any('dot', 'sub'):
                    bits.append(stream.next())
                    name_allowed = True
                elif stream.current.test('name') and name_allowed:
                    bits.append(stream.next())
                    name_allowed = False
                else:
                    break
            viewname = nodes.Const("".join([b.value for b in bits]))
            if not bits:
                raise TemplateSyntaxError(
                    "'%s' requires path to view" % tag.value, tag.lineno)

        # get arguments
        args = []
        kwargs = []
        while not stream.current.test_any('block_end', 'name:as'):
            if args or kwargs:
                stream.expect('comma')
            if stream.current.test('name') and stream.look().test('assign'):
                key = nodes.Const(stream.next().value)
                stream.skip()
                value = parser.parse_expression()
                kwargs.append(nodes.Pair(key, value, lineno=key.lineno))
            else:
                args.append(parser.parse_expression())

        make_call_node = lambda *kw: \
            self.call_method('_reverse',
                             args=[viewname, nodes.List(args), nodes.Dict(kwargs)],
                             kwargs=kw)

        # if an as-clause is specified, write the result to context...
        if stream.next_if('name:as'):
            var = nodes.Name(stream.expect('name').value, 'store')
            call_node = make_call_node(
                nodes.Keyword('fail', nodes.Const(False)))
            return nodes.Assign(var, call_node)
        # ...otherwise print it out.
        else:
            return nodes.Output([make_call_node()]).set_lineno(tag.lineno)
Example #14
0
def json_path(data, path):
    if data is None:
        raise TemplateSyntaxError('JSON decode failure!', 0)
    jsonpath_expr = jsonpath_parse(path)
    match = jsonpath_expr.find(data)
    if len(match) < 1:
        return ''
    value = match[0].value
    if value is None:
        value = 'null'
    return value
Example #15
0
 def wrap(self, stream, name=None, filename=None):
     """This is called with the stream as returned by `tokenize` and wraps
     every token in a :class:`Token` and converts the value.
     """
     for lineno, token, value in stream:
         if token in ignored_tokens:
             continue
         elif token == TOKEN_LINESTATEMENT_BEGIN:
             token = TOKEN_BLOCK_BEGIN
         elif token == TOKEN_LINESTATEMENT_END:
             token = TOKEN_BLOCK_END
         # we are not interested in those tokens in the parser
         elif token in (TOKEN_RAW_BEGIN, TOKEN_RAW_END):
             continue
         elif token == TOKEN_DATA:
             value = self._normalize_newlines(value)
         elif token == 'keyword':
             token = value
         elif token == TOKEN_NAME:
             value = str(value)
             if check_ident and not value.isidentifier():
                 raise TemplateSyntaxError(
                     'Invalid character in identifier',
                     lineno, name, filename)
         elif token == TOKEN_STRING:
             # try to unescape string
             try:
                 value = self._normalize_newlines(value[1:-1]) \
                     .encode('ascii', 'backslashreplace') \
                     .decode('unicode-escape')
             except Exception as e:
                 msg = str(e).split(':')[-1].strip()
                 raise TemplateSyntaxError(msg, lineno, name, filename)
         elif token == TOKEN_INTEGER:
             value = int(value.replace("_", ""))
         elif token == TOKEN_FLOAT:
             # remove all "_" first to support more Python versions
             value = literal_eval(value.replace("_", ""))
         elif token == TOKEN_OPERATOR:
             token = operators[value]
         yield Token(lineno, token, value)
Example #16
0
 def wrap(self, stream, name=None, filename=None):
     """This is called with the stream as returned by `tokenize` and wraps
     every token in a :class:`Token` and converts the value.
     """
     for lineno, token, value in stream:
         if token in ignored_tokens:
             continue
         elif token == 'linestatement_begin':
             token = 'block_begin'
         elif token == 'linestatement_end':
             token = 'block_end'
         # we are not interested in those tokens in the parser
         elif token in ('raw_begin', 'raw_end'):
             continue
         elif token == 'data':
             value = self._normalize_newlines(value)
         elif token == 'keyword':
             token = value
         elif token == 'name':
             value = str(value)
             if check_ident and not value.isidentifier():
                 raise TemplateSyntaxError(
                     'Invalid character in identifier', lineno, name,
                     filename)
         elif token == 'string':
             # try to unescape string
             try:
                 value = self._normalize_newlines(value[1:-1]) \
                     .encode('ascii', 'backslashreplace') \
                     .decode('unicode-escape')
             except Exception as e:
                 msg = str(e).split(':')[-1].strip()
                 raise TemplateSyntaxError(msg, lineno, name, filename)
         elif token == 'integer':
             value = int(value.replace("_", ""))
         elif token == 'float':
             # remove all "_" first to support more Python versions
             value = literal_eval(value.replace("_", ""))
         elif token == 'operator':
             token = operators[value]
         yield Token(lineno, token, value)
Example #17
0
    def parse(self, parser):
        stream = parser.stream

        tag = next(stream)
        if stream.current.test('string'):
            path = parser.parse_primary()
        else:
            raise TemplateSyntaxError('''
"%s" requires path to asset file''' % tag.value, tag.lineno)
        while not parser.stream.current.type == 'block_end':
            next(parser.stream)
        result = self.call_method('_build_url', args=[path])
        return nodes.Output([nodes.MarkSafe(result)]).set_lineno(tag.lineno)
Example #18
0
    def filter_stream(self, stream):
        paren_stack = 0

        for token in stream:
            if token.type != "data":
                yield token
                continue

            pos = 0
            lineno = token.lineno

            while 1:
                if not paren_stack:
                    match = _outside_re.search(token.value, pos)
                else:
                    match = _inside_re.search(token.value, pos)
                if match is None:
                    break
                new_pos = match.start()
                if new_pos > pos:
                    preval = token.value[pos:new_pos]
                    yield Token(lineno, "data", preval)
                    lineno += count_newlines(preval)
                gtok = match.group()
                if gtok[0] == "\\":
                    yield Token(lineno, "data", gtok[1:])
                elif not paren_stack:
                    yield Token(lineno, "block_begin", None)
                    yield Token(lineno, "name", "trans")
                    yield Token(lineno, "block_end", None)
                    paren_stack = 1
                else:
                    if gtok == "(" or paren_stack > 1:
                        yield Token(lineno, "data", gtok)
                    paren_stack += gtok == ")" and -1 or 1
                    if not paren_stack:
                        yield Token(lineno, "block_begin", None)
                        yield Token(lineno, "name", "endtrans")
                        yield Token(lineno, "block_end", None)
                pos = match.end()

            if pos < len(token.value):
                yield Token(lineno, "data", token.value[pos:])

        if paren_stack:
            raise TemplateSyntaxError(
                "unclosed gettext expression",
                token.lineno,
                stream.name,
                stream.filename,
            )
Example #19
0
def get_document_render_styles(doc_path) -> RenderStylesCollection:
    styles = RenderStylesCollection()

    doc: DocType = Document(doc_path)

    style_name = None
    attrs = dict()

    for element in _iter_block_items(doc):
        if not style_name and not isinstance(element, Paragraph):
            continue

        if not style_name:
            match = _BEGIN_STYLE.match(element.text)
            if match:
                style_name = match.group(1)
        else:
            if isinstance(element, Table):
                attrs['table'] = element._tblPr.xml
            else:
                text = element.text
                if _END_STYLE.match(text):
                    styles.add_style(RenderStyle(name=style_name, **attrs))
                    style_name = None
                    attrs = dict()
                    continue

                match = _TAG_STYLE.match(text)
                if match:
                    tag_name = match.group(1).lower()
                    if tag_name in PARAGRAPH_STYLE_TAGS:
                        # Get style from paragraph
                        if element._element.pPr is not None:
                            attrs[tag_name] = element._element.pPr.xml
                        else:
                            attrs[tag_name] = '<w:pPr></w:pPr>'
                    elif tag_name in RAW_STYLE_TAGS:
                        # Get style from Run
                        if element.runs[0]._element.rPr is not None:
                            attrs[tag_name] = element.runs[0]._element.rPr.xml
                        else:
                            attrs[tag_name] = '<w:rPr></w:rPr>'

    if style_name is not None:
        raise TemplateSyntaxError(
            'Unexpected end of template style definition {}. Never closed'.format(style_name),
            None
        )

    return styles
Example #20
0
    def parse(self, parser):
        lineno = parser.stream.next().lineno
        token = next(parser.stream)

        if token.value not in self.allowed_languages:
            raise TemplateSyntaxError(
                'Expected language token from set: %s' %
                ', '.join(self.allowed_languages), lineno)

        body = parser.parse_statements(['name:endshow'], drop_needle=True)
        node = nodes.CallBlock(
            self.call_method('_show_support', [nodes.Const(token.value)]), [],
            [], body).set_lineno(lineno)
        return node
def thumbnail_obj(source, size, **opts):
    """Make thumbnail from source image"""
    if not source:
        return None

    raise_errors = thumbnailer_settings.THUMBNAIL_DEBUG
    accepted_opts = {}
    for key, value in opts.items():
        if key in VALID_OPTIONS:
            accepted_opts[key] = value
    opts = accepted_opts
    m = RE_SIZE.match(size)

    if m:
        opts['size'] = (int(m.group(1)), int(m.group(2)))
    else:
        if raise_errors:
            raise TemplateSyntaxError('%r is not a valid size.' % size, 1)

    if 'quality' in opts:
        try:
            opts['quality'] = int(opts['quality'])
        except (TypeError, ValueError):
            if raise_errors:
                raise TemplateSyntaxError(
                    '%r is an invalid quality.' % opts['quality'], 1)

    try:
        curr_thumbnail = get_thumbnailer(source).get_thumbnail(opts)
    except Exception as e:
        if raise_errors:
            raise TemplateSyntaxError(
                'Couldn\'t get the thumbnail %s: %s' % (source, e), 1)
        else:
            return None

    return curr_thumbnail
Example #22
0
    def parse(self, parser):
        stream = parser.stream

        tag = stream.next()
        if stream.current.test('string'):
            path = parser.parse_primary()
        else:
            raise TemplateSyntaxError(
                '''\
"%s" requires path to asset file, relative to STATICFILES_URL''' % tag.value,
                tag.lineno)
        while not parser.stream.current.type == 'block_end':
            parser.stream.next()
        result = self.call_method(self.build_method, args=[path])
        return nodes.Output([nodes.MarkSafe(result)]).set_lineno(tag.lineno)
Example #23
0
def addfilter(env: "Environment", token: "Token",
              parser: "Parser") -> nodes.Node:
    """The addfilter tag {% addfilter name ... %} ... {% endaddfilter %}

    This allows one to use the python code inside the body to add a filter or
    replace an existing filter

    Args:
        env: The environment
        token: The token matches tag name
        parser: The parser

    Returns:
        The parsed node
    """
    token = parser.stream.expect("name")
    filtername = token.value

    pass_env: Union[bool, Token]
    if parser.stream.current.type is TOKEN_BLOCK_END:
        # no pass_environment
        pass_env = False
    else:
        pass_env = parser.stream.expect("name:pass_env")

    body = parser.parse_statements(("name:endaddfilter", ), drop_needle=True)
    body = decode_raw(body[0].nodes[0].data)
    body_parts = body.split("\n", 1)
    if not body_parts[0]:
        body = "" if len(body_parts) < 2 else body_parts[1]
    body = textwrap.dedent(body)

    globs = env.globals.copy()
    code = compile(body, "<liquid-addfilter-tag>", mode="exec")
    exec(code, globs)
    try:
        filterfunc = globs[filtername]
    except KeyError:
        raise TemplateSyntaxError(
            f"No such filter defined in 'addfilter': {filtername}",
            token.lineno,
        ) from None

    if pass_env:
        filterfunc = pass_environment(filterfunc)  # type: ignore
    env.filters[filtername] = filterfunc

    return nodes.Output([], lineno=token.lineno)
Example #24
0
    def __getitem__(self, key):
        if not isinstance(key, string_types):
            raise ValueError('key must be a string')

        key = to_native(key)

        if '.' not in key:  # might be a built-in value, delegate to base dict
            return self._delegatee.__getitem__(key)

        func = self._collection_jinja_func_cache.get(key)

        if func:
            return func

        acr = AnsibleCollectionRef.try_parse_fqcr(key, self._dirname)

        if not acr:
            raise KeyError('invalid plugin name: {0}'.format(key))

        try:
            pkg = import_module(acr.n_python_package_name)
        except ImportError:
            raise KeyError()

        parent_prefix = acr.collection

        if acr.subdirs:
            parent_prefix = '{0}.{1}'.format(parent_prefix, acr.subdirs)

        for dummy, module_name, ispkg in pkgutil.iter_modules(
                pkg.__path__, prefix=parent_prefix + '.'):
            if ispkg:
                continue

            try:
                plugin_impl = self._pluginloader.get(module_name)
            except Exception as e:
                raise TemplateSyntaxError(to_native(e), 0)

            method_map = getattr(plugin_impl, self._method_map_name)

            for f in iteritems(method_map()):
                fq_name = '.'.join((parent_prefix, f[0]))
                # FIXME: detect/warn on intra-collection function name collisions
                self._collection_jinja_func_cache[fq_name] = f[1]

        function_impl = self._collection_jinja_func_cache[key]
        return function_impl
Example #25
0
    def filter_stream(self, stream):
        paren_stack = 0

        for token in stream:
            if token.type is not 'data':
                yield token
                continue

            pos = 0
            lineno = token.lineno

            while 1:
                if not paren_stack:
                    match = _outside_re.search(token.value, pos)
                else:
                    match = _inside_re.search(token.value, pos)
                if match is None:
                    break
                new_pos = match.start()
                if new_pos > pos:
                    preval = token.value[pos:new_pos]
                    yield Token(lineno, 'data', preval)
                    lineno += count_newlines(preval)
                gtok = match.group()
                if gtok[0] == '\\':
                    yield Token(lineno, 'data', gtok[1:])
                elif not paren_stack:
                    yield Token(lineno, 'block_begin', None)
                    yield Token(lineno, 'name', 'trans')
                    yield Token(lineno, 'block_end', None)
                    paren_stack = 1
                else:
                    if gtok == '(' or paren_stack > 1:
                        yield Token(lineno, 'data', gtok)
                    paren_stack += gtok == ')' and -1 or 1
                    if not paren_stack:
                        yield Token(lineno, 'block_begin', None)
                        yield Token(lineno, 'name', 'endtrans')
                        yield Token(lineno, 'block_end', None)
                pos = match.end()

            if pos < len(token.value):
                yield Token(lineno, 'data', token.value[pos:])

        if paren_stack:
            raise TemplateSyntaxError('unclosed gettext expression',
                                      token.lineno, stream.name,
                                      stream.filename)
    def compile_expression(self, source, undefined_to_none=True):
        """A handy helper method that returns a callable that accepts keyword
        arguments that appear as variables in the expression.  If called it
        returns the result of the expression.
        
        This is useful if applications want to use the same rules as Jinja
        in template "configuration files" or similar situations.
        
        Example usage:
        
        >>> env = Environment()
        >>> expr = env.compile_expression('foo == 42')
        >>> expr(foo=23)
        False
        >>> expr(foo=42)
        True
        
        Per default the return value is converted to `None` if the
        expression returns an undefined value.  This can be changed
        by setting `undefined_to_none` to `False`.
        
        >>> env.compile_expression('var')() is None
        True
        >>> env.compile_expression('var', undefined_to_none=False)()
        Undefined
        
        .. versionadded:: 2.1
        """
        parser = Parser(self, source, state='variable')
        exc_info = None
        try:
            expr = parser.parse_expression()
            if not parser.stream.eos:
                raise TemplateSyntaxError('chunk after expression',
                                          parser.stream.current.lineno, None,
                                          None)
            expr.set_environment(self)
        except TemplateSyntaxError:
            exc_info = sys.exc_info()

        if exc_info is not None:
            self.handle_exception(exc_info, source_hint=source)
        body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
        template = self.from_string(nodes.Template(body, lineno=1))
        return TemplateExpression(template, undefined_to_none)
Example #27
0
 def wrap(self, stream, name=None, filename=None):
     """This is called with the stream as returned by `tokenize` and wraps
     every token in a :class:`Token` and converts the value.
     """
     for lineno, token, value in stream:
         if token in ignored_tokens:
             continue
         elif token == 'linestatement_begin':
             token = 'block_begin'
         elif token == 'linestatement_end':
             token = 'block_end'
         # we are not interested in those tokens in the parser
         elif token in ('raw_begin', 'raw_end'):
             continue
         elif token == 'data':
             value = self._normalize_newlines(value)
         elif token == 'keyword':
             token = value
         elif token == 'name':
             value = str(value)
         elif token == 'string':
             # try to unescape string
             try:
                 value = self._normalize_newlines(value[1:-1]) \
                     .encode('ascii', 'backslashreplace') \
                     .decode('unicode-escape')
             except Exception as e:
                 msg = str(e).split(':')[-1].strip()
                 raise TemplateSyntaxError(msg, lineno, name, filename)
             # if we can express it as bytestring (ascii only)
             # we do that for support of semi broken APIs
             # as datetime.datetime.strftime.  On python 3 this
             # call becomes a noop thanks to 2to3
             if PY2:
                 try:
                     value = value.encode('ascii')
                 except UnicodeError:
                     pass
         elif token == 'integer':
             value = int(value)
         elif token == 'float':
             value = float(value)
         elif token == 'operator':
             token = operators[value]
         yield Token(lineno, token, value)
Example #28
0
    def compile_expression(self, source, undefined_to_none=True):
        parser = Parser(self, source, state='variable')
        exc_info = None
        try:
            expr = parser.parse_expression()
            if not parser.stream.eos:
                raise TemplateSyntaxError('chunk after expression',
                                          parser.stream.current.lineno, None,
                                          None)
            expr.set_environment(self)
        except TemplateSyntaxError:
            exc_info = sys.exc_info()

        if exc_info is not None:
            self.handle_exception(exc_info, source_hint=source)
        body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
        template = self.from_string(nodes.Template(body, lineno=1))
        return TemplateExpression(template, undefined_to_none)
Example #29
0
    def _cache_support(self, expire_time, fragm_name, vary_on, lineno, caller):
        from django.core.cache import cache  # delay depending in settings
        from django.utils.http import urlquote

        try:
            expire_time = int(expire_time)
        except (ValueError, TypeError):
            raise TemplateSyntaxError(
                '"%s" tag got a non-integer '
                'timeout value: %r' % (list(self.tags)[0], expire_time),
                lineno)

        cache_key = u':'.join([fragm_name] + [urlquote(v) for v in vary_on])
        value = cache.get(cache_key)
        if value is None:
            value = caller()
            cache.set(cache_key, value, expire_time)
        return value
Example #30
0
    def _cache_support(self, expire_time, fragm_name, vary_on, lineno, caller):
        from hashlib import md5
        from django.core.cache import cache   # delay depending in settings
        from django.utils.http import urlquote

        try:
            expire_time = int(expire_time)
        except (ValueError, TypeError):
            raise TemplateSyntaxError('"%s" tag got a non-integer timeout '
                'value: %r' % (list(self.tags)[0], expire_time), lineno)

        args_string = u':'.join([urlquote(v) for v in vary_on])
        args_md5 = md5(args_string)
        cache_key = 'template.cache.%s.%s' % (fragm_name, args_md5.hexdigest())
        value = cache.get(cache_key)
        if value is None:
            value = caller()
            cache.set(cache_key, value, expire_time)
        return value