fix(search): glob '?' matches one character, not two (#1682)

This commit is contained in:
Amir Fathi authored and GitHub committed 2026-07-12 11:05:13 +02:00
1 parent 6018bf4616
commit 1901e63dc4
3 files changed
+20 -2

No files matched your search

+3
View File
@@ -3,6 +3,9 @@
Status of the `main` branch. Changes prior to the next official version change will appear here.
* General:
- Fix: in `glob_to_regex` / `search_text(is_glob=True)`, a `?` wildcard matched two characters instead
of one (it emitted `..` rather than `.`); it now matches a single character, consistent with the
`?` semantics documented for `glob_match` and the `test_??.py` example in `search_text`'s docstring.
- Add notion of trusted projects via new global configuration setting `trusted_project_path_patterns`.
Current effects:
- `ls_specific_settings` defined in project configurations will only be applied for trusted projects
+1 -1
View File
@@ -124,7 +124,7 @@ def glob_to_regex(glob_pat: str) -> str:
if ch == "*":
regex_parts.append(".*")
elif ch == "?":
regex_parts.append("..")
regex_parts.append(".")
elif ch == "\\":
i += 1
if i < len(glob_pat):
+16 -1
View File
@@ -1,9 +1,10 @@
import re
from collections.abc import Callable
import pytest
from serena.util.file_proxy import FileCollection, FileProxy
from serena.util.text_utils import LineType, MultiFileContentReplacer, search_files, search_text
from serena.util.text_utils import LineType, MultiFileContentReplacer, glob_to_regex, search_files, search_text
class TestSearchText:
@@ -201,6 +202,20 @@ class TestSearchText:
assert len(matches_curly) == 1
assert "{bar}" in matches_curly[0].lines[0].line_content
def test_glob_to_regex_question_matches_single_char(self):
"""A glob '?' matches exactly one character, matching glob_match's documented semantics."""
rx = glob_to_regex("a?c")
assert re.fullmatch(rx, "abc") is not None
assert re.fullmatch(rx, "ac") is None
assert re.fullmatch(rx, "abbc") is None
def test_search_text_glob_question_single_char(self):
"""search_text('c?t', is_glob=True) must match 'cat' (one char), not 'coat' (two chars)."""
content = "value_cat_end\nvalue_coat_end"
matches = search_text("c?t", content=content, is_glob=True, multiline=False)
assert len(matches) == 1
assert "value_cat_end" in matches[0].lines[0].line_content
def test_search_text_no_matches(self):
"""Test searching with a pattern that doesn't match anything."""
content = """