Skip to content

Commit 32f0b1b

Browse files
committed
feat: add path utils for centralized path validation
1 parent c0a200a commit 32f0b1b

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

src/humanloop/path_utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from pathlib import Path
2+
from typing import Optional
3+
4+
from humanloop.error import HumanloopRuntimeError
5+
6+
7+
def validate_no_extensions(path: str, allowed_extensions: Optional[list[str]] = None) -> str:
8+
"""Validates that path has no extensions (or only allowed ones) and returns path without extension."""
9+
if "." in path:
10+
parts = path.rsplit(".", 1)
11+
extension = parts[1] if len(parts) > 1 else ""
12+
path_without_extension = parts[0]
13+
14+
if allowed_extensions and extension in allowed_extensions:
15+
return path
16+
17+
raise HumanloopRuntimeError(
18+
f"Path '{path}' includes a file extension which is not supported in this context. "
19+
f"Use the format without extensions: '{path_without_extension}'."
20+
)
21+
return path
22+
23+
def validate_no_slashes(path: str) -> str:
24+
"""Validates that path has no leading/trailing slashes."""
25+
if path != path.strip("/"):
26+
raise HumanloopRuntimeError(
27+
f"Invalid path: '{path}'. Path should not contain leading/trailing slashes. "
28+
f"Valid example: 'path/to/resource'"
29+
)
30+
return path
31+
32+
def validate_not_absolute(path: str, base_dir: Optional[str] = None) -> str:
33+
"""Validates that path is not absolute."""
34+
if Path(path).is_absolute():
35+
message = f"Absolute paths are not supported: '{path}'."
36+
if base_dir:
37+
message += f" Paths should be relative to '{base_dir}'."
38+
raise HumanloopRuntimeError(message)
39+
return path

0 commit comments

Comments
 (0)