refactor: 统一代码格式,调整多行代码换行风格

对多个文件进行代码格式化调整,将长行参数拆分为多行书写,提升代码可读性,包括:
- 调整函数定义、调用的多行换行格式
- 优化列表、元组、字典的多行排版
- 新增README.md项目说明文档
This commit is contained in:
2026-07-30 14:25:12 +08:00
parent dce9e31bde
commit fdb664e546
10 changed files with 491 additions and 49 deletions
+17 -3
View File
@@ -34,7 +34,9 @@ def client(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Iterator[TestClie
return None
monkeypatch.setattr(QdrantService, "ensure_collections", _noop_ensure_collections)
monkeypatch.setattr(document_module.settings, "upload_dir", str(tmp_path / "uploads"))
monkeypatch.setattr(
document_module.settings, "upload_dir", str(tmp_path / "uploads")
)
with TestClient(app) as test_client:
yield test_client
@@ -45,7 +47,13 @@ def _inject_manager(monkeypatch: pytest.MonkeyPatch, manager: FakeManager) -> No
def _make_minimal_pdf(text: str = "Hello PDF World") -> bytes:
content_stream = f"BT /F1 24 Tf 100 700 Td ({text}) Tj ET".encode("latin-1")
content_obj = b"<< /Length " + str(len(content_stream)).encode() + b" >>\nstream\n" + content_stream + b"\nendstream"
content_obj = (
b"<< /Length "
+ str(len(content_stream)).encode()
+ b" >>\nstream\n"
+ content_stream
+ b"\nendstream"
)
return (
b"%PDF-1.0\n"
b"1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n"
@@ -161,7 +169,13 @@ def test_upload_docx_extracts_text(
content = _make_docx(["第一段落", "第二段落"])
resp = client.post(
"/api/v1/documents/upload",
files={"file": ("doc.docx", content, "application/vnd.openxmlformats-officedocument.wordprocessingml.document")},
files={
"file": (
"doc.docx",
content,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
)
},
)
assert resp.status_code == 202
+20 -5
View File
@@ -14,7 +14,13 @@ from app.core.file_parser import parse_file, supported_extensions
def _make_minimal_pdf(text: str = "Hello PDF World") -> bytes:
"""构造一个含一页文本的最小 PDF(pypdf 可读出文本)"""
content_stream = f"BT /F1 24 Tf 100 700 Td ({text}) Tj ET".encode("latin-1")
content_obj = b"<< /Length " + str(len(content_stream)).encode() + b" >>\nstream\n" + content_stream + b"\nendstream"
content_obj = (
b"<< /Length "
+ str(len(content_stream)).encode()
+ b" >>\nstream\n"
+ content_stream
+ b"\nendstream"
)
return (
b"%PDF-1.0\n"
b"1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n"
@@ -36,6 +42,7 @@ def _make_minimal_pdf(text: str = "Hello PDF World") -> bytes:
def _make_docx(text_lines: list[str]) -> bytes:
from docx import Document # type: ignore[import-untyped]
document = Document()
for line in text_lines:
document.add_paragraph(line)
@@ -222,7 +229,9 @@ def _patch_pdf_ocr_deps(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setitem(sys.modules, "rapidocr_onnxruntime", fake_module)
def test_parse_pdf_ocr_fallback_when_text_layer_empty(monkeypatch: pytest.MonkeyPatch) -> None:
def test_parse_pdf_ocr_fallback_when_text_layer_empty(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""扫描件 PDF(文本层全空)触发 OCR 降级,返回识别文本"""
_patch_pdf_ocr_deps(monkeypatch)
monkeypatch.setattr(settings, "pdf_ocr_enabled", True)
@@ -256,7 +265,9 @@ def test_parse_pdf_ocr_respects_max_pages(monkeypatch: pytest.MonkeyPatch) -> No
assert "OCR文本第2页" not in result
def test_parse_pdf_ocr_returns_empty_when_dependency_unavailable(monkeypatch: pytest.MonkeyPatch) -> None:
def test_parse_pdf_ocr_returns_empty_when_dependency_unavailable(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""rapidocr 导入失败:降级返回空文本,且把 _ocr_unavailable 置 True 避免重试"""
monkeypatch.setattr("pypdf.PdfReader", _FakePdfReader)
# 故意让 rapidocr_onnxruntime 提供一个非类的 RapidOCR,构造时抛错
@@ -273,7 +284,9 @@ def test_parse_pdf_ocr_returns_empty_when_dependency_unavailable(monkeypatch: py
assert fp_module._ocr_unavailable is True
def test_parse_pdf_ocr_runtime_exception_falls_back_to_empty(monkeypatch: pytest.MonkeyPatch) -> None:
def test_parse_pdf_ocr_runtime_exception_falls_back_to_empty(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""OCR 运行时抛错:仅告警,降级返回空文本(不抛出 ValueError)"""
monkeypatch.setattr("pypdf.PdfReader", _FakePdfReader)
@@ -291,7 +304,9 @@ def test_parse_pdf_ocr_runtime_exception_falls_back_to_empty(monkeypatch: pytest
assert parse_file("scan.pdf", b"fake pdf bytes") == ""
def test_parse_pdf_text_layer_present_skips_ocr(monkeypatch: pytest.MonkeyPatch) -> None:
def test_parse_pdf_text_layer_present_skips_ocr(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""文本层非空:直接返回文本,OCR 引擎不会被实例化"""
call_count = 0
+35 -9
View File
@@ -7,15 +7,28 @@ from datetime import datetime
from typing import Any
from app.config import Settings
from app.core.ingest_tasks import DEDUP_KEY_PREFIX, REDIS_KEY_PREFIX, IngestTaskManager, IngestTaskStatus
from app.core.ingest_tasks import (
DEDUP_KEY_PREFIX,
REDIS_KEY_PREFIX,
IngestTaskManager,
IngestTaskStatus,
)
from app.core.ingestion import IngestionError
from app.models.document import DocumentInput, DocumentSummary, IngestionResult, SummaryLevel
from app.models.document import (
DocumentInput,
DocumentSummary,
IngestionResult,
SummaryLevel,
)
def make_summary() -> DocumentSummary:
"""构造固定的三级总结"""
return DocumentSummary(
l1_summary="一句话总结", l2_outline=None, l3_content_outline="内容大纲", level=SummaryLevel.L3
l1_summary="一句话总结",
l2_outline=None,
l3_content_outline="内容大纲",
level=SummaryLevel.L3,
)
@@ -42,7 +55,9 @@ class FakeIngester:
self.gate: asyncio.Event | None = None
self.started = asyncio.Event()
async def ingest(self, doc: DocumentInput, progress_cb: Callable[[str], None] | None = None) -> IngestionResult:
async def ingest(
self, doc: DocumentInput, progress_cb: Callable[[str], None] | None = None
) -> IngestionResult:
self.calls.append(doc)
self.started.set()
if progress_cb is not None:
@@ -64,7 +79,9 @@ class FakeRedis:
self.writes: list[tuple[str, dict[str, Any], int | None]] = []
self.store: dict[str, dict[str, Any]] = {}
async def set_json(self, key: str, value: dict[str, Any], ttl: int | None = None) -> bool:
async def set_json(
self, key: str, value: dict[str, Any], ttl: int | None = None
) -> bool:
self.writes.append((key, value, ttl))
if self.fail_writes:
raise RuntimeError("redis down")
@@ -105,8 +122,12 @@ async def test_submit_returns_immediately_and_completes() -> None:
async def test_ingestion_error_marks_failed_with_stage_and_partial_summary() -> None:
"""IngestionError:任务 failederror.stage 透传,partial_summary 保留"""
summary = DocumentSummary(l1_summary="L1", l2_outline=None, l3_content_outline="L3", level=SummaryLevel.L3)
ingester = FakeIngester(error=IngestionError("classify", "分类判定失败: boom", summary=summary))
summary = DocumentSummary(
l1_summary="L1", l2_outline=None, l3_content_outline="L3", level=SummaryLevel.L3
)
ingester = FakeIngester(
error=IngestionError("classify", "分类判定失败: boom", summary=summary)
)
manager = IngestTaskManager(ingester, FakeRedis(), Settings())
task_id = await manager.submit(DocumentInput(text="正文"))
@@ -179,10 +200,14 @@ async def test_redis_mirror_ttl_done_and_failed() -> None:
assert done_writes[-1][0]["status"] == IngestTaskStatus.DONE
redis2 = FakeRedis()
failing_manager = IngestTaskManager(FakeIngester(error=RuntimeError("boom")), redis2, settings)
failing_manager = IngestTaskManager(
FakeIngester(error=RuntimeError("boom")), redis2, settings
)
failed_id = await failing_manager.submit(DocumentInput(text="y"))
await failing_manager.wait_done(failed_id, timeout=5)
failed_writes = [(v, ttl) for key, v, ttl in redis2.writes if key.endswith(failed_id)]
failed_writes = [
(v, ttl) for key, v, ttl in redis2.writes if key.endswith(failed_id)
]
assert failed_writes
assert failed_writes[-1][0]["status"] == IngestTaskStatus.FAILED
assert failed_writes[-1][1] == 604800
@@ -275,6 +300,7 @@ async def test_dedup_skipped_when_redis_unavailable() -> None:
async def test_dedup_lookup_failure_falls_back_to_normal_pipeline() -> None:
"""Redis get_json 抛错:去重查询降级为未命中,走原流水线"""
class _ExplodingRedis(FakeRedis):
async def get_json(self, key: str) -> dict[str, Any] | None:
raise RuntimeError("redis down")