Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
97 lines
3.8 KiB
Python
97 lines
3.8 KiB
Python
"""위키 생성 CLI (계획서 v4 §5.7, §11.6).
|
|
|
|
python -m wiki_out.run [--program X] [--all] [--limit N] [--dry-run]
|
|
|
|
- 요약(Stage 3) 이 없어도 파서 구조 사실만으로 문서를 만든다(조각이 생기면 재실행 시 채워짐).
|
|
- programs/packages/concepts 는 사람 교정 보존 병합(merge.py). 로직 조각은 프로그램 문서 안의 섹션.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import re
|
|
|
|
from config.glossary import load_glossary
|
|
from config.settings import settings
|
|
from index.db import connect
|
|
|
|
from .entities import write_entity_wiki
|
|
from .merge import merge_write
|
|
from .okf_writer import PIPELINE, _fm, _lst, _now, _q, write_manifest, write_program_wiki
|
|
|
|
|
|
def write_concepts() -> int:
|
|
"""도메인 용어 사전을 concepts/ 문서로 출력.
|
|
|
|
사전 로딩은 config.glossary 로 옮겼다 — 질의 확장(query/expand.py)이 같은 사전을 써야 하고,
|
|
파싱 규칙이 두 곳에 있으면 갈라진다.
|
|
"""
|
|
glossary = load_glossary()
|
|
count = 0
|
|
for concept, related in glossary.items():
|
|
fm = [
|
|
"type: concept",
|
|
f"title: {_q(concept)}",
|
|
f"description: {_q(concept + ' — 도메인 개념 (질의 확장용)')}",
|
|
f"tags: {_lst(related[:10])}",
|
|
f"generated: {{ by: {_q(PIPELINE)}, at: {_q(_now())} }}",
|
|
]
|
|
body = ["## 관련 용어", "",
|
|
"이 목록은 검색 질의 확장에도 쓰인다 — `/search/logic?q=` 에 아래 어느 말로 물어도 걸린다.",
|
|
""] + [f"- {t}" for t in related] + [""]
|
|
rel = f"concepts/{re.sub(r'[^0-9A-Za-z가-힣_.-]', '_', concept)}.md"
|
|
merge_write(settings.wiki_dir / rel, _fm(fm) + "\n" + "\n".join(body),
|
|
code_hash=None, wiki_dir=settings.wiki_dir, doc_rel=rel)
|
|
count += 1
|
|
return count
|
|
|
|
|
|
def main() -> None:
|
|
ap = argparse.ArgumentParser(description="OKF 위키 생성")
|
|
ap.add_argument("--program", default=None, help="프로그램 하나만")
|
|
ap.add_argument("--all", action="store_true", help="소스 있는 전체 프로그램")
|
|
ap.add_argument("--limit", type=int, default=None)
|
|
ap.add_argument("--no-entities", action="store_true",
|
|
help="tables/ functions/ tcodes/ 엔티티 페이지를 만들지 않는다")
|
|
ap.add_argument("--dry-run", action="store_true")
|
|
args = ap.parse_args()
|
|
|
|
con = connect()
|
|
try:
|
|
if args.program:
|
|
names = [args.program.upper()]
|
|
elif args.all:
|
|
rows = con.execute(
|
|
"SELECT name FROM program WHERE has_source=1 ORDER BY name").fetchall()
|
|
names = [r["name"] for r in rows]
|
|
else:
|
|
ap.error("--program 또는 --all 필요")
|
|
if args.limit:
|
|
names = names[: args.limit]
|
|
if args.dry_run:
|
|
print(json.dumps({"would_process": len(names)}, ensure_ascii=False))
|
|
return
|
|
|
|
totals = {"programs": 0, "chunks": 0, "packages": 0, "failed": 0}
|
|
for name in names:
|
|
try:
|
|
s = write_program_wiki(name, con=con)
|
|
totals["programs"] += s["programs"]
|
|
totals["chunks"] += s["chunks"]
|
|
totals["packages"] += s["packages"]
|
|
except Exception as e: # noqa: BLE001
|
|
totals["failed"] += 1
|
|
print(f"[FAIL] {name}: {type(e).__name__}: {e}")
|
|
totals["concepts"] = write_concepts()
|
|
if not args.no_entities:
|
|
# tables/ functions/ tcodes/ — 파서 사실만으로 만들어진다 (수정사항 8번)
|
|
totals.update(write_entity_wiki(con, settings.wiki_dir))
|
|
write_manifest(settings.wiki_dir, con)
|
|
print(json.dumps(totals, ensure_ascii=False))
|
|
finally:
|
|
con.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|