Beispiel #1
0
    def preprocess(self, source, name, filename=None):
        ret_source = ''
        start_pos = 0

        while True:
            tag_match = begin_tag_m.search(source, start_pos)

            if tag_match:

                end_tag = end_tag_m.search(source, tag_match.end())

                if not end_tag:
                    raise TemplateSyntaxError(
                        'Expecting "endhaml" tag',
                        self._get_lineno(source[:start_pos]))

                haml_source = source[tag_match.end():end_tag.start()]

                h = self.get_preprocessor(self.environment.hamlish_mode)
                try:
                    ret_source += source[start_pos:tag_match.start(
                    )] + h.convert_source(haml_source)
                except TemplateIndentationError, e:
                    raise TemplateSyntaxError(e.message,
                                              e.lineno,
                                              name=name,
                                              filename=filename)
                except TemplateSyntaxError, e:
                    raise TemplateSyntaxError(e.message,
                                              e.lineno,
                                              name=name,
                                              filename=filename)

                start_pos = end_tag.end()
Beispiel #2
0
    def _parse_line(self, lineno, line):

        inline_data = None

        if self._has_inline_data(line):
            line, inline_data = self._parse_inline_data(line)

        if self._has_nested_tags(line):
            node = self._parse_nested_tags(lineno, line)
        else:
            node = self._parse_node(lineno, line)

        if inline_data is not None:

            if not node.can_have_children():
                raise TemplateSyntaxError('Node can\'t contain inline data',
                                          lineno)

            elif isinstance(node, NestedTags) and isinstance(
                    node.nodes[-1], TextNode):
                raise TemplateSyntaxError(
                    'TextNode can\'t contain inline data', lineno)

            return InlineData(node, inline_data)
        return node
Beispiel #3
0
    def preprocess(self, source, name, filename=None):
        ret_source = ''
        start_pos = 0

        while True:
            tag_match = begin_tag_m.search(source, start_pos)
            if tag_match:
                end_tag = end_tag_m.search(source, tag_match.end())
                if not end_tag:
                    raise TemplateSyntaxError(
                        'Expecting "endjade" tag',
                        self._get_lineno(source[:start_pos]))

                jade_source = source[tag_match.end():end_tag.start()]
                jade_source = convert(jade_source)

                try:
                    ret_source += source[start_pos:tag_match.start(
                    )] + jade_source
                except TemplateIndentationError as e:
                    raise TemplateSyntaxError(e.message,
                                              e.lineno,
                                              name=name,
                                              filename=filename)
                except TemplateSyntaxError as e:
                    raise TemplateSyntaxError(e.message,
                                              e.lineno,
                                              name=name,
                                              filename=filename)
                start_pos = end_tag.end()
            else:
                ret_source += source[start_pos:]
                break

        return ret_source
Beispiel #4
0
    def _cache_support(self, expire_time, fragm_name, vary_on, lineno,
                       cache_name, caller):
        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)

        if cache_name:
            try:
                cache = get_cache(cahe_name)
            except InvalidCacheBackendError:
                raise TemplateSyntaxError(
                    'Invalid cache name specified for cache tag: {}'.format(
                        cache_name))
        else:
            try:
                cache = get_cache('template_fragments')
            except InvalidCacheBackendError:
                cache = get_cache('default')

        cache_key = make_template_fragment_key(fragm_name, vary_on)

        value = cache.get(cache_key)
        if value is None:
            value = caller()
            cache.set(cache_key, force_text(value), expire_time)

        return value
Beispiel #5
0
    def _get_haml_tree(self, source):

        source_lines = self._get_source_lines(source)

        root = Node()

        # contains always atleast one element
        block_stack = [root]

        # stack for current indent level
        indent_stack = [-1]

        for lineno, line in enumerate(source_lines, 1):

            if not line.strip():
                block_stack[-1].add(EmptyLine())
                continue

            indent = 0
            m = re.match(r'^(\s+)', line)
            if m:
                indent = m.group(1)
                if ' ' in indent and '\t' in indent:
                    raise TemplateIndentationError('Mixed tabs and spaces',
                                                   lineno)
                indent = len(indent)

            if indent > indent_stack[-1]:
                indent_stack.append(indent)
            else:
                while indent < indent_stack[-1]:
                    indent_stack.pop()
                    block_stack.pop()
                block_stack.pop()

            if indent != indent_stack[-1]:
                raise TemplateIndentationError(
                    'Unindent does not match any outer indentation level',
                    lineno)

            node = self._parse_line(lineno, line.strip())

            if not block_stack[-1].can_have_children():

                if isinstance(node, InlineData):
                    raise TemplateSyntaxError(
                        'Inline Data Node can\'t contain child nodes', lineno)
                else:
                    raise TemplateSyntaxError(
                        'Self closing tag can\'t contain child nodes', lineno)

            block_stack[-1].add(node)
            block_stack.append(node)

        return root.children
Beispiel #6
0
    def parse_html_block(self, block, depth):

        m = re.match('^(\w+)(.*)$', block[1][1:])

        if m is None:
            raise TemplateSyntaxError(
                'Expected html tag, got "%s".' % block[1][1:], block[0])

        tag = m.group(1)
        attrs = m.group(2)

        data = ''
        if self.INLINE_DATA_SEP in attrs:
            attrs, data = attrs.split(self.INLINE_DATA_SEP, 1)

        if self.debug:
            self.output.newline()

        self.output.indent(depth)

        self_closing = False

        if attrs and attrs[-1] == self.SELF_CLOSING_TAG:
            attrs = attrs[:-1]
            self_closing = True
        elif tag in self.self_closing_html_tags:
            self_closing = True

        attrs = attrs.rstrip()

        if attrs and attrs[0] in (self.ID_SHORTCUT, self.CLASS_SHORTCUT):
            attrs = self._parse_shortcut_attributes(attrs)

        if self_closing and (data or block[2]):
            raise TemplateSyntaxError("Self closing tags can't have content",
                                      block[0])

        if self_closing:
            self.output.self_closing_html(tag, attrs)
        else:
            self.output.open_html(tag, attrs)

        if not self_closing and (data or not block[2]):
            if data:
                self.output.write(data)
            self.output.close_html(tag)

        if not self.debug:
            self.output.newline()

        self.create_output(block[2], depth + 1)

        if not data and not self_closing and block[2]:
            self._close_block(depth, lambda: self.output.close_html(tag))
Beispiel #7
0
    def preprocess(self, source, name, filename=None):
        if name is None or os.path.splitext(name)[1] not in \
            self.environment.hamlish_file_extensions:
            return source

        h = self.get_preprocessor(self.environment.hamlish_mode)
        try:
            return h.convert_source(source)
        except TemplateIndentationError as e:
            raise TemplateSyntaxError(e.message, e.lineno, name=name, filename=filename)
        except TemplateSyntaxError as e:
            raise TemplateSyntaxError(e.message, e.lineno, name=name, filename=filename)
Beispiel #8
0
  def parse(self, parser):
    lineno = next(parser.stream).lineno

    github_path = ''
    tag = None
    last_token_type = None
    for token in parser.stream:
      if last_token_type == lexer.TOKEN_NAME and token.value == 'tag':
        parser.stream.expect(lexer.TOKEN_COLON)
        tag = parser.stream.expect(lexer.TOKEN_NAME).value
        break
      github_path += token.value
      last_token_type = token.type

    m = self.github_path_re.match(github_path)
    if not m:
      raise TemplateSyntaxError(
          'Github file path must be in the format '
          '/<owner>/<repo>/blob/<branch>/<path>, '
          'found {}'.format(repr(github_path)),
          lineno, parser.name, parser.filename)

    owner, repo, branch, path = m.groups()
    call = self.call_method('_github_sample', [
        nodes.Const(owner),
        nodes.Const(repo),
        nodes.Const(branch),
        nodes.Const(path),
        nodes.Const(tag),
    ])
    return nodes.CallBlock(call, [], [], []).set_lineno(lineno)
Beispiel #9
0
    def _parse_html(self, lineno, line):

        m = re.match('^(\w+)(.*)$', line[1:])
        if m is None:
            raise TemplateSyntaxError('Expected html tag, got "%s".' % line,
                                      lineno)

        tag = m.group(1)
        attrs = m.group(2)

        self_closing = False
        if attrs and attrs[-1] == self.SELF_CLOSING_TAG:
            self_closing = True
            attrs = attrs[:-1].rstrip()
        elif tag in self._self_closing_html_tags:
            self_closing = True

        if attrs.startswith(self.ID_SHORTCUT) or \
            attrs.startswith(self.CLASS_SHORTCUT):

            attrs = self._parse_shortcut_attributes(attrs)

        if self_closing:
            return SelfClosingHTMLTag(tag, attrs)
        return HTMLTag(tag, attrs)
    def test_raises_templatesyntaxerror_exception(self, mock_logger):
        dg = DocumentGenerator(self.downloadable)
        dg.get_docx = MagicMock(side_effect=TemplateSyntaxError('', 0))

        with self.assertRaises(TemplateSyntaxError):
            dg.get_pdf()
            mock_logger.warning.assert_called()
Beispiel #11
0
class HamlishExtension(Extension):
    def __init__(self, environment):
        super(HamlishExtension, self).__init__(environment)

        environment.extend(hamlish_mode='compact',
                           hamlish_file_extensions=('.haml', ),
                           hamlish_indent_string='    ',
                           hamlish_newline_string='\n',
                           hamlish_debug=False,
                           hamlish_enable_div_shortcut=False,
                           hamlish_from_string=self._from_string)

    def preprocess(self, source, name, filename=None):
        if name is None or os.path.splitext(name)[1] not in \
            self.environment.hamlish_file_extensions:
            return source

        h = self.get_preprocessor(self.environment.hamlish_mode)
        try:
            return h.convert_source(source)
        except TemplateIndentationError, e:
            raise TemplateSyntaxError(e.message,
                                      e.lineno,
                                      name=name,
                                      filename=filename)
        except TemplateSyntaxError, e:
            raise TemplateSyntaxError(e.message,
                                      e.lineno,
                                      name=name,
                                      filename=filename)
Beispiel #12
0
def substitute_jinja2(text, substitutions, job=None, filename=None):
    """
	Use `jinja2` so apply formatting to a string.
	
	:param text: A string, like the contents of a file, in which substitutions should be applied.
	:param substitutions: Also called 'context', contains a mapping of things to replace.
	:return: Substituted string.
	"""
    try:
        from jinja2 import Template, __version__ as jinja_version
    except ImportError as err:
        raise ImportError('Jinja2 is set as the formatter, but '.format(err))
    if int(jinja_version.split('.')[1]) < 7:
        raise ImportError(
            'Jinja2 needs at least version 2.7, but you have {0:s}'.format(
                jinja_version))
    from jinja2 import TemplateSyntaxError

    try:
        template = Template(text,
                            undefined=StrictUndefined,
                            trim_blocks=True,
                            lstrip_blocks=True)
    except TemplateSyntaxError as err:
        raise TemplateSyntaxError('In file {0:s}: {1:}'.format(filename, err),
                                  err.lineno)
    return template.render(**substitutions)
Beispiel #13
0
 def fail(self, message):
     raise TemplateSyntaxError(
         message,
         self.token.lineno,
         self.stream.name,
         self.stream.filename,
     )
Beispiel #14
0
    def preprocess(self, source, name, filename=None):
        if not name or os.path.splitext(name)[1] not in self.HAML_EXTENSIONS:
            return source

        compiler = Compiler()
        try:
            return compiler.process(source)
        except Exception, e:
            raise TemplateSyntaxError(e, None, name=name, filename=filename)
Beispiel #15
0
 def test_template_syntax_error(self):
     with mock.patch("course.content.markup_to_html") as mock_mth:
         from jinja2 import TemplateSyntaxError
         mock_mth.side_effect = TemplateSyntaxError(lineno=10,
                                                    message=b"my error")
         resp = self.post_batch_issue_exam_ticket_view(
             data=self.get_post_data())
         self.assertEqual(resp.status_code, 200)
         self.assertEqual(ExamTicket.objects.count(), 0)
         self.assertAddMessageCallCount(1)
         self.assertAddMessageCalledWith("Template rendering failed")
Beispiel #16
0
    def parse_jinja_block(self, block, depth, continued_block=None):

        line = block[1][1:]

        m = re.match('^(\w+)(.*)$', line)
        if m is None:
            raise TemplateSyntaxError('Expected jinja tag, got "%s".' % line,
                                      block[0])

        name = m.group(1)

        if continued_block is not None:
            if name not in self.continued_jinja_tags:
                continued_block = self.close_continued_block(
                    continued_block, depth)

        if name in self.extended_jinja_tags:
            continued_block = name

        data = ''

        if self.INLINE_DATA_SEP in line:
            line, data = line.split(self.INLINE_DATA_SEP, 1)

        if self.debug:
            self.output.newline()

        self.output.indent(depth)
        self.output.open_jinja(name, line)

        if data:
            self.output.write(data)


        if name not in self.self_closing_jinja_tags and \
            continued_block is None and (data or not block[2]):
            self.output.close_jinja(name)

        if not self.debug:  # and block[2]:
            self.output.newline()

        self.create_output(block[2], depth + 1)

        if not data and name not in self.self_closing_jinja_tags and continued_block is None\
            and block[2]:
            self._close_block(depth, lambda: self.output.close_jinja(name))

        if name in self.extended_jinja_tags:
            return name

        return continued_block
Beispiel #17
0
    def parse(self, parser):
        tag = next(parser.stream)

        package_name = parser.parse_expression()
        if not package_name:
            raise TemplateSyntaxError("Bad package name", tag.lineno)

        args = [package_name]
        if tag.value == "stylesheet":
            return nodes.CallBlock(self.call_method('package_css', args), [], [], []).set_lineno(tag.lineno)

        if tag.value == "javascript":
            return nodes.CallBlock(self.call_method('package_js', args), [], [], []).set_lineno(tag.lineno)

        return []
Beispiel #18
0
    def _cache_support(self, expire_time, fragm_name, vary_on, lineno, caller):
        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 = make_template_fragment_key(fragm_name, vary_on)

        value = cache.get(cache_key)
        if value is None:
            value = caller()
            cache.set(cache_key, force_text(value), expire_time)

        return value
Beispiel #19
0
    def parse_experiment_enroll(self, parser):
        """Parse {% experiment_enroll ... %} tags"""

        lineno = parser.stream.current.lineno

        # list of nodes that will be used when calling the callback:
        args = []

        # parsing first parameter:
        experiment_name = parser.stream.current
        args.append(self._name_or_const(experiment_name))
        next(parser.stream)

        # parsing remaining parameters (the "alternatives"):
        alternatives = []
        while parser.stream.current.type != 'block_end':
            if self._token_as(parser):
                break
            alternatives.append(self._name_or_const(parser.stream.current))
            next(parser.stream)
        args.append(nodes.List(alternatives))

        # expecting `as` after the alternatives:
        if not self._token_as(parser):
            raise TemplateSyntaxError(
                'Syntax should be like: '
                '{% experiment_enroll "experiment_name"'
                ' "alternative1" "alternative2" ... as some_variable %}',
                lineno,
            )
        next(parser.stream)

        # parse what comes after `as`:
        target = parser.parse_assign_target()

        # We're done with parsing the tag.

        # we will also need the context in the callback:
        args.append(nodes.ContextReference())

        # create a callback node that will be executed on render:
        call_node = self.call_method('render_experiment_enroll',
                                     args,
                                     lineno=lineno)

        # return an assignment node that will trigger the callback:
        return nodes.Assign(target, call_node, lineno=lineno)
Beispiel #20
0
    def _parse_jinja(self, lineno, line):

        m = re.match('^(\w+)(.*)$', line[1:])
        if m is None:
            raise TemplateSyntaxError('Expected jinja tag, got "%s".' % line,
                                      lineno)

        tag = m.group(1)
        attrs = m.group(2)

        if tag in self._self_closing_jinja_tags:
            return SelfClosingJinjaTag(tag, attrs)

        elif tag in self._extended_tags:
            return ExtendingJinjaTag(tag, attrs)

        return JinjaTag(tag, attrs)
    def preprocess(self, source, name, filename=None):
        """Preprocesses the template from HAML to Jinja-style HTML."""

        if (not name or os.path.splitext(name)[1]
                not in self.environment.haml_file_extensions):
            return source

        try:
            renderer = Renderer(
                source,
                indent_string=self.environment.haml_indent_string,
                newline_string=self.environment.haml_newline_string)
        except TemplateSyntaxError, e:
            raise TemplateSyntaxError(e.message,
                                      e.lineno,
                                      name=name,
                                      filename=filename)
Beispiel #22
0
    def _parse_nested_tags(self, lineno, line):

        tags = line.split(self.NESTED_TAGS_SEP)

        nodes = []
        node_lines = [] #Used to make a nicer error message

        for line in [x.strip() for x in tags]:

            node = self._parse_node(lineno, line)

            if nodes and not nodes[-1].can_have_children():
                raise TemplateSyntaxError('Node "%s" can\'t contain children' % node_lines[-1], lineno)

            nodes.append(node)
            node_lines.append(line)

        return NestedTags(nodes)
Beispiel #23
0
    def parse_experiment(self, parser):
        """Parse {% experiment ... %} tags"""

        lineno = parser.stream.current.lineno

        # list of nodes that will be used when calling the callback:
        args = []

        # get tag parameters:
        while parser.stream.current.type != 'block_end':
            if parser.stream.skip_if('comma'):
                continue  # just ignore commas
            # {% experiment %} tag only accepts strings, i.e. Const:
            args.append(nodes.Const(parser.stream.current.value))
            next(parser.stream)

        # verify tag syntax:
        tokens = [nodes.Const('experiment')] + args
        try:
            _parse_token_contents(list(map(attrgetter('value'), tokens)))
        except ValueError:
            raise TemplateSyntaxError(
                "Syntax should be like: "
                "{% experiment experiment_name"
                " alternative [weight=val] [user=val] %}",
                lineno,
            )

        # fill in default values:
        while len(args) < 4:
            args.append(nodes.Const(None))

        # additional args:
        args.append(nodes.ContextReference())

        # parse the body of the block up to `endexperiment` and
        # drop the needle (which will always be `endexperiment`):
        body = parser.parse_statements(['name:endexperiment'],
                                       drop_needle=True)

        # Jinja2 callbacky nodey magic:
        call_node = self.call_method('render_experiment', args, lineno=lineno)
        return nodes.CallBlock(call_node, [], [], body).set_lineno(lineno)
Beispiel #24
0
    def _cache_support(self, expire_time, fragm_name, vary_on, lineno, caller):
        try:
            if expire_time is not None:
                expire_time = int(expire_time)
        except (ValueError, TypeError):
            raise TemplateSyntaxError(
                f'"{list(self.tags)[0]}" tag got a non-integer timeout value: {expire_time!r}',
                lineno,
            )

        cache_key = make_template_fragment_key(fragm_name, vary_on)

        value = cache.get(cache_key)
        if value is None:
            value = caller()
            cache.set(cache_key, force_str(value), expire_time)
        else:
            value = force_str(value)

        return value
Beispiel #25
0
    def parse_experiment_enrolled_alternative(self, parser):
        """
        Parse {% experiment_enrolled_alternative <experiment_name> %} tags
        """

        lineno = parser.stream.current.lineno

        # list of nodes that will be used when calling the callback:
        args = []

        # get experiment name from token
        experiment_name = parser.stream.current
        args.append(self._name_or_const(experiment_name))
        next(parser.stream)

        # we will also need the context in the callback:
        args.append(nodes.ContextReference())

        # expecting `as` after the alternatives:
        if not self._token_as(parser):
            raise TemplateSyntaxError(
                'Syntax should be like: '
                '{% experiment_enrolled_alternative "experiment_name"'
                ' as some_variable %}',
                lineno,
            )
        next(parser.stream)

        # parse what comes after `as`:
        target = parser.parse_assign_target()

        # create a callback node that will be executed on render:
        call_node = self.call_method('render_experiment_enrolled_alternative',
                                     args,
                                     lineno=lineno)

        # return an assignment node that will trigger the callback:
        return nodes.Assign(target, call_node, lineno=lineno)
Beispiel #26
0
class HamlishExtension(Extension):
    def __init__(self, environment):
        super(HamlishExtension, self).__init__(environment)

        environment.extend(
            hamlish_mode=getattr(settings, 'HAMLISH_MODE', 'compact'),
            hamlish_file_extensions=getattr(settings,
                                            'HAMLISH_FILE_EXTENSIONS',
                                            ('.haml', )),
            hamlish_indent_string=getattr(settings, 'HAMLISH_INDENT_STRING',
                                          ' '),
            hamlish_newline_string=getattr(settings, 'HAMLISH_NEWLINE_STRING',
                                           '\n'),
            hamlish_debug=getattr(settings, 'HAMLISH_DEBUG', False),
            hamlish_enable_div_shortcut=getattr(settings,
                                                'HAMLISH_ENABLE_DIV_SHORTCUT',
                                                True),
        )

    def preprocess(self, source, name, filename=None):
        if not os.path.splitext(name)[1] in \
            self.environment.hamlish_file_extensions:
            return source

        h = self.get_preprocessor(self.environment.hamlish_mode)
        try:
            return h.convert_source(source)
        except TemplateIndentationError, e:
            raise TemplateSyntaxError(e.message,
                                      e.lineno,
                                      name=name,
                                      filename=filename)
        except TemplateSyntaxError, e:
            raise TemplateSyntaxError(e.message,
                                      e.lineno,
                                      name=name,
                                      filename=filename)
 def test():
     raise TemplateSyntaxError('wtf', 42)
Beispiel #28
0
 def test_pickleable_syntax_error(self, fs_env):
     original = TemplateSyntaxError("bad template", 42, "test", "test.txt")
     unpickled = pickle.loads(pickle.dumps(original))
     assert str(original) == str(unpickled)
     assert original.name == unpickled.name
Beispiel #29
0
def _embed_extension_parse(self, open_token_condition, close_token_condition,
                           parser):
    args = [
        nodes.ContextReference(),
        nodes.Const(parser.filename),
        nodes.Const(parser.stream.current.lineno)
    ]
    kwargs = {}
    name_token = parser.stream.expect(open_token_condition)
    automata_state = AutomataState.Expect_Name
    content_path = None

    while parser.stream.current.type != TOKEN_BLOCK_END:
        if automata_state == AutomataState.Expect_Name:
            name_token = parser.stream.expect(TOKEN_NAME)
            automata_state = AutomataState.Expect_Assign
        elif automata_state == AutomataState.Expect_Assign:
            parser.stream.skip_if(TOKEN_ASSIGN)
            automata_state = AutomataState.Expect_Value
        elif automata_state == AutomataState.Expect_Value:
            value_token = parser.stream.next_if(TOKEN_FLOAT)

            if value_token:
                kwargs[name_token.value] = value_token.value
            else:
                value_token = parser.stream.next_if(TOKEN_INTEGER)

                if value_token:
                    kwargs[name_token.value] = value_token.value
                else:
                    value_token = parser.stream.expect(TOKEN_STRING)

                    if name_token.value == 'absolute_path':
                        content_path = normpath(
                            abspath(
                                join(parser.environment.globals['source_path'],
                                     value_token.value)))
                    elif name_token.value == 'relative_path':
                        content_path = normpath(
                            abspath(
                                join(dirname(parser.filename),
                                     value_token.value)))
                    else:
                        kwargs[name_token.value] = value_token.value

            automata_state = AutomataState.Expect_Comma
        elif automata_state == AutomataState.Expect_Comma:
            parser.stream.skip_if(TOKEN_COMMA)
            automata_state = AutomataState.Expect_Name

    lineno = parser.stream.current.lineno

    if content_path is not None:
        if not isfile(content_path):
            raise TemplateSyntaxError(
                f'Cannot find content file "{content_path}".', lineno,
                parser.filename)

        kwargs['content_path'] = content_path
        body = []
    else:
        body = parser.parse_statements([close_token_condition],
                                       drop_needle=True)

    return nodes.CallBlock(
        self.call_method('_process_markup', args, [
            nodes.Keyword(name, nodes.Const(value))
            for name, value in kwargs.items()
        ]), [], [], body).set_lineno(lineno)
Beispiel #30
0
 def test():
     raise TemplateSyntaxError("wtf", 42)