An application to show the time in multiple timezones. It is built in Python using the PyQt5 GUI framework and packaged as a macOS application with py2app.
The project uses uv to manage Python, the virtual
environment, and dependencies. Dependencies are declared in pyproject.toml
and pinned in uv.lock, which should both be committed. The Python version is
set in .python-version.
Install uv (for example with Homebrew):
brew install uvThen, from the project directory, create the virtual environment and install all dependencies:
make setup-devThis runs uv sync, which creates a .venv directory in the project and
installs everything from uv.lock, including the development dependencies
needed to build the app.
Run the application from source with:
make runor, equivalently:
uv run python Clock.pyuv run always uses the project's .venv, so there is no need to activate it
first. If you prefer working inside the environment, activate it with
source .venv/bin/activate and leave it with deactivate.
Add or remove dependencies with uv rather than editing pyproject.toml by hand,
so the lock file stays in sync:
uv add <package> # runtime dependency
uv add --dev <package> # development/build dependency
uv remove <package>To upgrade packages within the constraints in pyproject.toml, run
uv lock --upgrade (or uv lock --upgrade-package <package> for just one),
followed by uv sync.
If the app fails to start with an error that Qt could not find the cocoa
platform plugin, the cached copy of the Qt packages may be damaged. Clear them
from the uv cache and reinstall:
uv cache clean pyqt5 pyqt5-qt5 pyqt5-sip
uv sync --reinstall-package pyqt5 --reinstall-package pyqt5-qt5 --reinstall-package pyqt5-sipThe timezones shown are read from a JSON configuration file at ~/.clock.json.
If the file does not exist, it is created on first launch with these defaults:
{
"ui_settings": {},
"timezones": [
["JST", "Asia/Tokyo"],
["UTC", "UTC"],
["ET", "US/Eastern"]
]
}Each timezone entry is a pair of the label displayed in the window and an
IANA timezone name.
Edit this file to change which timezones appear. The defaults in
clockui/AppConfig.py are only used when the file is first created.
The application is built with py2app, which is installed as a development
dependency by make setup-dev. For local testing, build an alias bundle with:
make dist-testThis builds a macOS application package in ./dist that references the source
modules in the development environment instead of copying them in. It builds
very quickly and can be built and launched in one step with:
make run-dist-testWhen ready to test and distribute the final app, build the full application with:
make distThis creates a self-contained macOS application in ./dist that can be run as a
normal app, installed in the Applications directory, or run from the Desktop.
Use make run-dist to build and open it in one step.
setuptoolsis pinned below version 81 in the development dependencies because py2app, on Python 3.9, still relies on thepkg_resourcesmodule that newer setuptools releases have removed.setup.pyincludes a small subclass of the py2app command that clearsinstall_requires. setuptools fills that field from the dependencies inpyproject.toml, and py2app refuses to build when it is set. Dependencies are handled by uv, and py2app finds what to bundle by tracing the imports inClock.py.
Run make or make help to list the available targets.
| Target | Description |
|---|---|
setup-dev |
Create the .venv and install dependencies with uv |
run |
Run the clock app from the Python source |
dist-test |
Build a test application bundle in dist/ that links to source |
run-dist-test |
Build and run the test application bundle |
dist |
Build a full application package in dist/ |
run-dist |
Build and open the full application |
clean |
Remove the build/ and dist/ directories |
uninstall |
Remove build/, dist/, and the .venv |
- TBD
The source code is built for Python 3 and includes type annotations and type hinting. Documentation mostly follows the numpy style conventions.
Created By: Brian McLaughlin ([email protected])