Skip to content

Commit 844efc1

Browse files
authored
fix: escape directory to prevent \n on Windows directory name to fail on Pathlib + Tests (#4101)
* 📝 (utils.py): add format_directory_path function to properly escape and format directory paths for consistency and validity * ✨ (test_format_directory_path.py): add unit tests for the format_directory_path function to ensure correct formatting of directory paths 📝 (test_format_directory_path.py): add documentation and examples for different types of directory paths in the unit tests to improve code readability and maintainability * 🐛 (utils.py): fix the incorrect replacement of backslashes with newline characters in the format_directory_path function 📝 (test_rewrite_file_path.py): update test cases and function names to reflect the changes made in the format_directory_path function in utils.py * 🐛 (test_format_directory_path.py): update parameter name from 'path' to 'input_path' for clarity and consistency 📝 (test_format_directory_path.py): improve test case descriptions and handle newline characters in paths correctly
1 parent f5ffbc4 commit 844efc1

File tree

3 files changed

+86
-32
lines changed

3 files changed

+86
-32
lines changed

src/backend/base/langflow/base/data/utils.py

+13
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ def is_hidden(path: Path) -> bool:
4444
return path.name.startswith(".")
4545

4646

47+
def format_directory_path(path: str) -> str:
48+
"""Format a directory path to ensure it's properly escaped and valid.
49+
50+
Args:
51+
path (str): The input path string.
52+
53+
Returns:
54+
str: A properly formatted path string.
55+
"""
56+
return path.replace("\n", "\\n")
57+
58+
4759
def retrieve_file_paths(
4860
path: str,
4961
*,
@@ -52,6 +64,7 @@ def retrieve_file_paths(
5264
depth: int,
5365
types: list[str] = TEXT_FILE_TYPES,
5466
) -> list[str]:
67+
path = format_directory_path(path)
5568
path_obj = Path(path)
5669
if not path_obj.exists() or not path_obj.is_dir():
5770
msg = f"Path {path} must exist and be a directory."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import pytest
2+
from langflow.base.data.utils import format_directory_path
3+
4+
5+
@pytest.mark.parametrize(
6+
"input_path, expected",
7+
[
8+
# Test case 1: Standard path with no newlines (no change expected)
9+
("/home/user/documents/file.txt", "/home/user/documents/file.txt"),
10+
# Test case 2: Path with newline character (replace \n with \\n)
11+
("/home/user/docu\nments/file.txt", "/home/user/docu\\nments/file.txt"),
12+
# Test case 3: Path with multiple newline characters
13+
("/home/user/\ndocu\nments/file.txt", "/home/user/\\ndocu\\nments/file.txt"),
14+
# Test case 4: Path with only newline characters
15+
("\n\n\n", "\\n\\n\\n"),
16+
# Test case 5: Empty path (as per the original function, this remains an empty string)
17+
("", ""),
18+
# Test case 6: Path with mixed newlines and other special characters
19+
("/home/user/my-\ndocs/special_file!.pdf", "/home/user/my-\\ndocs/special_file!.pdf"),
20+
# Test case 7: Windows-style path with newline
21+
("C:\\Users\\\nDocuments\\file.txt", "C:\\Users\\\\nDocuments\\file.txt"), # No conversion of backslashes
22+
# Test case 8: Path with trailing newline
23+
("/home/user/documents/\n", "/home/user/documents/\\n"),
24+
# Test case 9: Path with leading newline
25+
("\n/home/user/documents/", "\\n/home/user/documents/"),
26+
# Test case 10: Path with multiple consecutive newlines
27+
("/home/user/docu\n\nments/file.txt", "/home/user/docu\\n\\nments/file.txt"),
28+
# Test case 11: Windows-style path (backslashes remain unchanged)
29+
("C:\\Users\\Documents\\file.txt", "C:\\Users\\Documents\\file.txt"),
30+
# Test case 12: Windows path with trailing backslash
31+
("C:\\Users\\Documents\\", "C:\\Users\\Documents\\"),
32+
# Test case 13: Mixed separators (leave as is)
33+
("C:/Users\\Documents/file.txt", "C:/Users\\Documents/file.txt"),
34+
# Test case 14: Network path (UNC) (leave backslashes as is)
35+
("\\\\server\\share\\file.txt", "\\\\server\\share\\file.txt"),
36+
],
37+
)
38+
def test_format_directory_path(input_path, expected):
39+
result = format_directory_path(input_path)
40+
assert result == expected
41+
42+
43+
# Additional test for type checking
44+
def test_format_directory_path_type():
45+
result = format_directory_path("/home/user/file.txt")
46+
assert isinstance(result, str)
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,38 @@
1-
from langflow.graph.utils import rewrite_file_path
1+
from langflow.base.data.utils import format_directory_path
22
import pytest
33

44

55
@pytest.mark.parametrize(
6-
"file_path, expected",
6+
"input_path, expected",
77
[
8-
# Test case 1: Standard path with multiple directories
9-
("/home/user/documents/file.txt", ["documents/file.txt"]),
10-
# Test case 2: Path with only one directory
11-
("/documents/file.txt", ["documents/file.txt"]),
12-
# Test case 3: Path with no directories (just filename)
13-
("file.txt", ["file.txt"]),
14-
# Test case 4: Path with multiple levels and special characters
15-
("/home/user/my-docs/special_file!.pdf", ["my-docs/special_file!.pdf"]),
16-
# Test case 5: Path with trailing slash
17-
("/home/user/documents/", ["user/documents"]),
18-
# Test case 6: Empty path
19-
("", [""]),
20-
# Test case 7: Path with only slashes
21-
("///", [""]),
22-
# Test case 8: Path with dots
23-
("/home/user/../documents/./file.txt", ["./file.txt"]),
24-
# Test case 9: Windows-style path
25-
("C:\\Users\\Documents\\file.txt", ["Documents/file.txt"]),
26-
# Test case 10: Windows path with trailing backslash
27-
("C:\\Users\\Documents\\", ["Users/Documents"]),
28-
# Test case 11: Mixed separators
29-
("C:/Users\\Documents/file.txt", ["Documents/file.txt"]),
30-
# Test case 12: Network path (UNC)
31-
("\\\\server\\share\\file.txt", ["share/file.txt"]),
8+
# Test case 1: Standard path with no newlines
9+
("/home/user/documents/file.txt", "/home/user/documents/file.txt"),
10+
# Test case 2: Path with newline character
11+
("/home/user/docu\nments/file.txt", "/home/user/docu\\nments/file.txt"),
12+
# Test case 3: Path with multiple newline characters
13+
("/home/user/\ndocu\nments/file.txt", "/home/user/\\ndocu\\nments/file.txt"),
14+
# Test case 4: Path with only newline characters
15+
("\n\n\n", "\\n\\n\\n"),
16+
# Test case 5: Empty path
17+
("", ""),
18+
# Test case 6: Path with mixed newlines and other special characters
19+
("/home/user/my-\ndocs/special_file!.pdf", "/home/user/my-\\ndocs/special_file!.pdf"),
20+
# Test case 7: Windows-style path with newline
21+
("C:\\Users\\\nDocuments\\file.txt", "C:\\Users\\\\nDocuments\\file.txt"),
22+
# Test case 8: Path with trailing newline
23+
("/home/user/documents/\n", "/home/user/documents/\\n"),
24+
# Test case 9: Path with leading newline
25+
("\n/home/user/documents/", "\\n/home/user/documents/"),
26+
# Test case 10: Path with multiple consecutive newlines
27+
("/home/user/docu\n\nments/file.txt", "/home/user/docu\\n\\nments/file.txt"),
3228
],
3329
)
34-
def test_rewrite_file_path(file_path, expected):
35-
result = rewrite_file_path(file_path)
30+
def test_format_directory_path(input_path, expected):
31+
result = format_directory_path(input_path)
3632
assert result == expected
3733

3834

3935
# Additional test for type checking
40-
def test_rewrite_file_path_type():
41-
result = rewrite_file_path("/home/user/file.txt")
42-
assert isinstance(result, list)
43-
assert all(isinstance(item, str) for item in result)
36+
def test_format_directory_path_type():
37+
result = format_directory_path("/home/user/file.txt")
38+
assert isinstance(result, str)

0 commit comments

Comments
 (0)