v3 migration: linter tools/check-md.py (0/219 issues); sec01 #47 RU table fixed; AGENTS.md: migration done, liart TODO + pending unification markers

This commit is contained in:
Dmitry Kokorin 2026-09-21 11:11:53 +03:00
parent 4f5372ab56
commit f3fb432bd9
3 changed files with 16 additions and 15 deletions

View file

@ -2,7 +2,11 @@
"""Lint book cards against CANON v3 (see AGENTS.md).
Usage: python3 tools/check-md.py [section ...] (default: all)
Exit code: 0 = clean, 1 = issues found."""
import re, sys, os, glob
import re, sys, os, glob, importlib.util
# single source of truth for MANIFEST parsing: the migration tool
_spec = importlib.util.spec_from_file_location("_mig", os.path.join(os.path.dirname(__file__), "migrate_cards_v3.py"))
_mig = importlib.util.module_from_spec(_spec); _spec.loader.exec_module(_mig)
ALLOWED_SECTIONS = re.compile(r'^## (Editions — [A-Z]{2}|Downloads|Catalog records|Notes)$')
BANNED_SECTIONS = ('## Russian editions', '## Libgen', '## RSL records', '## Verdict',
@ -61,14 +65,14 @@ def lint_card(path, manifest_files):
if dm:
rows = re.findall(r'^\|\s*(EN|RU\??|\?)\s*\|\s*([0-9]{2}-[a-zA-Z0-9\.\-]+)\s*\|', dm.group(1), re.M)
disk = set(os.path.basename(f) for f in glob.glob(f"downloads/{sec_of(path)}/*"))
manifest = set(f for f in manifest_files.get(num, []))
manifest = set(f for f, _, _ in manifest_files.get(num, []))
for lang, fname in rows:
if fname not in disk:
issues.append(f'Downloads file not on disk: {fname}')
if manifest and fname not in manifest:
issues.append(f'Downloads file not in MANIFEST: {fname}')
if manifest and set(f for _, f in rows) != manifest:
extra = manifest - set(f for _, f in rows)
if manifest and set(f for _, f in rows) != set(manifest):
extra = set(manifest) - set(f for _, f in rows)
missing = set(f for _, f in rows) - manifest
if extra: issues.append(f'MANIFEST files missing from card: {sorted(extra)}')
if missing: issues.append(f'card files not in MANIFEST: {sorted(missing)}')
@ -99,19 +103,16 @@ def main():
secdir = f'sections/{sec}'
if not os.path.isdir(secdir):
continue
# manifest file sets
mfiles = {}
mp = f'downloads/{sec}/MANIFEST.md'
if os.path.exists(mp):
mt = open(mp).read()
for f in re.findall(r'([0-9]{2}-[a-zA-Z0-9\.\-]+\.(?:pdf|fb2|epub|doc|docx|chm|djvu|txt|zip|azw3))', mt):
mfiles.setdefault(f[:2], set()).add(f)
mfiles = _mig.parse_manifest_files(f'downloads/{sec}/MANIFEST.md')
ncards = 0
for p in sorted(glob.glob(f'{secdir}/[0-9][0-9]-*.md')):
ncards += 1
for i in lint_card(p, mfiles):
total += 1
print(f'{p}: {i}')
if ncards == 0:
print(f'{sec}: 0 cards (skipped)')
continue
for i in lint_index_status(secdir):
total += 1
print(f'{secdir}/INDEX: {i}')