Skip to content

Commit

Permalink
fix: escape directory to prevent \n on Windows directory name to fail…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
Cristhianzl authored Oct 14, 2024
1 parent f5ffbc4 commit 844efc1
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 32 deletions.
13 changes: 13 additions & 0 deletions src/backend/base/langflow/base/data/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ def is_hidden(path: Path) -> bool:
return path.name.startswith(".")


def format_directory_path(path: str) -> str:
"""Format a directory path to ensure it's properly escaped and valid.
Args:
path (str): The input path string.
Returns:
str: A properly formatted path string.
"""
return path.replace("\n", "\\n")


def retrieve_file_paths(
path: str,
*,
Expand All @@ -52,6 +64,7 @@ def retrieve_file_paths(
depth: int,
types: list[str] = TEXT_FILE_TYPES,
) -> list[str]:
path = format_directory_path(path)
path_obj = Path(path)
if not path_obj.exists() or not path_obj.is_dir():
msg = f"Path {path} must exist and be a directory."
Expand Down
46 changes: 46 additions & 0 deletions src/backend/tests/unit/utils/test_format_directory_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import pytest
from langflow.base.data.utils import format_directory_path


@pytest.mark.parametrize(
"input_path, expected",
[
# Test case 1: Standard path with no newlines (no change expected)
("/home/user/documents/file.txt", "/home/user/documents/file.txt"),
# Test case 2: Path with newline character (replace \n with \\n)
("/home/user/docu\nments/file.txt", "/home/user/docu\\nments/file.txt"),
# Test case 3: Path with multiple newline characters
("/home/user/\ndocu\nments/file.txt", "/home/user/\\ndocu\\nments/file.txt"),
# Test case 4: Path with only newline characters
("\n\n\n", "\\n\\n\\n"),
# Test case 5: Empty path (as per the original function, this remains an empty string)
("", ""),
# Test case 6: Path with mixed newlines and other special characters
("/home/user/my-\ndocs/special_file!.pdf", "/home/user/my-\\ndocs/special_file!.pdf"),
# Test case 7: Windows-style path with newline
("C:\\Users\\\nDocuments\\file.txt", "C:\\Users\\\\nDocuments\\file.txt"), # No conversion of backslashes
# Test case 8: Path with trailing newline
("/home/user/documents/\n", "/home/user/documents/\\n"),
# Test case 9: Path with leading newline
("\n/home/user/documents/", "\\n/home/user/documents/"),
# Test case 10: Path with multiple consecutive newlines
("/home/user/docu\n\nments/file.txt", "/home/user/docu\\n\\nments/file.txt"),
# Test case 11: Windows-style path (backslashes remain unchanged)
("C:\\Users\\Documents\\file.txt", "C:\\Users\\Documents\\file.txt"),
# Test case 12: Windows path with trailing backslash
("C:\\Users\\Documents\\", "C:\\Users\\Documents\\"),
# Test case 13: Mixed separators (leave as is)
("C:/Users\\Documents/file.txt", "C:/Users\\Documents/file.txt"),
# Test case 14: Network path (UNC) (leave backslashes as is)
("\\\\server\\share\\file.txt", "\\\\server\\share\\file.txt"),
],
)
def test_format_directory_path(input_path, expected):
result = format_directory_path(input_path)
assert result == expected


# Additional test for type checking
def test_format_directory_path_type():
result = format_directory_path("/home/user/file.txt")
assert isinstance(result, str)
59 changes: 27 additions & 32 deletions src/backend/tests/unit/utils/test_rewrite_file_path.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,38 @@
from langflow.graph.utils import rewrite_file_path
from langflow.base.data.utils import format_directory_path
import pytest


@pytest.mark.parametrize(
"file_path, expected",
"input_path, expected",
[
# Test case 1: Standard path with multiple directories
("/home/user/documents/file.txt", ["documents/file.txt"]),
# Test case 2: Path with only one directory
("/documents/file.txt", ["documents/file.txt"]),
# Test case 3: Path with no directories (just filename)
("file.txt", ["file.txt"]),
# Test case 4: Path with multiple levels and special characters
("/home/user/my-docs/special_file!.pdf", ["my-docs/special_file!.pdf"]),
# Test case 5: Path with trailing slash
("/home/user/documents/", ["user/documents"]),
# Test case 6: Empty path
("", [""]),
# Test case 7: Path with only slashes
("///", [""]),
# Test case 8: Path with dots
("/home/user/../documents/./file.txt", ["./file.txt"]),
# Test case 9: Windows-style path
("C:\\Users\\Documents\\file.txt", ["Documents/file.txt"]),
# Test case 10: Windows path with trailing backslash
("C:\\Users\\Documents\\", ["Users/Documents"]),
# Test case 11: Mixed separators
("C:/Users\\Documents/file.txt", ["Documents/file.txt"]),
# Test case 12: Network path (UNC)
("\\\\server\\share\\file.txt", ["share/file.txt"]),
# Test case 1: Standard path with no newlines
("/home/user/documents/file.txt", "/home/user/documents/file.txt"),
# Test case 2: Path with newline character
("/home/user/docu\nments/file.txt", "/home/user/docu\\nments/file.txt"),
# Test case 3: Path with multiple newline characters
("/home/user/\ndocu\nments/file.txt", "/home/user/\\ndocu\\nments/file.txt"),
# Test case 4: Path with only newline characters
("\n\n\n", "\\n\\n\\n"),
# Test case 5: Empty path
("", ""),
# Test case 6: Path with mixed newlines and other special characters
("/home/user/my-\ndocs/special_file!.pdf", "/home/user/my-\\ndocs/special_file!.pdf"),
# Test case 7: Windows-style path with newline
("C:\\Users\\\nDocuments\\file.txt", "C:\\Users\\\\nDocuments\\file.txt"),
# Test case 8: Path with trailing newline
("/home/user/documents/\n", "/home/user/documents/\\n"),
# Test case 9: Path with leading newline
("\n/home/user/documents/", "\\n/home/user/documents/"),
# Test case 10: Path with multiple consecutive newlines
("/home/user/docu\n\nments/file.txt", "/home/user/docu\\n\\nments/file.txt"),
],
)
def test_rewrite_file_path(file_path, expected):
result = rewrite_file_path(file_path)
def test_format_directory_path(input_path, expected):
result = format_directory_path(input_path)
assert result == expected


# Additional test for type checking
def test_rewrite_file_path_type():
result = rewrite_file_path("/home/user/file.txt")
assert isinstance(result, list)
assert all(isinstance(item, str) for item in result)
def test_format_directory_path_type():
result = format_directory_path("/home/user/file.txt")
assert isinstance(result, str)

0 comments on commit 844efc1

Please sign in to comment.