from pathlib import Path class WorkspacePathError(ValueError): pass def candidate_path(workspace: str, requested_path: str) -> Path: root = Path(workspace).resolve() path = Path(requested_path).expanduser() if path.is_absolute(): return path.resolve() return (root / path).resolve() def is_inside_workspace(workspace: str, path: Path) -> bool: root = Path(workspace).resolve() if root != path and root not in path.parents: return False return True def resolve_workspace_path( workspace: str, relative_path: str, allow_outside: bool = False ) -> Path: path = candidate_path(workspace, relative_path) if not allow_outside and not is_inside_workspace(workspace, path): raise WorkspacePathError(f"Path escapes workspace: {relative_path}") return path