Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
for tag_class in LIQUID_TAGS.values():
if tag_class in parser_class.__loaded_tags__:
continue
parser_class.__loaded_tags__.append(tag_class)
if tag_class.SYNTAX:
base_grammar.update(tag_class.SYNTAX)
if tag_class.TRANSFORMERS:
for transformer_func in tag_class.TRANSFORMERS:
# remove t_ prefix
transformer_name = transformer_func.__name__[2:]
setattr(transformer_class,
transformer_name,
transformer_func)
parser_class.TRANSFORMER = v_args(inline=True)(transformer_class)
return parser_class
return wrapper
def read_grammer_file(filename='grammer.lark'):
basepath = path.dirname(__file__)
grammer_filepath = path.abspath(path.join(basepath, filename))
with open(grammer_filepath) as f:
return f.read()
def init_parser():
grammer = read_grammer_file()
parser = Lark(grammer)
return parser
@v_args(inline=True)
class TreeToRequiresTransformer(Transformer, object):
def __init__(self, callables_dict, *args, **kwargs):
super(TreeToRequiresTransformer, self).__init__(*args, **kwargs)
self.function_whitelist_lookup = callables_dict
def var_expression(self, var):
return R(var.value)
def number_expression(self, var):
return float(var.value)
def func_expression(self, func):
return func
def string_expression(self, var):
def _override_tree_children(tree: "Tree", new_child: Any) -> "Tree":
"""
Replaces the children of a Tree instance with a single child.
:param tree: Tree instance to update
:param new_child: new single child of the tree
:type tree: Tree
:type new_child: Any
:return: the tree instance with its single child
:rtype: Tree
"""
tree.children = [new_child]
return tree
@v_args(tree=True)
class TokenTransformer(Transformer_InPlace):
"""
Lark transformer which is in charge of cleaning and casting miscellaneous
rules in order to be easily reused in NodeTransformer.
"""
def int_value(self, tree: "Tree") -> "Tree":
"""
Replaces the children of the tree with a custom INT_VALUE token and
casts the string value to an int value.
:param tree: the Tree instance to update
:type tree: Tree
:return: the three with its INT_VALUE token child
:rtype: Tree
"""
# pylint: disable=no-self-use
# common grammar file, used to import some common grammar rules
COMMON_GRAMMAR = str(Path(__file__)
.parent
.joinpath('tags', 'tags.lark')
.resolve())
def _load_grammar(str_grammar, path=COMMON_GRAMMAR):
"""Lark doesn't support customizing include paths
See: https://github.com/lark-parser/lark/issues/603
"""
grammar = StringIO(str_grammar)
grammar.name = path
return grammar
@v_args(inline=True)
class TagTransformer(LarkTransformer):
"""Base transformer class for the tag fragment parser
Note that the rules defined here are defined in the common grammar
For those defined for each tag, we need to write new handlers for them,
as well as those that we want to override here.
"""
def start(self, expr):
"""The start rule"""
return expr
def tags__var(self, varname):
"""The variables"""
return TagFragVar(varname)
class ASTSubscriptExpression(ASTNode):
_id = 'subscript_expr'
_props = ['addr', 'index']
class ASTLiteral(ASTNode):
_id = 'literal'
_props = ['value']
class ASTIdentifer(ASTNode):
_id = 'identifier'
_props = ['value']
@v_args(inline=True)
class ASTTransformer(Transformer):
def program(slf, *stmts):
return ASTProgram(stmts=stmts)
def block_stmt(slf, *body):
return ASTBlockStatement(body=list(body))
def assign_stmt(slf, target, op, expr):
return ASTAssignStatement(target=target, op=op, expr=expr)
def input_stmt(slf, dest):
return ASTInputStatement(dest=dest)
def output_stmt(slf, src):
return ASTOutputStatement(src=src)
"""Tag __OUTPUT__
{{x}}
{{x | filter}}
{{x | filter: args}}
"""
from lark import v_args
from ...tagmgr import register_tag
from ..tagparser import Tag, TagTransformer
@v_args(inline=True)
class TransformerOutput(TagTransformer):
"""Transformer for fragment parsing output tag"""
expr = TagTransformer.tags__expr
expr_filter = TagTransformer.tags__expr_filter
output = TagTransformer.tags__output
@register_tag('__OUTPUT__')
class TagOutput(Tag):
"""Class for if tag"""
VOID = True
SYNTAX = r"""
start: output
%import .tags (output, WS_INLINE)
%ignore WS_INLINE
?subatom: NAME -> var_name
| FLOAT -> float_literal
| INT -> int_literal
| "(" num_expr ")"
%import common.FLOAT
%import common.INT
%import common.WS_INLINE
%import common.CNAME -> NAME
%ignore WS_INLINE
""", start='expr')
@lark.v_args(inline=True)
class EvaluateTree(lark.Transformer):
from operator import not_, or_, and_, xor
from operator import eq, ne, le, ge, lt, gt
from operator import add, sub, mul, truediv, floordiv, neg, pos, inv, mod, pow, lshift, rshift
float_literal = float
int_literal = int
class Expressions(Transformation):
def __init__(self, output, masked=True):
self.output = output
self.masked = masked
def measurements(self, input_measurements):
parser = formula_parser()
TagFragGetAttr,
TagFragGetItem,
TagFragFilter,
TagFragOutput,
TagFragOpComparison,
)
from .tag import Tag, TagLiteral
from .tagmgr import get_tag, load_all_tags
from .config import LIQUID_LOG_INDENT
from .grammar import BASE_GRAMMAR
from .exceptions import (
TagUnclosed, EndTagUnexpected,
TagWrongPosition
)
@v_args(inline=True)
class TagFactory(Transformer):
"""Transformer for the parser"""
# Last literal tag or last compact mode
LAST_LITERAL_OR_COMPACT = None
def __init__(self, parser, base_level=0):
"""Construct. base_level is used for tags like liquid"""
super().__init__()
self.parser = parser
self.config = parser.config
self.stack = deque()
self.base_level = base_level
self.root = get_tag(
'ROOT', None, self._context(Diot(line=1, column=1))
)
if base_level == 0:
limit = args.get('limit', None)
if limit:
limit = limit.render(local_envs, global_envs)
offset = args.get('offset', None)
if offset:
offset = offset.render(local_envs, global_envs)
cols = args.get('cols', None)
if cols:
cols = cols.render(local_envs, global_envs)
return TablerowObject(str(itername), obj, limit, offset, cols)
@v_args(inline=True)
class TransformerTablerow(tagfor.TransformerFor):
"""Transformer for fragment parsing tablerow tag"""
def cols_arg(self, token):
return ('cols', token)
def iter(self, itername):
return itername
def tablerow_syntax(self, itername, expr, *args):
return TagFragTablerow(itername, expr, args)
@register_tag
class TagTablerow(Tag):
"""Class for if tag"""