Coverage for flowr / cli / resolution.py: 100%
20 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-02 18:23 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-02 18:23 +0000
1"""Flow name resolution: maps short flow names to file paths.
3If the argument is an existing file path, return it directly.
4Otherwise, treat it as a flow name and search the configured
5flows directory for a matching .yaml file.
6"""
8from pathlib import Path
9from typing import Protocol
12class FlowNameNotFoundError(Exception):
13 """Raised when a flow name cannot be resolved to a file path."""
15 def __init__(self, flow_name: str, flows_dir: Path) -> None:
16 """Initialize with the unresolvable flow name and searched directory."""
17 self.flow_name = flow_name
18 self.flows_dir = flows_dir
19 super().__init__(f"Flow not found: '{flow_name}' (searched in {flows_dir})")
22class FlowNameResolver(Protocol):
23 """Resolve a flow name or file path to a valid flow file path.
25 If the argument is an existing file path, return it directly.
26 Otherwise, treat it as a flow name and search the configured
27 flows directory for a matching .yaml file.
28 """
30 def resolve(self, flow_arg: str, flows_dir: Path) -> Path: # pragma: no cover
31 """Resolve a flow argument to a file path.
33 Args:
34 flow_arg: A file path or short flow name.
35 flows_dir: The configured flows directory.
37 Returns:
38 The resolved Path to the flow YAML file.
40 Raises:
41 FlowNameNotFoundError: The argument is not an existing file
42 and no matching .yaml file exists in flows_dir.
43 """
44 ...
47class DefaultFlowNameResolver:
48 """Default implementation: file paths first, then name resolution."""
50 def resolve(self, flow_arg: str, flows_dir: Path) -> Path:
51 """Resolve a flow argument to a file path.
53 If flow_arg is an existing file path, return it directly
54 (backward compatible). Otherwise, treat it as a flow name
55 and look for {flows_dir}/{flow_name}.yaml.
57 Args:
58 flow_arg: A file path or short flow name.
59 flows_dir: The configured flows directory.
61 Returns:
62 The resolved Path to the flow YAML file.
64 Raises:
65 FlowNameNotFoundError: The argument is not an existing file
66 and no matching .yaml file exists in flows_dir.
67 """
68 path = Path(flow_arg)
69 if path.exists():
70 return path
72 name = flow_arg
73 if not name.endswith(".yaml"):
74 name = f"{name}.yaml"
76 resolved = flows_dir / name
77 if resolved.exists():
78 return resolved
80 raise FlowNameNotFoundError(flow_arg, flows_dir)