mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-05 04:14:03 +00:00
fix: allow non-existent paths in ignore check
The _is_ignored_relative_path method used to raise FileNotFoundError when checking a path that does not exist on disk. This prevented editing tools (replace_content, insert_after_symbol, etc.) from operating on newly created files. Since a non-existent file cannot be matched by ignore patterns, returning False (not ignored) is semantically correct and safe. Changes: - _is_ignored_relative_path: return False instead of raising for non-existent paths, with a debug log message - validate_relative_path docstring: updated to reflect new behavior - Added 3 test cases covering non-existent path scenarios
This commit is contained in:
1 parent
981f560fa3
commit
9c19d5f7f8
3 files changed
+36
-6
No files matched your search
@@ -2,6 +2,9 @@
|
||||
|
||||
Status of the `main` branch. Changes prior to the next official version change will appear here.
|
||||
|
||||
* General:
|
||||
- Not existing paths return `False` on is ignored checks (instead of raising an error)
|
||||
|
||||
# v1.5.1 (2026-05-18)
|
||||
|
||||
* General:
|
||||
|
||||
@@ -191,8 +191,8 @@ class Project(ToStringMixin):
|
||||
|
||||
def _is_ignored_relative_path(self, relative_path: str | Path, ignore_non_source_files: bool = True) -> bool:
|
||||
"""
|
||||
Determine whether an existing path should be ignored based on file type and ignore patterns.
|
||||
Raises `FileNotFoundError` if the path does not exist.
|
||||
Determine whether a path should be ignored based on file type and ignore patterns.
|
||||
Returns False for non-existent paths since they cannot be matched by ignore patterns.
|
||||
|
||||
:param relative_path: Relative path to check
|
||||
:param ignore_non_source_files: whether files that are not source files (according to the file masks
|
||||
@@ -208,7 +208,8 @@ class Project(ToStringMixin):
|
||||
|
||||
abs_path = os.path.join(self.project_root, relative_path)
|
||||
if not os.path.exists(abs_path):
|
||||
raise FileNotFoundError(f"File {abs_path} not found, the ignore check cannot be performed")
|
||||
log.debug(f"Path {abs_path} does not exist, skipping ignore check")
|
||||
return False
|
||||
|
||||
# Check file extension if it's a file
|
||||
is_file = os.path.isfile(abs_path)
|
||||
@@ -284,10 +285,11 @@ class Project(ToStringMixin):
|
||||
|
||||
def validate_relative_path(self, relative_path: str, require_not_ignored: bool = False) -> None:
|
||||
"""
|
||||
Validates that the given relative path to an existing file/dir is safe to read or edit,
|
||||
meaning it's inside the project directory.
|
||||
Validates that the given relative path is safe to read or edit,
|
||||
meaning it's inside the project directory and not ignored.
|
||||
|
||||
Passing a path to a non-existing file will lead to a `FileNotFoundError`.
|
||||
Non-existent paths are allowed (not considered ignored) to support
|
||||
editing tools that create new files.
|
||||
|
||||
:param relative_path: the path to validate, relative to the project root
|
||||
:param require_not_ignored: if True, the path must not be ignored according to the project's ignore settings
|
||||
|
||||
@@ -102,6 +102,31 @@ class TestGlobalIgnoredPaths:
|
||||
assert project.is_ignored_path(str(self.project_path / "debug.log"))
|
||||
assert not project.is_ignored_path(str(self.project_path / "main.py"))
|
||||
|
||||
def test_nonexistent_path_not_ignored(self) -> None:
|
||||
"""Non-existent paths should return False (not ignored), not raise FileNotFoundError."""
|
||||
project = _create_test_project(self.project_path)
|
||||
nonexistent = str(self.project_path / "src" / "new_file.py")
|
||||
assert not os.path.exists(nonexistent)
|
||||
assert not project.is_ignored_path(nonexistent)
|
||||
|
||||
def test_nonexistent_path_with_ignore_patterns(self) -> None:
|
||||
"""Non-existent paths matching ignore patterns still return False (cannot check)."""
|
||||
project = _create_test_project(
|
||||
self.project_path,
|
||||
global_ignored_paths=["*.log"],
|
||||
)
|
||||
nonexistent = str(self.project_path / "nonexistent.log")
|
||||
assert not os.path.exists(nonexistent)
|
||||
# Should not raise, should not match the *.log pattern
|
||||
assert not project.is_ignored_path(nonexistent)
|
||||
|
||||
def test_validate_relative_path_allows_nonexistent(self) -> None:
|
||||
"""validate_relative_path with require_not_ignored should not raise for non-existent paths."""
|
||||
project = _create_test_project(self.project_path)
|
||||
nonexistent = "src/new_file.py"
|
||||
# Should not raise
|
||||
project.validate_relative_path(nonexistent, require_not_ignored=True)
|
||||
|
||||
|
||||
class TestRegisteredProjectGlobalIgnoredPaths:
|
||||
"""RegisteredProject.get_project_instance() correctly passes global patterns to Project."""
|
||||
|
||||
Reference in new issue
Block a user