The Python Engineering Lab is a completed, hands-on software engineering project. I built a workout-tracking application step by step to strengthen my Python and backend engineering skills.
Rather than completing ten unrelated tutorials, I developed one application through ten stages. It began as a small service that could receive and return workout data. With each stage, I added a capability expected in real software: input validation, automated tests, database storage, search, pagination, file imports, scheduled tasks, caching, and text processing.
The result demonstrates how I approach engineering work:
- I break a larger system into manageable, clearly defined increments.
- I write the first solution myself to understand the underlying mechanics.
- I test behavior and handle invalid or incomplete data deliberately.
- I structure code so that new features can be added without rewriting the whole application.
- I document both the result and the lessons learned.
All ten stages are complete. ✅
The application records activities such as running, swimming, cycling, badminton, strength training, and rest days.
It was intentionally built around a familiar topic so that the engineering decisions remain easy to see. For example, different activities require different information: a run needs distance and duration, strength training needs a duration, and a rest day needs neither. The application therefore has to understand context, reject incomplete entries, and handle optional information safely.
By the final stage, a user can:
- add and view workouts;
- receive clear feedback when information is missing or invalid;
- search, filter, and browse larger sets of results;
- import several workouts from a CSV file;
- enter a workout as ordinary text for the application to interpret;
- rely on automated tests to verify that the system behaves correctly.
Behind the scenes, workouts are stored in a database, repeated requests are served efficiently through caching, and scheduled jobs can run without a user having to trigger them.
My goal was not simply to produce another finished application. I wanted to consolidate the foundations behind reliable backend systems by implementing each capability from scratch and understanding how the parts work together.
Every stage has its own folder and documentation. The notes include what I learned, what caused difficulty, and which decisions I deliberately postponed. This makes the repository both a working codebase and a transparent record of my engineering process.
The application separates responsibilities into clear layers:
- A user or another application sends a request.
- The Flask API receives it, checks the input, and returns a response.
- Reusable application logic handles searching, importing, scheduling, caching, and text extraction.
- A dedicated data-access layer manages all communication with the SQLite database.
- Automated tests check the complete API behavior.
This separation matters because each part can evolve independently. For example, a scheduled job can reuse the same database functions as the API without duplicating storage logic.
| Stage | Capability added | Why it matters in a real product | Engineering focus |
|---|---|---|---|
| 01 — REST API | Add and retrieve workouts | Allows a website, mobile app, or other system to exchange data with the application | Flask, HTTP, JSON |
| 02 — Validation & Error Handling | Check input and return clear errors | Protects data quality and gives users useful feedback | Validation rules, error responses |
| 03 — Automated API Tests | Verify expected and unexpected behavior | Reduces the risk that future changes break existing features | pytest, fixtures, test client |
| 04 — Database Storage | Save workouts permanently | Keeps information available after the application restarts | SQLite, SQL, data-access layer |
| 05 — Search & Filtering | Find workouts by relevant criteria | Helps users retrieve useful records from growing datasets | Query parameters, dynamic queries |
| 06 — Pagination | Return large result sets in smaller pages | Keeps responses manageable and efficient | Result limits, offsets, metadata |
| 07 — CSV File Import | Import multiple workouts together | Replaces repetitive manual entry and supports existing data | File uploads, CSV processing |
| 08 — Scheduled Background Jobs | Run recurring work automatically | Supports tasks that should happen without a user request | Scheduling, background processing |
| 09 — Caching | Reuse frequently requested results | Improves response speed and reduces unnecessary database work | Cache strategy, invalidation |
| 10 — Text Parsing | Turn ordinary text into structured workouts | Makes data entry faster and more natural | Regular expressions, information extraction |
The project uses Python 3.12, Flask, SQLite, pytest, and APScheduler. Most functionality relies on Python's standard library, including CSV processing and regular expressions. Dependencies were introduced only when a stage genuinely required them.
From stage 04 onward, the database code lives in a dedicated db.py
data-access layer. Flask routes manage web requests, while db.py manages
storage. This keeps responsibilities clear and allows features such as
background jobs to reuse the same database operations.
Python 3.12 or newer is required.
git clone https://github.com/ajitagupta/python-engineering-lab.git
cd python-engineering-lab
python -m venv .venv
.venv\Scripts\activate # macOS/Linux: source .venv/bin/activateEach numbered folder contains its own README with dependencies and run instructions. Reading the folders in order shows how the application evolved from a basic endpoint into a small but complete backend system.
A completed learning-in-public project: ten carefully understood engineering concepts, combined into one working application.
