From c589ed49b8732743458cef6ccdf9e314dec90206 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Tue, 20 Oct 2026 05:57:05 +0200 Subject: [PATCH] fix: the site says 1 file, not 1 files Counts were printed with a fixed plural and the site said "1 files" 234 times, "1 issues" and "1 entries" too. A shared helper picks the noun, and the generated-pages prose test refuses the form. --- scripts/generate_site.py | 17 +++++++++-------- scripts/siterender.py | 5 +++++ tests/test_prose_style.py | 4 +++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/scripts/generate_site.py b/scripts/generate_site.py index 772824f1..68905eb1 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -1707,7 +1707,7 @@ def _render_platform_systems( anchor = sys_id.replace(" ", "-") if use_collapsible: - status_tag = "OK" if ok_count == total else f"{total - ok_count} issues" + status_tag = "OK" if ok_count == total else _count(total - ok_count, "issue") lines.append(f'') lines.append(f'??? note "{sys_id} ({ok_count}/{total} - {status_tag})"') lines.append("") @@ -3052,7 +3052,7 @@ def _emulator_file_summary( held = f"{in_repo_count} in repo, {missing_count} missing" if unsourceable_count: held += f", {unsourceable_count} unsourceable" - total = f"**{len(slots)} files**" + total = f"**{_count(len(slots), 'file')}**" if len(slots) != len(files): total += f" ({len(files)} accepted versions)" parts = [ @@ -3344,7 +3344,7 @@ def _render_problem_files( if missing_files: lines.extend([ f'### Missing ' - f"{len(missing_files)} files", + f"{_count(len(missing_files), 'file')}", "", "| File | Required | Platforms |", "|------|----------|-----------|", @@ -3359,7 +3359,7 @@ def _render_problem_files( if untested_files: lines.extend([ f'### Untested ' - f"{len(untested_files)} files", + f"{_count(len(untested_files), 'file')}", "", "Present but hash not verified.", "", @@ -3375,7 +3375,7 @@ def _render_problem_files( if mismatch_files: lines.extend([ f'### Hash Mismatch ' - f"{len(mismatch_files)} files", + f"{_count(len(mismatch_files), 'file')}", "", "Platform says OK but emulator validation disagrees.", "", @@ -3792,11 +3792,11 @@ def generate_gap_analysis( if src_missing_details: req_src = [m for m in src_missing_details if m["required"]] lines.extend([ - f"### Files to Source ({len(src_missing_details)} files, " + f"### Files to Source ({_count(len(src_missing_details), 'file')}, " f"{len(req_src)} required" + ( - f"; {entries} entries, a file declared with the same hash " - "at several places is listed once)" + f", {_count(entries, 'entry', 'entries')}: " + "a file declared with the same hash at several places is listed once)" if entries != len(src_missing_details) else ")" ), "", @@ -4932,6 +4932,7 @@ from sitesources import ( # noqa: E402,F401 ) from siterender import ( # noqa: E402,F401 _by_mode, + _count, _render_yaml_value, _slugify_anchor, _system_page_map, diff --git a/scripts/siterender.py b/scripts/siterender.py index a1999d01..1cf06c88 100644 --- a/scripts/siterender.py +++ b/scripts/siterender.py @@ -30,6 +30,11 @@ def _code(value: object) -> str: return "`" + str(value).replace("`", "'") + "`" +def _count(number: int, noun: str, plural: str = "") -> str: + """A count and its noun, singular for one: the site printed "1 files" 234 times.""" + return f"{number:,} {noun if number == 1 else plural or noun + 's'}" + + def _escape_tags(text: str) -> str: """Show a placeholder such as ```` as it was written. diff --git a/tests/test_prose_style.py b/tests/test_prose_style.py index 84d750ab..29309ebc 100644 --- a/tests/test_prose_style.py +++ b/tests/test_prose_style.py @@ -27,6 +27,8 @@ GLYPHS = re.compile( # backticks, which are blanked before the search. CLAUSE_SEMICOLON = re.compile(r"[A-Za-z0-9)\]\"']; [A-Za-z(]") BACKTICKS = re.compile(r"`[^`\n]*`") +# "1 files", a count the generator printed without its singular. +ONE_PLURAL = re.compile(r"(?", "", page.read_text(encoding="utf-8"), flags=re.S) text = FENCED.sub("", text) for number, line in enumerate(text.splitlines(), 1): - if GLYPHS.search(line) or _semicolons(line): + if GLYPHS.search(line) or _semicolons(line) or ONE_PLURAL.search(line): offenders.append(f"{page.relative_to(ROOT)}:{number}: {line.strip()[:100]}") self.assertEqual(offenders, [], "\n".join(offenders[:40]))