mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 12:15:10 +00:00
fix: improve ignored_paths YAML guidance
Fixes #1561 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
22c135a881
commit
bd9c4c9e89
4 files changed
+62
-1
No files matched your search
@@ -71,6 +71,13 @@ additional_workspace_folders: []
|
||||
|
||||
# list of additional paths to ignore in this project.
|
||||
# Same syntax as gitignore, so you can use * and **.
|
||||
# Important: quote patterns that start with `*`, otherwise YAML treats them as aliases.
|
||||
# Example:
|
||||
# ignored_paths:
|
||||
# - "examples/**"
|
||||
# - ".worktrees/**"
|
||||
# - "**/bin/**"
|
||||
# - "**/obj/**"
|
||||
# Note: global ignored_paths from serena_config.yml are also applied additively.
|
||||
ignored_paths: []
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ ls_specific_settings: {}
|
||||
# list of paths to ignore across all projects.
|
||||
# Same syntax as gitignore, so you can use * and **.
|
||||
# These patterns are merged additively with each project's own ignored_paths.
|
||||
# Quote patterns that start with `*`, e.g. `"**/bin/**"`.
|
||||
ignored_paths: []
|
||||
|
||||
# list of regex patterns which, when matched, mark a memory entry as read‑only.
|
||||
|
||||
+11
-1
@@ -68,7 +68,17 @@ def load_yaml(path: str, comment_normalisation: YamlCommentNormalisation = YamlC
|
||||
"""
|
||||
with open(path, encoding=SERENA_FILE_ENCODING) as f:
|
||||
yaml = _create_yaml(preserve_comments=True)
|
||||
commented_map: CommentedMap | None = yaml.load(f)
|
||||
try:
|
||||
commented_map: CommentedMap | None = yaml.load(f)
|
||||
except Exception as e:
|
||||
msg = str(e)
|
||||
if "undefined alias" in msg:
|
||||
raise ValueError(
|
||||
f"Invalid YAML in {path}: values that start with `*` must be quoted. "
|
||||
"This often happens in `ignored_paths` when using gitignore-style globs like "
|
||||
'`"**/bin/**"` or `"**/obj/**"`.'
|
||||
) from e
|
||||
raise
|
||||
if commented_map is None: # ruamel returns None for empty documents, but we want an empty CommentedMap
|
||||
commented_map = CommentedMap()
|
||||
normalise_yaml_comments(commented_map, comment_normalisation)
|
||||
|
||||
@@ -499,6 +499,25 @@ class TestProjectSerenaDataFolder:
|
||||
assert project.path_to_serena_data_folder() == str(custom_serena)
|
||||
|
||||
|
||||
class TestProjectConfigYamlValidation:
|
||||
def test_ignored_paths_globs_starting_with_star_require_quotes(self):
|
||||
project_dir = Path(tempfile.mkdtemp())
|
||||
try:
|
||||
serena_dir = project_dir / SERENA_MANAGED_DIR_NAME
|
||||
serena_dir.mkdir(parents=True)
|
||||
(serena_dir / "project.yml").write_text('project_name: "demo"\nlanguages: ["csharp"]\nignored_paths:\n- **/bin/**\n')
|
||||
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
ProjectConfig.load(project_dir, create_default_serena_config())
|
||||
|
||||
msg = str(exc_info.value)
|
||||
assert "values that start with `*` must be quoted" in msg
|
||||
assert "ignored_paths" in msg
|
||||
assert '"**/bin/**"' in msg
|
||||
finally:
|
||||
shutil.rmtree(project_dir)
|
||||
|
||||
|
||||
class TestSerenaConfigFromConfigFileRobustness:
|
||||
"""Tests that ``SerenaConfig.from_config_file`` does not abort the whole
|
||||
loader when a single registered project has a broken ``project.yml``.
|
||||
@@ -568,6 +587,30 @@ class TestSerenaConfigFromConfigFileRobustness:
|
||||
f"Expected a warning naming {bad_project.resolve()}, got: {caplog.messages}"
|
||||
)
|
||||
|
||||
def test_alias_like_ignored_path_error_is_logged_with_hint(self, caplog, monkeypatch):
|
||||
good_project = self._make_project_dir(
|
||||
"good_project",
|
||||
'project_name: "good_project"\nlanguages: ["python"]\n',
|
||||
)
|
||||
bad_project = self._make_project_dir(
|
||||
"bad_project",
|
||||
'project_name: "bad_project"\nlanguages: ["csharp"]\nignored_paths:\n- **/bin/**\n',
|
||||
)
|
||||
self._write_master_config([good_project, bad_project])
|
||||
|
||||
monkeypatch.setattr(
|
||||
SerenaConfig,
|
||||
"_determine_config_file_path",
|
||||
classmethod(lambda cls: str(self.master_config_path)),
|
||||
)
|
||||
|
||||
with caplog.at_level(logging.ERROR):
|
||||
config = SerenaConfig.from_config_file(generate_if_missing=False)
|
||||
|
||||
registered_roots = {Path(p.project_root).resolve() for p in config.projects}
|
||||
assert registered_roots == {good_project.resolve()}
|
||||
assert any("must be quoted" in msg and str(bad_project.resolve()) in msg for msg in caplog.messages), caplog.messages
|
||||
|
||||
|
||||
class TestMemoriesManagerCustomPath:
|
||||
"""Tests for MemoriesManager with a custom serena data folder."""
|
||||
|
||||
Reference in new issue
Block a user