Source code for snakemake.ioutils.subpath

import os
from pathlib import Path
from typing import Callable, Optional, Union

from snakemake.common import get_function_params, overwrite_function_params
from snakemake.io import is_callable


[docs] def subpath( path_or_func: Union[Callable, str, Path], strip_suffix: Optional[str] = None, basename: bool = False, parent: bool = False, ancestor: Optional[int] = None, ): """Return the subpath of a given path. Args: path_or_func: A string, pathlib.Path, or a function returning a string or pathlib.Path. strip_suffix: If given, strip the suffix from the path. basename: If True, return the basename of the path (cannot be used together with parent or ancestor). parent: If True, return the parent directory of the path (cannot be used together with ancestor). ancestor: If given, return the ancestor directory of the path (cannot be used together with parent). """ # TODO typecheck arguments, maybe find a decorator for that purpose def do(path): if isinstance(path, Path): path = str(path) if not isinstance(path, str): raise ValueError( "Value passed to subpath " "must be a single string or pathlib.Path (or a function returning those). " f"Obtained value: {repr(path)}" ) if strip_suffix is not None: if not path.endswith(strip_suffix): raise ValueError( f"Path {path} does not end with the specified suffix {strip_suffix}" ) path = path[: -len(strip_suffix)] if basename: if parent or ancestor is not None: raise ValueError( "basename cannot be used together with parent or ancestor" ) path = os.path.basename(path) elif parent: if ancestor is not None: raise ValueError("parent cannot be used together with ancestor") path = os.path.dirname(path) if path == "": path = "." elif ancestor is not None: if ancestor < 1: raise ValueError("ancestor must be greater than 0") for _ in range(ancestor): path = os.path.dirname(path) if path == "": path = "." break return path if is_callable(path_or_func): params = get_function_params(path_or_func) def inner(wildcards, **args): value = path_or_func(wildcards, **args) return do(value) overwrite_function_params(inner, params) return inner else: return do(path_or_func)