diff --git a/src/gdb/tasks/layout.py b/src/gdb/tasks/layout.py index 7c07153..315cbde 100644 --- a/src/gdb/tasks/layout.py +++ b/src/gdb/tasks/layout.py @@ -575,31 +575,22 @@ def _resolve_layout2_manifest_path(self, data_root: Path) -> Optional[Path]: @staticmethod def _resolve_manifest_file_path(root: Path, value: Any) -> str: + # See ``_resolve_manifest_path`` for why we skip ``.resolve()``. raw = str(value or "").strip() if not raw: return "" if raw.startswith(("http://", "https://")): return raw - as_path = Path(raw) - if as_path.is_file(): - return str(as_path.resolve()) - candidate = (root / raw).resolve() - if candidate.is_file(): - return str(candidate) - return "" + candidate = Path(raw) if os.path.isabs(raw) else root / raw + return str(candidate) if candidate.is_file() else "" @staticmethod def _resolve_manifest_dir_path(root: Path, value: Any) -> str: raw = str(value or "").strip() if not raw: return "" - as_path = Path(raw) - if as_path.is_dir(): - return str(as_path.resolve()) - candidate = (root / raw).resolve() - if candidate.is_dir(): - return str(candidate) - return "" + candidate = Path(raw) if os.path.isabs(raw) else root / raw + return str(candidate) if candidate.is_dir() else "" def _compose_prompt(self, sample: Dict[str, Any]) -> str: lines = [ @@ -2881,13 +2872,15 @@ def _resolve_component_asset( value: Any, component_renders_dir: Path, ) -> str: + # See ``_resolve_manifest_path`` for why we skip ``.resolve()``. raw = str(value or "").strip() if not raw: return "" - as_path = Path(raw) - if as_path.is_file(): - return str(as_path.resolve()) + if os.path.isabs(raw): + as_path = Path(raw) + if as_path.is_file(): + return str(as_path) sample_dir = component_renders_dir / sample_id if raw.startswith(("http://", "https://")): @@ -2895,27 +2888,22 @@ def _resolve_component_asset( if filename: cached = sample_dir / filename if cached.is_file(): - return str(cached.resolve()) + return str(cached) return raw - if sample_dir.is_dir(): - candidate = sample_dir / raw - if candidate.is_file(): - return str(candidate.resolve()) - return "" + candidate = sample_dir / raw + return str(candidate) if candidate.is_file() else "" @staticmethod def _resolve_manifest_path(root: Path, value: Any) -> str: + # Hot path during load_data: ``.resolve()`` walks every path component + # with lstat to detect symlinks; the dataset has none, so we skip it + # in favour of a single ``is_file`` stat. raw = str(value or "").strip() if not raw: return "" - as_path = Path(raw) - if as_path.is_file(): - return str(as_path.resolve()) - candidate = (root / raw).resolve() - if candidate.is_file(): - return str(candidate) - return "" + candidate = Path(raw) if os.path.isabs(raw) else root / raw + return str(candidate) if candidate.is_file() else "" @classmethod def _strip_code_fence(cls, text: str) -> str: @@ -4270,15 +4258,13 @@ def _load_pair_side(self, side: Any, *, root: Path) -> Optional[Dict[str, Any]]: } def _resolve_component_render_dir(self, value: Any, *, root: Path, sample_id: str) -> Path: + # See ``_resolve_manifest_path`` for why we skip ``.resolve()``. raw = str(value or "").strip() if raw: - p = Path(raw) - if p.is_dir(): - return p.resolve() - candidate = (root / raw).resolve() + candidate = Path(raw) if os.path.isabs(raw) else root / raw if candidate.is_dir(): return candidate - return (root / "component_renders" / sample_id).resolve() + return root / "component_renders" / sample_id def _collect_component_assets(self, component_dir: Path, sample_id: str) -> List[str]: if not component_dir.is_dir():