[build-system] requires = ["setuptools>=68", "wheel"] build-backend = "setuptools.build_meta" [project] name = "ocr-sprint-service" version = "0.1.0" description = "OCR service for Indonesian police 'surat sprint' documents (FastAPI + PaddleOCR + hybrid extraction)" readme = "README.md" requires-python = ">=3.10,<3.13" license = { text = "Proprietary" } authors = [{ name = "Adrian Kuman Firmansah" }] dependencies = [ # Web framework "fastapi>=0.115,<0.116", "uvicorn[standard]>=0.30,<0.34", "python-multipart>=0.0.9", "pydantic>=2.7,<3", "pydantic-settings>=2.4,<3", # Image / PDF "pillow>=10.4,<12", "opencv-python-headless>=4.10,<5", "numpy>=1.26,<2.2", "PyMuPDF>=1.24,<2", "python-magic>=0.4.27", # Logging / observability "structlog>=24.1", "prometheus-client>=0.20", # Async pipeline + persistence (Phase 4) "celery[redis]>=5.4", "redis>=5.0", "sqlalchemy>=2.0", "psycopg[binary]>=3.2", "alembic>=1.13", # Misc "httpx>=0.27", "tenacity>=8.5", ] [project.optional-dependencies] dev = [ "pytest>=8.2", "pytest-asyncio>=0.23", "pytest-cov>=5.0", "ruff>=0.6.9", "mypy>=1.11", "types-Pillow", "pre-commit>=3.7", ] # OCR runtime — kept as an optional extra so unit tests / dev installs don't # pull ~1.5 GB of Paddle wheels. Install via `pip install -e ".[ocr]"` on # the worker host. CPU build by default; GPU users override the index URL. ocr = [ "paddlepaddle>=2.6.2,<4", "paddleocr>=2.7.5,<3", ] # Extraction layer (Phase 5) — kept optional so MVP install stays light llm = [ "ollama>=0.3", "instructor>=1.4", ] [project.scripts] ocr-sprint-api = "ocr_sprint.main:run" [tool.setuptools.packages.find] where = ["src"] [tool.setuptools.package-data] "ocr_sprint" = ["py.typed"] # ---------- Tooling ---------- [tool.ruff] line-length = 100 target-version = "py310" src = ["src", "tests"] [tool.ruff.lint] select = [ "E", "F", "W", # pycodestyle / pyflakes "I", # isort "B", # bugbear "UP", # pyupgrade "SIM", # simplify "RUF", # ruff-specific "C4", # comprehensions "PIE", "PT", # pytest style "TID", # tidy imports ] ignore = [ "E501", # line length handled by formatter "B008", # FastAPI Depends() pattern ] [tool.ruff.format] quote-style = "double" [tool.mypy] python_version = "3.10" strict = true warn_unused_ignores = true warn_redundant_casts = true disallow_untyped_defs = true plugins = ["pydantic.mypy"] mypy_path = "src" namespace_packages = true explicit_package_bases = true [[tool.mypy.overrides]] module = ["paddleocr.*", "paddle.*", "cv2.*", "fitz.*", "magic.*", "celery.*", "kombu.*"] ignore_missing_imports = true [tool.pytest.ini_options] minversion = "8.0" addopts = "-ra --strict-markers --strict-config" testpaths = ["tests"] asyncio_mode = "auto" filterwarnings = [ "ignore::DeprecationWarning:paddle.*", "ignore::DeprecationWarning:paddleocr.*", ] [tool.coverage.run] source = ["src/ocr_sprint"] branch = true [tool.coverage.report] exclude_lines = [ "pragma: no cover", "raise NotImplementedError", "if TYPE_CHECKING:", ]