Author: André Lacasse
Welcome to the Points Tax Calculator API! I've been working for a few years as a python dev but I never had the chance to start a project from scratch. So this is a first and in any cases, I thank you for the opportunity, it was fun. I used the opportunity to try to use newer libraries and to better myself at knowing how to plug the different pieces of a project. I wanted as much as possible to start it like a real world project. I’m proud of the result and hope you find it interesting.
- Flask-based REST API
- Interactive Swagger UI documentation
- Redis caching for tax bracket data
- Asynchronous HTTP calls with HTTPX
- Comprehensive testing with pytest and plugins
- Containerized development and testing with Docker
-
Clone the repository and navigate into it:
git clone [email protected]:alacasse/points-test.git cd points-test/
-
Configure the tax service URL in
docker-compose.yml:environment: TAX_SERVICE_URL: http://host.docker.internal:5001/tax-calculator
-
Start the application:
make start
-
Browse the API docs at http://localhost:5000/api/docs.
make testsmake logs| Variable | Description |
|---|---|
FLASK_ENV |
development or testing; toggles debug mode and error pages |
REDIS_URL |
URL for the Redis instance (e.g. redis://redis:6379/0) |
USE_REDIS |
true/false to enable or disable caching in the tax service |
TAX_SERVICE_URL |
Base URL of the external tax calculation API |
TAX_SERVICE_TIMEOUT |
Initial timeout (seconds) for external API calls |
TAX_SERVICE_TIMEOUT_INCREASE_FACTOR |
Multiplier to increase timeout after each retry |
TAX_SERVICE_TIMEOUT_RETRY_AMOUNT |
Number of retry attempts before giving up on the external service |
Note:
REDISis enabled by default. To test logging and error handling without caching, setUSE_REDIS=false.
A lightweight, pre-forking WSGI HTTP server used in production to manage multiple worker processes for handling requests.
A framework around the OpenAPI spec that provides interactive API documentation and code generation tools.
A micro web framework that’s simple to use and ideal for small to medium APIs.
A Flask extension that allows annotating routes with OpenAPI specs (YAML or docstrings) and serves a Swagger UI automatically.
Used to cache external tax bracket data (which is static and occasionally unreliable) with a 24‑hour TTL, reducing flakiness and latency.
An async-capable HTTP client library that supports HTTP/1.1 and HTTP/2, chosen for its modern API and performance.
A powerful testing tool with a simple syntax, along with plugins:
- pytest-flask: simplifies Flask app testing (test client, context).
- pytest-asyncio: enables testing of
asyncfunctions.
Convenience commands (make start, make tests, make logs) for a smooth developer experience.
Tests run inside Docker to guarantee the same environment as production and avoid discrepancies between local venvs and containerized deployments.
To speed up builds:
-
Added a
.dockerignore. -
Enabled BuildKit and Compose v2 bake via
.envvariables:DOCKER_BUILDKIT=1 COMPOSE_BAKE=1
- Bracket-level taxes may not sum exactly to the total due to rounding.
- Redis is disabled during unit tests; Redis-specific tests are TODO.
- More edge-case tests could be added.