Skip to content

utils

utils

Utilities for managing configuration.

build_config

build_config(user: MutableConfig, depth: int = 0) -> T.Any

Function to build a configuration from a user-provided toml configuration on top of the base/template one.

The templates can be further nested (this function is recursive) up to a maximum (non-configurable) depth of 10.

Source code in src/mapyde/utils.py
def build_config(user: MutableConfig, depth: int = 0) -> T.Any:
    """
    Function to build a configuration from a user-provided toml configuration on top of the base/template one.

    The templates can be further nested (this function is recursive) up to a maximum (non-configurable) depth of 10.

    """

    template_str = user.get("base", {}).pop(
        "template", str(prefix.templates / "defaults.toml")  # type: ignore[attr-defined]  # pylint: disable=no-member
    )
    parent = {}

    if template_str:
        if depth >= 10:
            msg = 'Maximum template depth (10) exceeded. This is likely due to your base template not having `"template" = false` set.'
            raise RuntimeError(msg)

        template_path = Path(render_string(template_str))

        with resources.as_file(template_path) as template:
            if not template.exists():
                msg = f"{template_path} does not exist."
                raise OSError(msg)
            parent = build_config(
                load_config(template.name, str(template.parent)), depth=depth + 1
            )

    variables = merge(parent, user)

    # only render the entire merged configuration, not the intermediate ones
    return (
        variables
        if depth
        else tomllib.loads(render_string(tomli_w.dumps(variables), variables))
    )

env_override

env_override(value: T.Any, key: str) -> T.Any

Helper function for jinja2 to override environment variables

Source code in src/mapyde/utils.py
def env_override(value: T.Any, key: str) -> T.Any:
    """
    Helper function for jinja2 to override environment variables
    """
    return os.getenv(key, value)

load_config

load_config(filename: str, cwd: str = '.') -> T.Any

Helper function to load a local toml configuration by filename

Source code in src/mapyde/utils.py
def load_config(filename: str, cwd: str = ".") -> T.Any:
    """
    Helper function to load a local toml configuration by filename
    """
    env = Environment(loader=FileSystemLoader(cwd))
    env.filters["env_override"] = env_override

    tpl = env.get_template(filename)
    assert tpl.filename
    with Path(tpl.filename).open("rb") as fpointer:
        return tomllib.load(fpointer)

merge

merge(left: MutableConfig, right: ImmutableConfig, path: list[str] | None = None) -> ImmutableConfig

merges right dictionary into left dictionary

Source code in src/mapyde/utils.py
def merge(
    left: MutableConfig, right: ImmutableConfig, path: list[str] | None = None
) -> ImmutableConfig:
    """
    merges right dictionary into left dictionary
    """
    if path is None:
        path = []
    for key in right:
        if key in left:
            if isinstance(left[key], dict) and isinstance(right[key], dict):
                merge(left[key], right[key], [*path, str(key)])
            else:
                left[key] = right[key]
        else:
            left[key] = right[key]
    return left

output_path

output_path(config: ImmutableConfig) -> Path

Return the output path from the config.

Source code in src/mapyde/utils.py
def output_path(config: ImmutableConfig) -> Path:
    """
    Return the output path from the config.
    """
    return Path(config["base"]["path"]).joinpath(config["base"]["output"]).resolve()

render_string

render_string(blob: str, variables: ImmutableConfig | None = None) -> str

Render a string using various variables set by the mapyde package.

Source code in src/mapyde/utils.py
def render_string(blob: str, variables: ImmutableConfig | None = None) -> str:
    """
    Render a string using various variables set by the mapyde package.
    """
    variables = variables or {}
    tpl = Template(blob)
    return tpl.render(
        PWD=Path(os.getenv("PWD", ".")).as_posix(),
        USER=os.getenv("USER", "USER"),
        MAPYDE_DATA=prefix.data.as_posix(),  # type: ignore[attr-defined]
        MAPYDE_CARDS=prefix.cards.as_posix(),  # type: ignore[attr-defined]  # pylint: disable=no-member
        MAPYDE_LIKELIHOODS=prefix.likelihoods.as_posix(),  # type: ignore[attr-defined]  # pylint: disable=no-member
        MAPYDE_SCRIPTS=prefix.scripts.as_posix(),  # type: ignore[attr-defined]  # pylint: disable=no-member
        MAPYDE_TEMPLATES=prefix.templates.as_posix(),  # type: ignore[attr-defined]  # pylint: disable=no-member
        **variables,
    )

slugify

slugify(value: str, allow_unicode: bool = False) -> str

Taken from django utils.

  • Convert to ASCII if allow_unicode is False.
  • Convert spaces or repeated dashes to single dashes.
  • Remove characters that aren't alphanumerics, underscores, or hyphens.
  • Convert to lowercase.
  • Also strip leading and trailing whitespace, dashes, and underscores.
Source code in src/mapyde/utils.py
def slugify(value: str, allow_unicode: bool = False) -> str:
    """
    Taken from [django utils](https://github.com/django/django/blob/master/django/utils/text.py).

    - Convert to ASCII if `allow_unicode` is False.
    - Convert spaces or repeated dashes to single dashes.
    - Remove characters that aren't alphanumerics, underscores, or hyphens.
    - Convert to lowercase.
    - Also strip leading and trailing whitespace, dashes, and underscores.
    """
    value = str(value)
    if allow_unicode:
        value = unicodedata.normalize("NFKC", value)
    else:
        value = (
            unicodedata.normalize("NFKD", value)
            .encode("ascii", "ignore")
            .decode("ascii")
        )
    value = re.sub(r"[^\w\s-]", "", value.lower())
    return re.sub(r"[-\s]+", "-", value).strip("-_")

Last update: June 15, 2023