Source code for sparkle.instance

"""This package provides instance set support for Sparkle."""

from sparkle.instance.instances import (
    MultiFileInstanceSet,
    FileInstanceSet,
    IterableFileInstanceSet,
    InstanceSet,
)
from pathlib import Path


[docs] def Instance_Set(target: any) -> InstanceSet: """The combined interface for all instance set types.""" if ( isinstance(target, Path) and (target / MultiFileInstanceSet.instance_csv).exists() ) or ( isinstance(target, list) and isinstance(target[0], Path) and (target[0].parent / MultiFileInstanceSet.instance_csv).exists() ): return MultiFileInstanceSet(target) elif (not target.exists()) and ( target.parent / MultiFileInstanceSet.instance_csv ).exists(): # Single instance return MultiFileInstanceSet(target) elif ( isinstance(target, Path) and target.is_dir() and all( [ p.suffix in IterableFileInstanceSet.supported_filetypes for p in target.iterdir() ] ) ): return IterableFileInstanceSet(target) elif not target.exists(): # Resolve suffix alternatives = [p for p in target.parent.iterdir()] for alt in alternatives: if target.name == alt.stem: target = alt break return FileInstanceSet(target)
def resolve_instance_pair( instance_path: Path | list[Path], ) -> tuple[str, str] | list[tuple[str, str]]: """Resolve instance file path(s) to their canonical (set_name, instance_name) pairs. The inverse of resolve_instance_name, which maps a (set, instance) back to its path. The data frames are keyed by the pair, but the CLIs that write to them only receive file paths. The instance name cannot be derived from the path, because each InstanceSet subclass names its instances differently (FileInstanceSet uses the stem, IterableFileInstanceSet the full name with suffix, and MultiFileInstanceSet reads them from its instances.csv). Rather than guess, reconstruct the owning set from the parent directory and look each pair up by path, so the subclass supplies its own naming convention. Args: instance_path: A single instance file path, or a list of paths. Each path is resolved independently to its own pair. Returns: For a single Path, the (set_name, instance_name) pair. For a list of paths, the list of pairs, one per path, in the same order as the input. A pair falls back to (parent directory name, file stem) when the path matches no instance. """ single = isinstance(instance_path, Path) instance_paths = [instance_path] if single else instance_path instance_pairs = [] for path in instance_paths: target = path.resolve() # Instance_Set() picks the same subclass (file / iterable / multi-file) that was # used originally, so its instance_pairs carry the exact stored naming convention. instance_set = Instance_Set(path.parent) resolved_pair = next( ( pair for pair, pair_path in zip( instance_set.instance_pairs, instance_set.instance_paths ) # pair_path may be a list (multi-file instance), so normalise to a list. if target in [ file.resolve() for file in ( pair_path if isinstance(pair_path, list) else [pair_path] ) ] ), (path.parent.name, path.stem), ) instance_pairs.append(resolved_pair) # A single Path in yields its pair directly, a list yields a pair per path. return instance_pairs[0] if single else instance_pairs