Skip to content

SOURCE CODE liquid.utils DOCS

"""Some utils"""
from os import PathLike
from typing import TYPE_CHECKING, Iterable, List, Union
from jinja2 import nodes
from jinja2.lexer import TOKEN_INTEGER, TOKEN_NAME
from jinja2.exceptions import TemplateSyntaxError

if TYPE_CHECKING:
    from jinja2.lexer import TokenStream, Token

PathType = Union[PathLike, str]
PathTypeOrIter = Union[PathType, Iterable[PathType]]


def peek_tokens(stream: "TokenStream", n: int = 1) -> List["Token"]:DOCS
    """Peek ahead 'n' tokens in the token stream, but don't move the cursor

    Args:
        stream: The token stream
        n: n tokens to look at

    Returns:
        List of n tokens ahead.
    """
    out = []
    pushes = []
    for _ in range(n):
        out.append(next(stream))
        pushes.append(stream.current)

    for token in pushes:
        stream.push(token)
    stream.current = out[0]
    return out


def parse_tag_args(DOCS
    stream: "TokenStream", name: str, lineno: int
) -> nodes.Node:
    """Parse arguments for a tag.

    Only integer and name are allowed as values

    Examples:
        >>> "{{tablerow product in products cols:2}}"
        >>> parse_tag_args(stream, "cols", lineno)
        >>> # returns nodes.Const(2)

    Args:
        stream: The token stream
        name: The name of the argument
        lineno: The lineno

    Returns:
        None if the argument is not pressent otherwise a Const or Name node
    """
    # use Parser.parse_primary?
    arg = stream.skip_if(f"name:{name}")
    if not arg:
        return None

    stream.expect("colon")
    # tokens_ahead = peek_tokens(stream)
    if not stream.current.test_any(TOKEN_INTEGER, TOKEN_NAME):
        raise TemplateSyntaxError(
            f"Expected an integer or a variable as argument for '{name}'.",
            lineno,
        )

    arg = next(stream)
    if arg.type is TOKEN_INTEGER:
        return nodes.Const(arg.value)
    return nodes.Name(arg.value, "load")