mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-04-09 12:54:17 +00:00
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
72ad6dc953
commit
f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions
|
|
@ -1,22 +1,20 @@
|
|||
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
|
||||
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
|
||||
|
||||
"""A simple Python template renderer, for a nano-subset of Django syntax.
|
||||
|
||||
For a detailed discussion of this code, see this chapter from 500 Lines:
|
||||
http://aosabook.org/en/500L/a-template-engine.html
|
||||
|
||||
"""
|
||||
|
||||
# Coincidentally named the same as http://code.activestate.com/recipes/496702/
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
from typing import (
|
||||
Any, Callable, Dict, NoReturn, cast,
|
||||
)
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import cast
|
||||
from typing import Dict
|
||||
from typing import NoReturn
|
||||
|
||||
|
||||
class TempliteSyntaxError(ValueError):
|
||||
|
|
@ -37,7 +35,7 @@ class CodeBuilder:
|
|||
self.indent_level = indent
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "".join(str(c) for c in self.code)
|
||||
return ''.join(str(c) for c in self.code)
|
||||
|
||||
def add_line(self, line: str) -> None:
|
||||
"""Add a line of source to the code.
|
||||
|
|
@ -45,7 +43,7 @@ class CodeBuilder:
|
|||
Indentation and newline will be added for you, don't provide them.
|
||||
|
||||
"""
|
||||
self.code.extend([" " * self.indent_level, line, "\n"])
|
||||
self.code.extend([' ' * self.indent_level, line, '\n'])
|
||||
|
||||
def add_section(self) -> CodeBuilder:
|
||||
"""Add a section, a sub-CodeBuilder."""
|
||||
|
|
@ -117,6 +115,7 @@ class Templite:
|
|||
})
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, text: str, *contexts: dict[str, Any]) -> None:
|
||||
"""Construct a Templite with the given `text`.
|
||||
|
||||
|
|
@ -135,82 +134,82 @@ class Templite:
|
|||
# it, and execute it to render the template.
|
||||
code = CodeBuilder()
|
||||
|
||||
code.add_line("def render_function(context, do_dots):")
|
||||
code.add_line('def render_function(context, do_dots):')
|
||||
code.indent()
|
||||
vars_code = code.add_section()
|
||||
code.add_line("result = []")
|
||||
code.add_line("append_result = result.append")
|
||||
code.add_line("extend_result = result.extend")
|
||||
code.add_line("to_str = str")
|
||||
code.add_line('result = []')
|
||||
code.add_line('append_result = result.append')
|
||||
code.add_line('extend_result = result.extend')
|
||||
code.add_line('to_str = str')
|
||||
|
||||
buffered: list[str] = []
|
||||
|
||||
def flush_output() -> None:
|
||||
"""Force `buffered` to the code builder."""
|
||||
if len(buffered) == 1:
|
||||
code.add_line("append_result(%s)" % buffered[0])
|
||||
code.add_line('append_result(%s)' % buffered[0])
|
||||
elif len(buffered) > 1:
|
||||
code.add_line("extend_result([%s])" % ", ".join(buffered))
|
||||
code.add_line('extend_result([%s])' % ', '.join(buffered))
|
||||
del buffered[:]
|
||||
|
||||
ops_stack = []
|
||||
|
||||
# Split the text to form a list of tokens.
|
||||
tokens = re.split(r"(?s)({{.*?}}|{%.*?%}|{#.*?#})", text)
|
||||
tokens = re.split(r'(?s)({{.*?}}|{%.*?%}|{#.*?#})', text)
|
||||
|
||||
squash = in_joined = False
|
||||
|
||||
for token in tokens:
|
||||
if token.startswith("{"):
|
||||
if token.startswith('{'):
|
||||
start, end = 2, -2
|
||||
squash = (token[-3] == "-")
|
||||
squash = (token[-3] == '-')
|
||||
if squash:
|
||||
end = -3
|
||||
|
||||
if token.startswith("{#"):
|
||||
if token.startswith('{#'):
|
||||
# Comment: ignore it and move on.
|
||||
continue
|
||||
elif token.startswith("{{"):
|
||||
elif token.startswith('{{'):
|
||||
# An expression to evaluate.
|
||||
expr = self._expr_code(token[start:end].strip())
|
||||
buffered.append("to_str(%s)" % expr)
|
||||
buffered.append('to_str(%s)' % expr)
|
||||
else:
|
||||
# token.startswith("{%")
|
||||
# Action tag: split into words and parse further.
|
||||
flush_output()
|
||||
|
||||
words = token[start:end].strip().split()
|
||||
if words[0] == "if":
|
||||
if words[0] == 'if':
|
||||
# An if statement: evaluate the expression to determine if.
|
||||
if len(words) != 2:
|
||||
self._syntax_error("Don't understand if", token)
|
||||
ops_stack.append("if")
|
||||
code.add_line("if %s:" % self._expr_code(words[1]))
|
||||
ops_stack.append('if')
|
||||
code.add_line('if %s:' % self._expr_code(words[1]))
|
||||
code.indent()
|
||||
elif words[0] == "for":
|
||||
elif words[0] == 'for':
|
||||
# A loop: iterate over expression result.
|
||||
if len(words) != 4 or words[2] != "in":
|
||||
if len(words) != 4 or words[2] != 'in':
|
||||
self._syntax_error("Don't understand for", token)
|
||||
ops_stack.append("for")
|
||||
ops_stack.append('for')
|
||||
self._variable(words[1], self.loop_vars)
|
||||
code.add_line(
|
||||
f"for c_{words[1]} in {self._expr_code(words[3])}:",
|
||||
f'for c_{words[1]} in {self._expr_code(words[3])}:',
|
||||
)
|
||||
code.indent()
|
||||
elif words[0] == "joined":
|
||||
ops_stack.append("joined")
|
||||
elif words[0] == 'joined':
|
||||
ops_stack.append('joined')
|
||||
in_joined = True
|
||||
elif words[0].startswith("end"):
|
||||
elif words[0].startswith('end'):
|
||||
# Endsomething. Pop the ops stack.
|
||||
if len(words) != 1:
|
||||
self._syntax_error("Don't understand end", token)
|
||||
end_what = words[0][3:]
|
||||
if not ops_stack:
|
||||
self._syntax_error("Too many ends", token)
|
||||
self._syntax_error('Too many ends', token)
|
||||
start_what = ops_stack.pop()
|
||||
if start_what != end_what:
|
||||
self._syntax_error("Mismatched end tag", end_what)
|
||||
if end_what == "joined":
|
||||
self._syntax_error('Mismatched end tag', end_what)
|
||||
if end_what == 'joined':
|
||||
in_joined = False
|
||||
else:
|
||||
code.dedent()
|
||||
|
|
@ -219,19 +218,19 @@ class Templite:
|
|||
else:
|
||||
# Literal content. If it isn't empty, output it.
|
||||
if in_joined:
|
||||
token = re.sub(r"\s*\n\s*", "", token.strip())
|
||||
token = re.sub(r'\s*\n\s*', '', token.strip())
|
||||
elif squash:
|
||||
token = token.lstrip()
|
||||
if token:
|
||||
buffered.append(repr(token))
|
||||
|
||||
if ops_stack:
|
||||
self._syntax_error("Unmatched action tag", ops_stack[-1])
|
||||
self._syntax_error('Unmatched action tag', ops_stack[-1])
|
||||
|
||||
flush_output()
|
||||
|
||||
for var_name in self.all_vars - self.loop_vars:
|
||||
vars_code.add_line(f"c_{var_name} = context[{var_name!r}]")
|
||||
vars_code.add_line(f'c_{var_name} = context[{var_name!r}]')
|
||||
|
||||
code.add_line("return ''.join(result)")
|
||||
code.dedent()
|
||||
|
|
@ -240,30 +239,30 @@ class Templite:
|
|||
[Dict[str, Any], Callable[..., Any]],
|
||||
str,
|
||||
],
|
||||
code.get_globals()["render_function"],
|
||||
code.get_globals()['render_function'],
|
||||
)
|
||||
|
||||
def _expr_code(self, expr: str) -> str:
|
||||
"""Generate a Python expression for `expr`."""
|
||||
if "|" in expr:
|
||||
pipes = expr.split("|")
|
||||
if '|' in expr:
|
||||
pipes = expr.split('|')
|
||||
code = self._expr_code(pipes[0])
|
||||
for func in pipes[1:]:
|
||||
self._variable(func, self.all_vars)
|
||||
code = f"c_{func}({code})"
|
||||
elif "." in expr:
|
||||
dots = expr.split(".")
|
||||
code = f'c_{func}({code})'
|
||||
elif '.' in expr:
|
||||
dots = expr.split('.')
|
||||
code = self._expr_code(dots[0])
|
||||
args = ", ".join(repr(d) for d in dots[1:])
|
||||
code = f"do_dots({code}, {args})"
|
||||
args = ', '.join(repr(d) for d in dots[1:])
|
||||
code = f'do_dots({code}, {args})'
|
||||
else:
|
||||
self._variable(expr, self.all_vars)
|
||||
code = "c_%s" % expr
|
||||
code = 'c_%s' % expr
|
||||
return code
|
||||
|
||||
def _syntax_error(self, msg: str, thing: Any) -> NoReturn:
|
||||
"""Raise a syntax error using `msg`, and showing `thing`."""
|
||||
raise TempliteSyntaxError(f"{msg}: {thing!r}")
|
||||
raise TempliteSyntaxError(f'{msg}: {thing!r}')
|
||||
|
||||
def _variable(self, name: str, vars_set: set[str]) -> None:
|
||||
"""Track that `name` is used as a variable.
|
||||
|
|
@ -273,8 +272,8 @@ class Templite:
|
|||
Raises an syntax error if `name` is not a valid name.
|
||||
|
||||
"""
|
||||
if not re.match(r"[_a-zA-Z][_a-zA-Z0-9]*$", name):
|
||||
self._syntax_error("Not a valid name", name)
|
||||
if not re.match(r'[_a-zA-Z][_a-zA-Z0-9]*$', name):
|
||||
self._syntax_error('Not a valid name', name)
|
||||
vars_set.add(name)
|
||||
|
||||
def render(self, context: dict[str, Any] | None = None) -> str:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue