diff --git a/reme4/steps/base_step.py b/reme4/steps/base_step.py index 54dbefe0..1d5764d7 100644 --- a/reme4/steps/base_step.py +++ b/reme4/steps/base_step.py @@ -87,24 +87,6 @@ class BaseStep(ABC): return Path.cwd() return Path(self.app_context.app_config.working_dir) - def resolve_path(self, raw: str) -> Path | None: - """Resolve a relative `path=` argument under self.working_path. - - Rules: - - the caller supplies the full relative path under ``self.working_path``; - absolute paths are rejected. - Returns ``(abs_path, None)`` on success, or ``(None, error_message)`` on failure. - Filetype-specific gating (e.g. markdown-only / suffix auto-append) is - layered on top by callers — see ``reme4/steps/crud/_file_io.py::gate_md``. - """ - if not raw or not str(raw).strip(): - return None, "`path` is required" - s = str(raw).strip() - p = Path(s) - if p.is_absolute(): - return None, (f"path {s!r} is absolute; only relative paths accepted") - return self.working_path / p, None - def _resolve( self, key: str, diff --git a/reme4/steps/crud/_file_io.py b/reme4/steps/crud/_file_io.py index bf61171a..4beaa35d 100644 --- a/reme4/steps/crud/_file_io.py +++ b/reme4/steps/crud/_file_io.py @@ -11,6 +11,26 @@ from ...utils import get_logger logger = get_logger() +def resolve_path(working_path: Path, raw: str) -> tuple[Path | None, str | None]: + """Resolve a relative `path=` argument under self.working_path. + + Rules: + - the caller supplies the full relative path under ``self.working_path``; + absolute paths are rejected. + Returns ``(abs_path, None)`` on success, or ``(None, error_message)`` on failure. + Filetype-specific gating (e.g. markdown-only / suffix auto-append) is + layered on top by callers — see ``reme4/steps/crud/_file_io.py::gate_md``. + """ + if not raw or not str(raw).strip(): + return None, "`path` is required" + s = str(raw).strip() + p = Path(s) + if p.is_absolute(): + logger.info("absolute path detected, recommmending relative paths") + return p, None + return working_path / p, None + + def gate_md(target: Path, raw: str) -> tuple[Path | None, str | None]: """Markdown-only gate: auto-append `.md` when no suffix; reject any non-`.md` suffix. diff --git a/reme4/steps/crud/read.py b/reme4/steps/crud/read.py index fc30bf10..55285efa 100644 --- a/reme4/steps/crud/read.py +++ b/reme4/steps/crud/read.py @@ -2,6 +2,7 @@ from ._file_io import ( gate_md, + resolve_path, read_file_safe, truncate_text_output, ) @@ -26,7 +27,7 @@ class ReadStep(BaseStep): start_line = self.context.get("start_line") end_line = self.context.get("end_line") - target, err = self.resolve_path(raw) + target, err = resolve_path(self.working_path, raw) if err: self._fail(err) return None