Fix on-demand wildcard path resolution and metadata scanning

- Resolve normalized wildcard keys through indexed original paths
- Prevent recursive self-matches for missing indexed files
- Exclude Git metadata consistently from wildcard scans
- Cover path lookup, loading modes and precedence regressions
This commit is contained in:
EnragedAntelope
2026-10-31 15:24:10 -04:00
parent f643d64843
commit fc32922c44
2 changed files with 93 additions and 2 deletions
+11 -2
View File
@@ -111,6 +111,7 @@ def calculate_directory_size(directory_path, limit=None):
total_size = 0
try:
for root, directories, files in os.walk(directory_path, followlinks=True):
directories[:] = [d for d in directories if d not in ('.git', '.github')]
for file in files:
if file.endswith(('.txt', '.yaml', '.yml')):
file_path = os.path.join(root, file)
@@ -145,6 +146,7 @@ def scan_wildcard_metadata(wildcard_path):
discovered = 0
try:
for root, directories, files in os.walk(wildcard_path, followlinks=True):
directories[:] = [d for d in directories if d not in ('.git', '.github')]
for file in files:
if file.endswith('.txt'):
file_path = os.path.join(root, file)
@@ -243,6 +245,12 @@ def find_wildcard_file(key):
except Exception:
pass
# Normalization changes spaces and case; keep the original indexed path.
# Preserve direct-file precedence before falling back to the metadata.
file_path = available_wildcards.get(key)
if file_path and os.path.isfile(file_path):
return (file_path, file_path.endswith(('.yaml', '.yml')))
# Case 2: YAML nested key (e.g., "colors/warm" → "colors.yaml")
if '/' in key:
parent_key = key.split('/')[0]
@@ -297,8 +305,7 @@ def get_wildcard_value(key):
# Example: "dragon" matches "dragon.txt", "fantasy/dragon.txt", "dragon/fire.txt", etc.
matched_keys = []
for k in available_wildcards.keys():
if (k == key or
k.endswith('/' + key) or
if k != key and (k.endswith('/' + key) or
k.startswith(key + '/') or
('/' + key + '/') in k):
matched_keys.append(k)
@@ -453,6 +460,7 @@ def read_wildcard_dict(wildcard_path, on_demand=False):
"""
global wildcard_dict
for root, directories, files in os.walk(wildcard_path, followlinks=True):
directories[:] = [d for d in directories if d not in ('.git', '.github')]
for file in files:
file_path = os.path.join(root, file)
try:
@@ -1120,6 +1128,7 @@ def load_yaml_files_only(wildcard_path):
yaml_count = 0
try:
for root, directories, files in os.walk(wildcard_path, followlinks=True):
directories[:] = [d for d in directories if d not in ('.git', '.github')]
for file in files:
if file.endswith('.yaml') or file.endswith('.yml'):
file_path = os.path.join(root, file)
@@ -24,6 +24,88 @@ from populate_helpers import ( # noqa: E402
SEEDS = [0, 1, 42, 100, 999, 12345, 2_147_483_647]
@pytest.fixture
def wildcard_directory(tmp_path, monkeypatch):
monkeypatch.setattr(wc, "wildcards_path", str(tmp_path))
monkeypatch.setattr(wc, "wildcard_dict", {})
monkeypatch.setattr(wc, "available_wildcards", {})
monkeypatch.setattr(wc, "loaded_wildcards", {})
monkeypatch.setattr(wc, "_on_demand_mode", True)
monkeypatch.setattr(wc.config, "get_config", dict)
return tmp_path
@pytest.mark.parametrize("name", ["my colors.txt", "colors.TXT.txt"])
@pytest.mark.parametrize("prefix", ["", "collection/"])
@pytest.mark.parametrize("short_name", [False, True])
def test_on_demand_expands_indexed_normalized_paths(wildcard_directory, name, prefix, short_name):
path = wildcard_directory / prefix / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("red\n", encoding="utf-8")
wc.scan_wildcard_metadata(str(wildcard_directory))
key = wc.wildcard_normalize(os.path.splitext(name if short_name else prefix + name)[0])
assert wc.process(f"__{key}__", 42) == "red"
@pytest.mark.parametrize("key", ["missing", "collection/missing"])
def test_on_demand_missing_indexed_file_does_not_recurse(wildcard_directory, key):
wc.available_wildcards[key] = str(wildcard_directory / "removed.txt")
assert wc.get_wildcard_value(key) is None
@pytest.mark.parametrize("on_demand", [False, True])
def test_loading_preserves_direct_file_precedence(wildcard_directory, monkeypatch, on_demand):
custom = wildcard_directory / "custom"
custom.mkdir()
(wildcard_directory / "shared.txt").write_text("builtin\n", encoding="utf-8")
(custom / "shared.txt").write_text("custom\n", encoding="utf-8")
monkeypatch.setattr(wc.config, "get_config", lambda: {"custom_wildcards": str(custom)})
monkeypatch.setattr(wc, "get_cache_limit", lambda: 1 if on_demand else 1024 * 1024)
wc.wildcard_load()
# Preserve the existing precedence in each mode, rather than changing it here.
assert wc.process("__shared__", 42) == ("builtin" if on_demand else "custom")
def test_on_demand_depth_match_keeps_all_available_options(wildcard_directory):
for directory, option in (("first", "red"), ("second/nested", "blue")):
path = wildcard_directory / directory / "my colors.txt"
path.parent.mkdir(parents=True)
path.write_text(option + "\n", encoding="utf-8")
wc.scan_wildcard_metadata(str(wildcard_directory))
wc.available_wildcards["removed/my-colors"] = str(wildcard_directory / "removed.txt")
assert sorted(wc.get_wildcard_value("my-colors")) == ["blue", "red"]
@pytest.mark.parametrize("on_demand", [False, True])
def test_wildcard_scans_ignore_git_metadata(wildcard_directory, monkeypatch, caplog, on_demand):
for name in (".git", ".github"):
metadata = wildcard_directory / "collection" / name / "workflows"
metadata.mkdir(parents=True)
(metadata / "publish.yml").write_text("on: [push]\n", encoding="utf-8")
(metadata / "internal.txt").write_text("not a wildcard\n", encoding="utf-8")
# Other dot-directories remain valid wildcard locations.
visible = wildcard_directory / ".styles"
visible.mkdir()
(visible / "colors.txt").write_text("red\n", encoding="utf-8")
(wildcard_directory / "colors.yaml").write_text("palette: [blue]\n", encoding="utf-8")
expected_size = sum(p.stat().st_size for p in
(visible / "colors.txt", wildcard_directory / "colors.yaml"))
monkeypatch.setattr(wc, "get_cache_limit", lambda: 1 if on_demand else 1024 * 1024)
wc.wildcard_load()
assert wc.calculate_directory_size(str(wildcard_directory)) == expected_size
assert wc.process("__.styles/colors__ __palette__", 42) == "red blue"
keys = set(wc.available_wildcards) | set(wc.wildcard_dict) | set(wc.loaded_wildcards)
assert not any("/.git/" in k or "/.github/" in k for k in keys)
assert not [r for r in caplog.records if r.levelno >= logging.WARNING]
# ============================================================================
# Category 1: Basic wildcard __x__
# Tutorial L28 / PRD §2.1, §2.5