Skip to content

Mom's Canning Timer — Architecture

Layout

main.py                          run from a clone, no install
src/moms_canning_timer/
├── __main__.py                  python -m moms_canning_timer
├── app.py                       the window and the 2x2 grid
├── widget.py                    one burner: ring, entry, buttons
└── state.py                     timer state, with no GUI knowledge

Packaged with a src/ layout and published to PyPI as moms-canning-timer, with a canning-timer console script.

State is separate from the widget

state.py holds the countdown logic — duration, elapsed, running, paused — and knows nothing about tkinter. widget.py renders one burner and drives that state.

That split is what makes the timers testable. tests/test_state.py exercises the logic directly with no display at all, which is why the suite can run in CI where no window can be opened.

It also means the four burners are genuinely independent: each has its own state object, so pausing one has no effect on the others.

No third-party dependencies

requirements.txt pulls in nothing at runtime. tkinter is standard library.

That is a deliberate constraint rather than an accident of a small program. It means the app installs on a machine with no compiler and no network, starts instantly, and cannot be broken by a dependency update — appropriate for something opened in a kitchen while jars are boiling.

Adding a dependency should be weighed against losing that.

Three ways in, one program

Entry point For
main.py Running from a clone with nothing installed
canning-timer The console script from pip install
python -m moms_canning_timer The module form

All three reach the same application.

The finish alert

A bell plus a popup. The popup requires dismissal, which is the point — a timer that finishes while you are across the room should still be obvious when you come back.

Testing

tests/gui_support.py provides the scaffolding that lets widget tests run without a real display. See Testing.

CI

Four workflows: pytest, pylint, CodeQL analysis, and publish-to-PyPI on release.