콘텐츠로 이동

jussam.make_docs

jussam.make_docs

API 레퍼런스 문서 생성 모듈

학생이 자신의 helpers 폴더에 작성한 소스 코드의 docstring 을 읽어 HTML API 레퍼런스 문서를 만들어 준다. 이 저장소가 GitHub Actions 에서 문서를 배포할 때 쓰는 방식(mkdocs + mkdocstrings)을 그대로 개인 PC 에서 실행하는 것이므로, 결과물의 모양은 공식 문서와 같다.

mkdocs 설정 파일이나 문서 페이지를 직접 만들 필요는 없다. 소스 폴더를 훑어 공개 모듈(_ 로 시작하지 않는 최상위 *.py)마다 페이지와 목차를 자동으로 생성하므로, 파일을 추가하거나 지우면 문서도 따라 바뀐다.

사용 방법 (학생)

from jussam import make_api_docs

make_api_docs("helpers", "helpers-docs")

문서 생성에 필요한 패키지(mkdocs 계열)가 없으면 처음 한 번 자동으로 설치한다. 미리 설치해 두려면 다음과 같이 한다.

pip install "jussam[docs]"

make_api_docs

make_api_docs(
    src_dir,
    out_dir,
    site_name=None,
    open_browser=False,
    force=False,
    install=True,
    verbose=False,
)

소스 폴더의 docstring 을 읽어 HTML API 레퍼런스 문서를 생성한다.

Parameters:

Name Type Description Default
src_dir str

문서화할 소스 폴더 경로 (예: helpers)

required
out_dir str

문서가 생성될 폴더 경로 (예: helpers-docs)

required
site_name str

문서 상단에 표시할 제목. 생략하면 <폴더명> API Docs

None
open_browser bool

생성 후 기본 브라우저로 문서를 열지 여부

False
force bool

출력 폴더에 다른 파일이 있어도 진행할지 여부

False
install bool

필수 패키지가 없을 때 자동으로 설치할지 여부

True
verbose bool

빌드 상세 로그를 모두 출력할지 여부

False

Returns:

Name Type Description
str str

생성된 문서의 시작 페이지(index.html) 경로

Raises:

Type Description
FileNotFoundError

소스 폴더가 없거나 문서화할 *.py 가 없는 경우

ValueError

출력 폴더가 소스를 지울 수 있는 위치인 경우

RuntimeError

패키지 설치 또는 문서 빌드에 실패한 경우

Source code in jussam/make_docs.py
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
def make_api_docs(src_dir: str, out_dir: str, site_name: str = None,
                  open_browser: bool = False, force: bool = False,
                  install: bool = True, verbose: bool = False) -> str:
    """소스 폴더의 docstring 을 읽어 HTML API 레퍼런스 문서를 생성한다.

    Args:
        src_dir (str): 문서화할 소스 폴더 경로 (예: `helpers`)
        out_dir (str): 문서가 생성될 폴더 경로 (예: `helpers-docs`)
        site_name (str): 문서 상단에 표시할 제목. 생략하면 `<폴더명> API Docs`
        open_browser (bool): 생성 후 기본 브라우저로 문서를 열지 여부
        force (bool): 출력 폴더에 다른 파일이 있어도 진행할지 여부
        install (bool): 필수 패키지가 없을 때 자동으로 설치할지 여부
        verbose (bool): 빌드 상세 로그를 모두 출력할지 여부

    Returns:
        str: 생성된 문서의 시작 페이지(index.html) 경로

    Raises:
        FileNotFoundError: 소스 폴더가 없거나 문서화할 `*.py` 가 없는 경우
        ValueError: 출력 폴더가 소스를 지울 수 있는 위치인 경우
        RuntimeError: 패키지 설치 또는 문서 빌드에 실패한 경우
    """
    # -------------------------------------
    # 경로 확인
    # -------------------------------------
    src_path = Path(src_dir).expanduser().resolve()

    if not src_path.is_dir():
        raise FileNotFoundError(
            f"소스 폴더를 찾을 수 없습니다: {src_path}\n"
            "노트북이 있는 위치를 기준으로 한 상대 경로이거나 절대 경로여야 합니다."
        )

    package = src_path.name
    project_root = src_path.parent
    out_path = Path(out_dir).expanduser().resolve()

    if not (src_path / "__init__.py").exists():
        print(f"[경고] {src_path}/__init__.py 가 없어 패키지 개요가 비어 보일 수 있습니다.")

    modules = _find_modules(src_path)

    if not modules:
        raise FileNotFoundError(f"{src_path} 안에 문서화할 .py 파일이 없습니다.")

    _check_output_dir(src_path, out_path, force)

    # -------------------------------------
    # 필수 패키지 확인 및 설치
    # -------------------------------------
    missing = _find_missing_packages()

    if missing:
        if not install:
            raise RuntimeError(
                "문서 생성에 필요한 패키지가 없습니다: " + ", ".join(missing) + "\n"
                f"    {sys.executable} -m pip install {' '.join(missing)}"
            )

        _install_packages(missing)

    # -------------------------------------
    # 설정 파일을 임시 폴더에 만들고 빌드
    # -------------------------------------
    print(f"[준비] 모듈 {len(modules)}개: {', '.join(modules)}")
    build_dir = Path(tempfile.mkdtemp(prefix=f"{PACKAGE_NAME}-docs-"))

    try:
        docs_dir = build_dir / "docs"
        docs_dir.mkdir()

        gen_script = _write_gen_script(build_dir, package, src_path)
        _write_index_page(docs_dir, package, modules)
        config_path = _write_mkdocs_config(
            build_dir, docs_dir, out_path, package, project_root,
            gen_script, site_name or f"{package} API Docs",
        )

        print("[빌드] 문서를 생성하는 중입니다...")
        code = _run_mkdocs(config_path, project_root, verbose)
    finally:
        shutil.rmtree(build_dir, ignore_errors=True)

    if code != 0:
        raise RuntimeError(
            "문서 빌드에 실패했습니다. verbose=True 로 다시 실행하면 원인을 볼 수 있습니다."
        )

    # 이 모듈이 만든 폴더임을 표시 (다음 실행 때 덮어쓰기 확인용)
    (out_path / _MARKER_NAME).write_text(
        f"이 폴더는 {PACKAGE_NAME}.make_api_docs() 가 생성한 문서 폴더입니다.\n", encoding="utf-8"
    )

    index_file = out_path / "index.html"
    print(f"[완료] 문서가 생성되었습니다: {out_path}")
    print(f"       {index_file} 파일을 브라우저로 열어보세요.")
    _show_link(index_file)

    if open_browser:
        webbrowser.open(index_file.as_uri())

    return str(index_file)