Source code for erc7730.model.paths.path_ops

from typing import assert_never

from erc7730.model.paths import (
    ROOT_DATA_PATH,
    ContainerPath,
    DataPath,
    DataPathElement,
    DescriptorPath,
    DescriptorPathElement,
)


[docs] def descriptor_path_strip_prefix(path: DescriptorPath, prefix: DescriptorPath) -> DescriptorPath: """ Strip expected prefix from a descriptor path, raising an error if the prefix is not matching. :param path: path to strip :param prefix: prefix to strip :return: path without prefix :raises ValueError: if the path does not start with the prefix """ if len(path.elements) < len(prefix.elements): raise ValueError(f"Path {path} does not start with prefix {prefix}.") for i, element in enumerate(prefix.elements): if path.elements[i] != element: raise ValueError(f"Path {path} does not start with prefix {prefix}.") return DescriptorPath(elements=path.elements[len(prefix.elements) :])
[docs] def data_path_strip_prefix(path: DataPath, prefix: DataPath) -> DataPath: """ Strip expected prefix from a data path, raising an error if the prefix is not matching. :param path: path to strip :param prefix: prefix to strip :return: path without prefix :raises ValueError: if the path does not start with the prefix """ if path.absolute != prefix.absolute or len(path.elements) < len(prefix.elements): raise ValueError(f"Path {path} does not start with prefix {prefix}.") for i, element in enumerate(prefix.elements): if path.elements[i] != element: raise ValueError(f"Path {path} does not start with prefix {prefix}.") return DataPath(absolute=path.absolute, elements=path.elements[len(prefix.elements) :])
[docs] def descriptor_path_starts_with(path: DescriptorPath, prefix: DescriptorPath) -> bool: """ Check if descriptor path starts with a given prefix. :param path: path to inspect :param prefix: prefix to check :return: True if path starts with prefix """ try: descriptor_path_strip_prefix(path, prefix) return True except ValueError: return False
[docs] def data_path_starts_with(path: DataPath, prefix: DataPath) -> bool: """ Check if data path starts with a given prefix. :param path: path to inspect :param prefix: prefix to check :return: True if path starts with prefix """ try: data_path_strip_prefix(path, prefix) return True except ValueError: return False
[docs] def path_starts_with( path: DataPath | ContainerPath | DescriptorPath, prefix: DataPath | ContainerPath | DescriptorPath ) -> bool: """ Check if path starts with a given prefix. :param path: path to inspect :param prefix: prefix to check :return: True if path starts with prefix """ match (path, prefix): case (ContainerPath(), ContainerPath()): return path == prefix case (DataPath(), DataPath()): return data_path_starts_with(path, prefix) case (DescriptorPath(), DescriptorPath()): return descriptor_path_starts_with(path, prefix) case _: return False
[docs] def descriptor_path_ends_with(path: DescriptorPath, suffix: DescriptorPathElement) -> bool: """ Check if descriptor path ends with a given element. :param path: path to inspect :param suffix: suffix to check :return: True if path ends with suffix """ return path.elements[-1] == suffix
[docs] def data_path_ends_with(path: DataPath, suffix: DataPathElement) -> bool: """ Check if data path ends with a given element. :param path: path to inspect :param suffix: suffix to check :return: True if path ends with suffix """ if not path.elements: return False return path.elements[-1] == suffix
[docs] def data_path_concat(parent: DataPath | None, child: DataPath) -> DataPath: """ Concatenate two data paths. :param parent: parent path :param child: child path :return: concatenated path """ if parent is None or child.absolute: return child return DataPath(absolute=parent.absolute, elements=[*parent.elements, *child.elements])
[docs] def data_or_container_path_concat(parent: DataPath | None, child: DataPath | ContainerPath) -> DataPath | ContainerPath: """ Concatenate a data path with either another data path, or a container path. :param parent: parent path :param child: child path :return: concatenated path """ if parent is None: return child match child: case DataPath() as child: return data_path_concat(parent, child) case ContainerPath() as child: return child case _: assert_never(child)
[docs] def data_path_append(parent: DataPath, child: DataPathElement) -> DataPath: """ Append an element to a data path. :param parent: parent path :param child: element to append :return: concatenated path """ return parent.model_copy(update={"elements": [*parent.elements, child]})
[docs] def descriptor_path_append(parent: DescriptorPath, child: DescriptorPathElement) -> DescriptorPath: """ Append an element to a descriptor path. :param parent: parent path :param child: element to append :return: concatenated path """ return parent.model_copy(update={"elements": [*parent.elements, child]})
[docs] def to_absolute(path: DataPath | ContainerPath) -> DataPath | ContainerPath: """ Convert a path to an absolute path. :param path: data path :return: absolute path """ match path: case DataPath(): return data_path_concat(ROOT_DATA_PATH, path) case ContainerPath(): return path case _: assert_never(path)
[docs] def to_relative(path: DataPath | ContainerPath) -> DataPath | ContainerPath: """ Convert a path to a relative path. :param path: data path :return: absolute path """ match path: case DataPath(): return path.model_copy(update={"absolute": False}) case ContainerPath(): return path case _: assert_never(path)