fix: mine --dry-run TypeError on files with room=None (#586) (#687)

* fix: return "general" room from process_file error paths (#586)

process_file() returned (0, None) for already-mined, unreadable, and
too-short files.  In --dry-run mode the caller always enters the
room_counts branch, so None ended up as a dict key and crashed the
summary printer with "unsupported format string passed to
NoneType.__format__".

Returning "general" instead of None makes the function contract
explicit: it always yields (int, str).  This matches the consensus
fix discussed in the issue thread.

* style: apply ruff format to test_miner.py
This commit is contained in:
Mikhail Valentsev
2026-04-13 02:23:44 +05:00
committed by GitHub
parent 862a07b198
commit 091c2fe1c6
2 changed files with 29 additions and 3 deletions
+3 -3
View File
@@ -416,16 +416,16 @@ def process_file(
# Skip if already filed
source_file = str(filepath)
if not dry_run and file_already_mined(collection, source_file, check_mtime=True):
return 0, None
return 0, "general"
try:
content = filepath.read_text(encoding="utf-8", errors="replace")
except OSError:
return 0, None
return 0, "general"
content = content.strip()
if len(content) < MIN_CHUNK_SIZE:
return 0, None
return 0, "general"
room = detect_room(filepath, content, rooms, project_path)
chunks = chunk_text(content, source_file)
+26
View File
@@ -262,6 +262,32 @@ def test_file_already_mined_check_mtime():
shutil.rmtree(tmpdir, ignore_errors=True)
def test_mine_dry_run_with_tiny_file_no_crash():
"""Dry-run must not crash when process_file returns 0 drawers (room was None)."""
tmpdir = tempfile.mkdtemp()
try:
project_root = Path(tmpdir).resolve()
# One normal file and one that falls below MIN_CHUNK_SIZE
write_file(project_root / "good.py", "def main():\n print('hello world')\n" * 20)
write_file(project_root / "tiny.txt", "x")
with open(project_root / "mempalace.yaml", "w") as f:
yaml.dump(
{
"wing": "test_project",
"rooms": [{"name": "general", "description": "General"}],
},
f,
)
palace_path = project_root / "palace"
# Should not raise TypeError on the summary print
mine(str(project_root), str(palace_path), dry_run=True)
finally:
shutil.rmtree(tmpdir, ignore_errors=True)
def test_status_missing_palace_does_not_create_empty_collection(tmp_path, capsys):
palace_path = tmp_path / "missing-palace"