Skip to content

template

Classes:

Name Description
Template

Python f-string implementation with lazy and optional variable substitutions.

Attributes#

Classes#

Template #

Template(template: str | Path, regex: str | None = None)

Python f-string implementation with lazy and optional variable substitutions.

The template string is expected to be formatted in the same way as python f-strings, with variables that should be substituted wrapped in curly braces {}. Additionally, square brackets may be used around curly brackets and other text to mark that substitution as optional -- i.e. if the variable cannot be found then the text wrapped in the square brackets will be removed.

Examples:

`mapping = dict(a="x", b="y", c="z")`

`TemplateString("{a}.{b}{c}w").substitute(mapping) # -> "x.yzw"`

`TemplateString("{a}.{b}[.{c}]").substitute(mapping) # -> "x.y.z"`

`TemplateString("{a}.{b}.{d}").substitute(mapping)  # raises ValueError`

`TemplateString("{a}.{b}[.{d}]").substitute(mapping) # -> "x.y"`

`TemplateString("{a}.{b}.{d}").substitute(mapping, True) # -> "x.y.{d}"`

Parameters:

Name Type Description Default
template str | Path

The template string. Variables to substitute should be wrapped by curly braces {}.

required
regex str | None

A regex pattern used to extract the substitutions used to create a formatted string with this template. Generated automatically if not provided.

None

Methods:

Name Description
extract_substitutions

Extracts the substitutions used to create the provided formatted string.

substitute

Substitutes variables in a template string.

Attributes:

Name Type Description
chunks
regex
template
variables
Source code in tsdat/tstring/template.py
def __init__(self, template: str | Path, regex: str | None = None) -> None:
    _template = str(template)
    if not self._is_balanced(_template):
        raise ValueError(f"Unbalanced brackets in template string: '{template}'")
    self.template = _template
    self.chunks = self._get_chunks(_template)
    self.regex = regex or self._generate_regex(self.chunks)
    self.variables = tuple(
        chunk.var_name for chunk in self.chunks if chunk.var_name is not None
    )

Attributes#

chunks instance-attribute #
chunks = _get_chunks(_template)
regex instance-attribute #
regex = regex or _generate_regex(chunks)
template instance-attribute #
template = _template
variables instance-attribute #
variables = tuple(
    var_name for chunk in chunks if var_name is not None
)

Functions#

extract_substitutions #
extract_substitutions(
    formatted_str: str,
) -> dict[str, str] | None

Extracts the substitutions used to create the provided formatted string.

Note that this is not guaranteed to return accurate results if the template is constructed such that separators between variables are ambiguous.

Parameters:

Name Type Description Default
formatted_str str

The formatted string

required

Returns:

Type Description
dict[str, str] | None

dict[str, str]: A dictionary mapping each matched template variable to its value in the formatted string. Returns None if there are no matches.

Source code in tsdat/tstring/template.py
def extract_substitutions(self, formatted_str: str) -> dict[str, str] | None:
    """Extracts the substitutions used to create the provided formatted string.

    Note that this is not guaranteed to return accurate results if the template
    is constructed such that separators between variables are ambiguous.

    Args:
        formatted_str (str): The formatted string

    Returns:
        dict[str, str]: A dictionary mapping each matched template variable to its
            value in the formatted string. Returns None if there are no matches.
    """
    match = re.match(self.regex, formatted_str)
    if match:
        return match.groupdict()
    else:
        return None
substitute #
substitute(
    mapping: (
        Mapping[str, str | Callable[[], str] | None] | None
    ) = None,
    allow_missing: bool = False,
    fill: str | None = None,
    **kwds: str | Callable[[], str] | None
) -> str

Substitutes variables in a template string.

Parameters:

Name Type Description Default
mapping Mapping[str, str | Callable[[], str] | None] | None

A key-value pair of variable name to the value to replace it with. If the value is a string it is dropped-in directly. If it is a no-argument callable the return value of the callable is used. If it is None, then it is treated as missing and the action taken depends on the allow_missing parameter.

None
allow_missing bool

Allow variables outside of square brackets to be missing, in which case they are left as-is, including the curly brackets. This is intended to allow users to perform some variable substitutions before all variables in the mapping are known. Defaults to False.

False
fill str

Value to use to fill in missing substitutions (e.g., "*"). Only applied if 'allow_missing=True' (values in square brackets []). If None (the default) then no values will be filled.

None
**kwds str | Callable[[], str] | None

Optional extras to be merged into the mapping dict. If a keyword passed here has the same name as a key in the mapping dict, the value here would be used instead.

{}

Raises:

Type Description
ValueError

If any required substitutions cannot be made and fill is None.

Returns:

Name Type Description
str str

The template string with the appropriate substitutions made.

Source code in tsdat/tstring/template.py
def substitute(
    self,
    mapping: Mapping[str, str | Callable[[], str] | None] | None = None,
    allow_missing: bool = False,
    fill: str | None = None,
    **kwds: str | Callable[[], str] | None,
) -> str:
    """Substitutes variables in a template string.

    Args:
        mapping (Mapping[str, str | Callable[[], str] | None] | None): A key-value pair
            of variable name to the value to replace it with. If the value is a
            string it is dropped-in directly. If it is a no-argument callable the
            return value of the callable is used. If it is None, then it is treated
            as missing and the action taken depends on the `allow_missing` parameter.
        allow_missing (bool, optional): Allow variables outside of square brackets to be
            missing, in which case they are left as-is, including the curly brackets.
            This is intended to allow users to perform some variable substitutions
            before all variables in the mapping are known. Defaults to False.
        fill (str, optional): Value to use to fill in missing substitutions
            (e.g., "*"). Only applied if 'allow_missing=True' (values in square
            brackets []). If None (the default) then no values will be filled.
        **kwds (str | Callable[[], str] | None): Optional extras to be merged into the
            mapping dict. If a keyword passed here has the same name as a key in the
            mapping dict, the value here would be used instead.

    Raises:
        ValueError: If any required substitutions cannot be made and fill is None.

    Returns:
        str: The template string with the appropriate substitutions made.
    """
    if mapping is None:
        mapping = {}
    mapping = {**mapping, **kwds}
    mapping = {k: v for k, v in mapping.items() if v is not None}

    results: list[str] = []
    for chunk in self.chunks:
        results.append(
            chunk.sub(
                value=mapping.get(chunk.var_name)
                if chunk.var_name is not None
                else None,
                allow_missing=allow_missing,
                fill=fill,
            )
        )
    return "".join(results)