Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@

## Development setup

Install `uv` first if it is not already available in your `PATH`, then sync the
repository-managed virtual environment:

```bash
python3.10 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
uv sync --frozen --all-extras
```

Install the parser stack only when you need live MinerU execution:

```bash
pip install "mineru[pipeline]==3.0.9"
uv pip install --python .venv/bin/python "mineru[pipeline]==3.0.9"
```

On Windows, replace `.venv/bin/python` with `.venv\Scripts\python.exe`.

## Test commands

```bash
pytest
PYTHONWARNINGS=error pytest
pytest --cov=src/newsdom_api --cov-branch --cov-report=term-missing --cov-fail-under=100
uv run pytest
PYTHONWARNINGS=error uv run pytest
uv run pytest --cov=src/newsdom_api --cov-branch --cov-report=term-missing --cov-fail-under=100
```

CI installs dependencies from `uv.lock`, and workflow actions are
Expand Down
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,26 @@ NewsDOM API parses scanned Japanese newspaper PDFs into DOM-like article trees.

### Install

Install `uv` first if it is not already available in your `PATH`, then sync the
repository-managed virtual environment:

```bash
python3.10 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
uv sync --frozen --all-extras
```

To enable real parsing with MinerU, install the MinerU CLI separately in the
environment that will execute parsing:
same `.venv` that `uv sync` created:

```bash
pip install "mineru[pipeline]==3.0.9"
uv pip install --python .venv/bin/python "mineru[pipeline]==3.0.9"
```

On Windows, replace `.venv/bin/python` with `.venv\Scripts\python.exe`.

### Run

```bash
uvicorn --app-dir src newsdom_api.main:app --reload
uv run uvicorn --app-dir src newsdom_api.main:app --reload
```

### Docker
Expand Down Expand Up @@ -75,13 +78,13 @@ curl -F "file=@sample.pdf" http://127.0.0.1:8000/parse
### Run tests

```bash
pytest
uv run pytest
```

### Fuzzing smoke

```bash
python fuzzers/dom_builder_fuzzer.py --smoke tests/fixtures/mineru_sample.json
uv run python fuzzers/dom_builder_fuzzer.py --smoke tests/fixtures/mineru_sample.json
```

The repository also enforces a `quality-gate` workflow with 100% source
Expand Down
8 changes: 4 additions & 4 deletions manual/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ FastAPI 서버를 실행하고, 스캔된 신문 PDF를 업로드하여 기사 D

## 1. 서버 실행하기

가상환경을 활성화한 상태에서, `uvicorn`을 이용하여 API 서버(`src/newsdom_api/main.py`)를 구동합니다.
저장소 루트에서 `uv run uvicorn`을 이용하여 API 서버(`src/newsdom_api/main.py`)를 구동합니다.

```bash
# 개발 시 핫-리로딩(--reload) 모드 사용
uvicorn --app-dir src newsdom_api.main:app --reload
uv run uvicorn --app-dir src newsdom_api.main:app --reload
```

## 2. 인터랙티브 웹 UI
Expand All @@ -24,8 +24,8 @@ FastAPI는 OpenAPI 기반의 대화형 API 문서를 자동으로 생성합니
`manual/assets/redoc.png` 경로에 보관합니다.
이 이미지는 `uv run uvicorn --app-dir src newsdom_api.main:app --host
127.0.0.1 --port 8000` 명령으로 서버를 띄운 뒤 `/docs`와 `/redoc`를
실제로 캡처한 결과입니다. 일반 실행은 활성화된 가상환경에서
`uvicorn --app-dir src newsdom_api.main:app --reload`를 사용하면 됩니다.
실제로 캡처한 결과입니다. 일반 실행은 저장소 루트에서
`uv run uvicorn --app-dir src newsdom_api.main:app --reload`를 사용하면 됩니다.

![Swagger UI 화면](assets/swagger-ui.png)

Expand Down
41 changes: 21 additions & 20 deletions manual/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,15 @@

## 1. 기본 테스트 및 개발 모드 설치

가장 간단한 형태로 파이썬 가상환경(Virtual Environment)을 생성하고
패키지를 설치합니다. 이 모드에서는 실제 `MinerU` 모델이 로드되지
않으며, `pytest`나 합성 픽스처(Synthetic Fixtures) 기반 테스트 용도로
적합합니다. 예시 명령은 `python3.10`을 사용하지만, 지원 범위 안의 다른 인터프리터도 동일하게 사용할 수 있습니다.
가장 간단한 형태로 저장소가 관리하는 가상환경을 `uv`로 동기화합니다.
이 모드에서는 실제 `MinerU` 모델이 로드되지 않으며, `pytest`나 합성
픽스처(Synthetic Fixtures) 기반 테스트 용도로 적합합니다. `uv sync`는
저장소 루트의 `.venv`를 자동으로 생성/갱신하므로 별도 `venv` 생성이나
활성화가 필수는 아닙니다.

```bash
# 가상 환경 생성 (권장 예시: python3.10)
python3.10 -m venv .venv

# 가상 환경 활성화
# macOS / Linux
source .venv/bin/activate
# Windows (WSL 환경 제외)
# .venv\Scripts\activate

# pip 업그레이드
python -m pip install --upgrade pip

# 의존성 패키지와 함께 개발 모드로 설치
pip install -e ".[dev]"
# 저장소 루트에서 개발/테스트/문서 extras까지 모두 동기화
uv sync --frozen --all-extras
```

---
Expand All @@ -50,9 +39,11 @@ pip install -e ".[dev]"

```bash
# MinerU 파이프라인 CLI 설치
pip install "mineru[pipeline]==3.0.9"
uv pip install --python .venv/bin/python "mineru[pipeline]==3.0.9"
```

Windows에서는 `.venv/bin/python` 대신 `.venv\Scripts\python.exe` 경로를 사용하세요.

이 명령어를 통해 **`mineru[pipeline]==3.0.9`** 버전이 설치되며
딥러닝 기반 모델을 위한 준비가 완료됩니다. 설치 후 처음 API 서버를
구동하고 PDF를 파싱할 때 모델(Weight) 파일을 백그라운드에서 다운로드할
Expand All @@ -77,14 +68,24 @@ export NEWSDOM_MINERU_BIN="/path/to/custom/mineru"

```bash
# 파이썬 경고(Warning)를 에러로 취급하여 꼼꼼하게 검사
PYTHONWARNINGS=error pytest
PYTHONWARNINGS=error uv run pytest
```

현재 저장소에는 별도의 `integration` 마커 테스트 묶음이 없으므로,
설치 확인의 기준은 기본 `pytest` 스위트 통과입니다. 추가로 MinerU
경로와 API 동작까지 확인하려면 서버를 직접 띄운 뒤 수동 API 점검
단계를 수행하세요.

```bash
# 별도 터미널에서 API 서버 기동
uv run uvicorn --app-dir src newsdom_api.main:app --host 0.0.0.0 --port 8000 --reload

# 다른 터미널에서 상태 확인
curl -sS http://127.0.0.1:8000/health
```

정상 응답 예시는 `{"status": "ok"}`이며 HTTP 200 상태 코드를 반환해야 합니다.

모든 테스트(`tests/`)가 성공적으로 통과했다면 API 서버를 실행할
준비가 된 것입니다.

Expand Down
29 changes: 24 additions & 5 deletions tests/test_manual_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,32 @@ def test_development_doc_uses_tree_wording():
assert "트리 구조의 DOM" in text


def test_installation_doc_uses_quoted_extras_and_clear_python_wording():
def test_installation_doc_uses_uv_first_setup_and_verification_commands():
text = Path("manual/installation.md").read_text(encoding="utf-8")
assert "Required: `>=3.10, <3.14`" in text
assert "uv sync --frozen --all-extras" in text
assert 'uv pip install --python .venv/bin/python "mineru[pipeline]==3.0.9"' in text
assert "uv run pytest" in text
assert "python3.10 -m venv .venv" not in text
assert 'pip install -e ".[dev]"' not in text


def test_installation_doc_includes_manual_api_healthcheck_commands():
text = Path("manual/installation.md").read_text(encoding="utf-8")
assert (
"예시 명령은 `python3.10`을 사용하지만, 지원 범위 안의 다른 인터프리터도 동일하게 사용할 수 있습니다."
"uv run uvicorn --app-dir src newsdom_api.main:app --host 0.0.0.0 --port 8000 --reload"
in text
)
assert "python3.10 -m venv .venv" in text
assert 'pip install -e ".[dev]"' in text
assert 'pip install "mineru[pipeline]==3.0.9"' in text
assert "curl -sS http://127.0.0.1:8000/health" in text
assert "HTTP 200" in text


def test_api_reference_uses_uv_run_server_command():
text = Path("manual/api-reference.md").read_text(encoding="utf-8")
assert "uv run uvicorn --app-dir src newsdom_api.main:app --reload" in text
assert "가상환경을 활성화한 상태" not in text


def test_installation_doc_notes_windows_uv_python_path_equivalent():
text = Path("manual/installation.md").read_text(encoding="utf-8")
assert ".venv\\Scripts\\python.exe" in text
27 changes: 23 additions & 4 deletions tests/test_readme.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,33 @@ def test_contributing_mentions_develop_branch():
assert "develop" in text


def test_readme_quotes_dev_extra_install_command():
def test_readme_uses_uv_sync_for_repo_setup():
text = Path("README.md").read_text(encoding="utf-8")
assert 'pip install -e ".[dev]"' in text
assert "uv sync --frozen --all-extras" in text
assert 'pip install -e ".[dev]"' not in text
assert "python3.10 -m venv .venv" not in text


def test_contributing_quotes_dev_extra_install_command():
def test_contributing_uses_uv_sync_for_repo_setup():
text = Path("CONTRIBUTING.md").read_text(encoding="utf-8")
assert 'pip install -e ".[dev]"' in text
assert "uv sync --frozen --all-extras" in text
assert 'pip install -e ".[dev]"' not in text


def test_readme_documents_uv_run_entrypoints():
text = Path("README.md").read_text(encoding="utf-8")
assert "uv run uvicorn --app-dir src newsdom_api.main:app --reload" in text
assert "uv run pytest" in text
assert (
"uv run python fuzzers/dom_builder_fuzzer.py --smoke tests/fixtures/mineru_sample.json"
in text
)


def test_repo_docs_note_windows_uv_python_path_equivalent():
for path in [Path("README.md"), Path("CONTRIBUTING.md")]:
text = path.read_text(encoding="utf-8")
assert ".venv\\Scripts\\python.exe" in text, path


def test_pull_request_template_exists():
Expand Down
11 changes: 11 additions & 0 deletions tests/test_truth_source_alignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,14 @@ def test_adr_follow_up_drops_stale_issue_references() -> None:
)
assert "#8" not in text
assert "#10" not in text


def test_public_docs_drop_stale_pip_setup_examples() -> None:
for path in [
Path("README.md"),
Path("CONTRIBUTING.md"),
Path("manual/installation.md"),
]:
text = path.read_text(encoding="utf-8")
assert 'pip install -e ".[dev]"' not in text, path
assert "python3.10 -m venv .venv" not in text, path
Loading