|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +## Project Overview |
| 4 | +A RESTful API that serves predictions from a trained ML model, built with Python 3 and Flask-RESTX. |
| 5 | + |
| 6 | +## Environment |
| 7 | +- Python 3.13 (venv at `venv/`) |
| 8 | +- Activate venv: `source venv/Scripts/activate` (bash on Windows) |
| 9 | + |
| 10 | +## Quality Gate |
| 11 | +Run before committing: |
| 12 | +``` |
| 13 | +powershell.exe -File make.ps1 |
| 14 | +``` |
| 15 | +Checks: black (formatter) → pylint → mypy. Must score 10.00/10 and zero mypy errors. |
| 16 | + |
| 17 | +## Dependencies |
| 18 | +- `requirements.txt` — pinned runtime deps (Flask, flask-restx, numpy, pandas, loguru, etc.) |
| 19 | +- `requirements-dev.txt` — dev tools (black, pylint, mypy) |
| 20 | +- `tests/requirements.txt` — test deps (pytest, requests, openapi-spec-validator) |
| 21 | +- Update all three when installing new packages in the venv |
| 22 | + |
| 23 | +## Git Workflow |
| 24 | +- Branch: `master` |
| 25 | +- Remote: `https://github.com/jgbustos/ml_rest_api.git` |
| 26 | +- Git user email: `35463898+jgbustos@users.noreply.github.com` (GitHub no-reply, required to push) |
| 27 | +- Run quality gate before every commit |
| 28 | +- Never commit `.claude/` directory |
| 29 | + |
| 30 | +## Key Architecture Decisions |
| 31 | + |
| 32 | +### Logging (loguru) |
| 33 | +- Entry point: `ml_rest_api/logging_setup.py` → `setup_logging()` |
| 34 | +- Called once in `app.py` after `Flask(__name__)` |
| 35 | +- `InterceptHandler` redirects all stdlib `logging` calls to loguru |
| 36 | +- Multi-line log messages are split per line so each gets a loguru header |
| 37 | +- `click.echo` and `click.secho` are monkey-patched to capture Flask/Werkzeug `* startup lines` |
| 38 | +- All modules keep using `getLogger(__name__)` — no need to import loguru directly |
| 39 | + |
| 40 | +### CSRF Protection |
| 41 | +- `CSRFProtect` is bound to the app in `initialize_app()` after `configure_app()` |
| 42 | +- Controlled via `WTF_CSRF_ENABLED` setting (default: `True`) |
| 43 | + |
| 44 | +### Type Annotations |
| 45 | +- Use built-in generics (`dict[str, Any]`, `list[str]`) not `typing.Dict`/`typing.List` |
| 46 | +- flask-restx has incomplete stubs — suppress with `# type: ignore` at import and decorator sites |
| 47 | +- Pylance strictness is high; suppress false positives with `# type: ignore[specific-code]` |
| 48 | + |
| 49 | +### ML Model |
| 50 | +- Model module loaded dynamically via `TrainedModelWrapper` in `wrapper.py` |
| 51 | +- Module name configured via `TRAINED_MODEL_MODULE_NAME` env var or settings |
| 52 | +- `ml_trained_model.py` is the default/example model module |
| 53 | + |
| 54 | +## Docker |
| 55 | +- `Dockerfile` uses `ENTRYPOINT ["python3"]` + `CMD ["ml_rest_api/app.py"]` |
| 56 | +- `docker-compose.yml` `command` must only pass the script path, not `python3` again |
| 57 | +- `.dockerignore` excludes: venv, tests, nginx, docker-compose, CI config, dev requirements |
| 58 | + |
| 59 | +## CI/CD |
| 60 | +- CircleCI config: `.circleci/config.yml` |
| 61 | +- Python image: `cimg/python:3.13` |
| 62 | +- Cache key: `v1-dependencies-py313-...` |
| 63 | +- Requires a CircleCI checkout key (User Key via GitHub OAuth) |
0 commit comments