Skip to content

Commit 2504e51

Browse files
committed
test: improve path normalization tests with parametrize and edge cases
1 parent d21020a commit 2504e51

File tree

2 files changed

+39
-25
lines changed

2 files changed

+39
-25
lines changed

src/humanloop/path_utils.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33

44
def normalize_path(path: str, strip_extension: bool = False) -> str:
55
"""Normalize a path to the standard API format: path/to/resource, where resource can be a file or a directory."""
6-
# Remove leading/trailing slashes
7-
path_obj = Path(path.strip("/"))
6+
# Handle backslashes for Windows paths before passing to PurePosixPath
7+
# This is needed because some backslash sequences are treated as escape chars
8+
path = path.replace("\\", "/")
89

9-
# Handle extension
10+
# Use PurePosixPath to normalize the path (handles consecutive slashes)
11+
path_obj = Path(path)
12+
13+
# Strip extension if requested
1014
if strip_extension:
1115
path_obj = path_obj.with_suffix("")
1216

13-
# Convert path to string with forward slashes, regardless of OS
14-
# This ensures consistent path format (e.g., "path/to/resource") across Windows/Unix
15-
return path_obj.as_posix()
17+
# Convert to string and remove any leading/trailing slashes
18+
# We use the path as a string and not as_posix() since we've already normalized separators
19+
return str(path_obj).strip("/")
Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,38 @@
1+
import pytest
2+
13
from humanloop import path_utils
24

35

4-
def test_normalize_path():
5-
"""Test path normalization functionality."""
6-
# GIVEN various file paths with different formats
7-
test_cases = [
8-
# Input path, expected with strip_extension=False, expected with strip_extension=True
6+
@pytest.mark.parametrize(
7+
"input_path, expected_with_extension, expected_without_extension",
8+
[
9+
# Basic cases
910
("path/to/file.prompt", "path/to/file.prompt", "path/to/file"),
1011
("path\\to\\file.agent", "path/to/file.agent", "path/to/file"),
1112
("/leading/slashes/file.prompt", "leading/slashes/file.prompt", "leading/slashes/file"),
1213
("trailing/slashes/file.agent/", "trailing/slashes/file.agent", "trailing/slashes/file"),
1314
("multiple//slashes//file.prompt", "multiple/slashes/file.prompt", "multiple/slashes/file"),
14-
]
15-
16-
# Test with strip_extension=False (default)
17-
for input_path, expected_with_ext, _ in test_cases:
18-
# WHEN they are normalized without stripping extension
19-
normalized = path_utils.normalize_path(input_path, strip_extension=False)
20-
# THEN they should be converted to the expected format with extension
21-
assert normalized == expected_with_ext
15+
# Edge cases
16+
("path/to/file with spaces.prompt", "path/to/file with spaces.prompt", "path/to/file with spaces"),
17+
(
18+
"path/to/file\\with\\backslashes.prompt",
19+
"path/to/file/with/backslashes.prompt",
20+
"path/to/file/with/backslashes",
21+
),
22+
("path/to/unicode/文件.prompt", "path/to/unicode/文件.prompt", "path/to/unicode/文件"),
23+
(
24+
"path/to/special/chars/!@#$%^&*().prompt",
25+
"path/to/special/chars/!@#$%^&*().prompt",
26+
"path/to/special/chars/!@#$%^&*()",
27+
),
28+
],
29+
)
30+
def test_normalize_path(input_path, expected_with_extension, expected_without_extension):
31+
"""Test path normalization with various path formats."""
32+
# Test without stripping extension
33+
normalized = path_utils.normalize_path(input_path, strip_extension=False)
34+
assert normalized == expected_with_extension, f"Failed with strip_extension=False for '{input_path}'"
2235

23-
# Test with strip_extension=True
24-
for input_path, _, expected_without_ext in test_cases:
25-
# WHEN they are normalized with extension stripping
26-
normalized = path_utils.normalize_path(input_path, strip_extension=True)
27-
# THEN they should be converted to the expected format without extension
28-
assert normalized == expected_without_ext
36+
# Test with extension stripping
37+
normalized = path_utils.normalize_path(input_path, strip_extension=True)
38+
assert normalized == expected_without_extension, f"Failed with strip_extension=True for '{input_path}'"

0 commit comments

Comments
 (0)