Source code for pythia.utils.ext

"""Python extensions and decorators."""

from __future__ import annotations

import importlib.util
import platform
import sys
from importlib import import_module
from pathlib import Path
from types import ModuleType
from typing import Any
from typing import Iterable
from typing import Optional
from typing import Tuple
from typing import TypeVar

RT = TypeVar("RT", Path, None)  # return type
T = TypeVar("T")


[docs]def not_empty(path: Path) -> Path: """Raise if receives an empty value. Args: path: The file to check for emptiness. Returns: The decorated function. Raises: EOFError: The received file is empty. """ if path is None: return path if not path.stat().st_size: raise EOFError(f"File {path} is empty") return path
[docs]def not_none(value: Optional[Any]): """Raise if receives `None`. Args: value: The value which should not be none. Returns: The received value. Raises: ValueError: The received value was `None`. """ if value is None: raise ValueError("Received disallowed `None`") return value
[docs]def get_arch() -> str: """Return system arch. Returns: platform, like `uname machine`. """ return platform.uname()[4]
[docs]def import_from_path(name: str, path: str | Path) -> ModuleType: """Import a module from a filepath. Args: name: the name to use for the module when importing. path: path to the python file to import as a module. Returns: The imported module. Raises: ImportError: unable to get spec from location See Also: `importlib.util.spec_from_file_location` """ spec = importlib.util.spec_from_file_location(name, str(path)) if not spec or not spec.loader: raise ImportError(f"Failed to import from {path=}") module = importlib.util.module_from_spec(spec) sys.modules[name] = module spec.loader.exec_module(module) return module
[docs]def import_from_str(module: str, *, name=None, suffix: str = "") -> ModuleType: """Import python file as a module or from its path. Args: module: name of the python file to import. name: ``__name__`` to use when import thing the module. If not set, defaults to the file's stem. suffix: file suffix. If set, load `name` as a file. Otherwise, Returns: The improted module. """ if suffix: path = Path(module).with_suffix(suffix) return import_from_path(name or path.stem, path) return import_module(module)
[docs]def grouped(iterable: Iterable[T], size=2) -> Iterable[Tuple[T, ...]]: """Iterate by groups. Args: iterable: container for the data to group by. size: size of the groups Returns: zip containing tuples of values. Example: >>> [*grouped(range(10),3)] [(0, 1, 2), (3, 4, 5), (6, 7, 8)] """ return zip(*[iter(iterable)] * size)
[docs]def remove_suffix(input_string: str, suffix: str) -> str: """Remove trailing substring. Args: input_string: Input string to look for the suffix. suffix: The substring to match at the end of the input string. Returns: If the string ends with the suffix string and that suffix is not empty, return string[:-len(suffix)]. Otherwise, return a copy of the original string Backport of stdlib@3.9 """ if suffix and input_string.endswith(suffix): return input_string[: -len(suffix)] return input_string
[docs]def remove_prefix(input_string: str, prefix: str) -> str: """Remove leading substring. Args: input_string: Input string to look for the suffix. prefix: The substring to match at the start of the input string. Returns: If the string ends with the suffix string and that suffix is not empty, return string[:-len(suffix)]. Otherwise, return a copy of the original string Backport of stdlib@3.9 """ if prefix and input_string.startswith(prefix): return input_string[len(prefix) :] return input_string
IS_JETSON = get_arch() == "aarch64"