PyWorkout — Development¶
Local Setup¶
An editable install means pyworkout on your PATH runs your working copy, so edits take effect immediately. To skip installing altogether, python main.py works just as well.
Development tooling — pytest, pytest-cov, pytest-mock, pylint, build — is not pulled in by the editable install:
Architecture in Brief¶
Almost all of PyWorkout is a single workout() function in main.py, roughly 600 lines. That is deliberate: the program is simple, and one readable function beats an abstraction layer nobody needs.
Two consequences worth knowing before you edit:
State lives in module-level globals set inside workout() — select (chosen muscle group), activity_num (current exercise), start (start time), complete (finished exercises), and times (per-exercise durations). Pylint objects to this; the file silences those specific warnings with inline # pylint: disable= comments. That is the established pattern here — please follow it rather than adding a .pylintrc.
Workout data is parallel lists. Each muscle group has a list of exercise names and a matching _count list of reps, and the two are index-aligned. Adding an exercise means appending to both, and updating the bounds check in the next branch. Configuration walks through this step by step.
gui.py is an unfinished Tkinter frontend. It is not connected to main.py and does not run — do not treat it as a reference for how the application behaves.
Everyday Commands¶
# Run the CLI
python main.py
# Run the tests
pytest tests/ -v
# Tests with coverage
pytest tests/ --cov=. --cov-report=term-missing
# Lint
pylint $(git ls-files '*.py')
# Build the distributable packages
python -m build
Testing covers the suite in more detail.
Conventions¶
- Comments. The codebase comments heavily. Match that when you touch
main.py. - No runtime dependencies. PyWorkout uses only the standard library. Please keep it that way — it is why the executable build stays small and the Docker image stays simple.
- Versioning. Semantic versioning. The version appears in both
setup.cfgandpyproject.toml; update them together.
Continuous Integration¶
Five workflows run in GitHub Actions:
| Workflow | Trigger | Does |
|---|---|---|
tests.yml |
Push or PR to main/develop |
pytest on Python 3.9–3.12, uploads coverage |
pylint.yml |
Every push | Pylint on Python 3.9 |
docker-publish.yml |
Push to main, tags, PRs, daily |
Builds and pushes the image to ghcr.io |
push-to-pypi.yml |
Release published | Builds and publishes to PyPI |
codeql-analysis.yml |
Push, PRs, schedule | Security scanning |
Releasing¶
- Bump the version in
setup.cfgandpyproject.toml. - Update
CHANGELOG.md. - Tag and push:
git tag v1.2.0 && git push --tags. - Publish a GitHub Release.
push-to-pypi.ymlhandles PyPI from there;docker-publish.ymlpushes the tagged image.