Info for Contributors
January 29, 2025 ยท View on GitHub
Setup with uv
Dependencies are managed strictly using uv, and the
uv.lock lockfile
is checked into source, to ensure a reproducible environment for all developers.
The lockfile also dictates the exact dependencies that will go into the bundled
application.
To get started, make sure you have uv installed, then run
git clone https://github.com/pymmcore-plus/pymmcore-gui.git
cd pymmcore-gui
uv sync
That will create a virtual environment at .venv in the root directory, and
install all dependencies. Note: uv sync will also install
python for you if necessary,
so you don't need to have it installed before running the command.
At any time, you can re-run uv sync to ensure that your
current environment matches the requirements specified in uv.lock.
Note
The lockfile itself shouldn't be manually edited, but if you need to
modify the constraints of the dependencies, you should do so as usual
in pyproject.toml, and then run uv lock to update the lockfile, then
commit it and open a PR.
Pre-commit hooks
We use pre-commit to run code checks on CI. These
checks are defined in .pre-commit-config.yaml. If
you want to catch errors locally before pushing to github, you can install the
pre-commit hooks with:
pre-commit install
To run the tests manually at any time, you can use:
pre-commit run --all-files
Activating the virtual environment (optional)
If you want to activate the virtual environment to run commands directly (without
preceding everything with uv run), run:
On windows:
.venv\Scripts\activate
On linux/mac:
source .venv/bin/activate
Python version support
The "primary" version of python that we target at any time is defined in
.python-version. This is the version that will be installed by uv if it's
not already present on your system. We also test against all versions greater
than the minimum version defined in pyproject.toml under the
[project.requires-python] section.
Running the GUI
To run the GUI, just run
uv run mmgui
(or... just mmgui if you've activated your virtual
environment)
Tip
This script is defined in pyproject.toml under the [project.scripts] section.
Testing
You can run the tests with
uv run pytest
(or... just pytest if you've activated your virtual
environment)
Creating a bundled application
We use PyInstaller to freeze the application into a
single, double-clickable executable. The configuration for PyInstaller is
defined in app/mmgui.spec.
Tip
For details pyinstaller and the mmgui.spec file, see the PyInstaller
documentation.
Locally
To create a bundled application locally , run
uv run pyinstaller app/mmgui.spec
Or, if you have just installed, you can use
the bundle task defined in justfile:
just bundle
This will create a double-clickable application in the dist/ directory.
On CI (for distribution)
The bundled application is also created on CI using GitHub Actions (it runs on
every push to main, and even for pull-requests). The workflow is defined in
.github/workflows/bundle.yml.
You can download the latest build artifacts from main branch
here
For a list of all bundles created (including those from PRs), see the GitHub Actions page for the bundle workflow. Click on any given run, and you'll see the artifacts produced by that run at the bottom.
Settings and Configuration
We use
pydantic-settings
to manage settings for the application.
Loading of user preferences and settings is done in pymmcore_gui/settings.py,
from the following sources, in order of decreasing precedence:
-
Values passed directly to the
Settings()constructor (highest precedence) -
Environment variables starting with
PMM_ -
User settings stored in a
USER_DATA_DIR/settings.jsonfile. (lowest precedence).USER_DATA_DIRis determined in a platform-specific way usingplatformdirs.user_data_dirwith the appnamepymmcore-gui.- Windows: C:\Users\[user]\AppData\Local\pymmcore-gui\pymmcore-gui
- macOS: ~/Library/Application Support/pymmcore-gui
- Linux: ~/.local/share/pymmcore-gui
Additional sources could be added in the future (e.g. a system-wide settings, in addition to user-specific settings). See documentation for pydantic-settings for more information.
Settings Schema Versioning
The settings schema is versioned, and the version is stored in the settings. We aim to be backwards-compatible with older settings files (i.e. we should always be able to load settings from an older version of the schema) and, when possible, forward-compatible (i.e. we should be able to load settings from a newer version of the schema, even if we don't understand all the new fields).
One must bump the schema version for any breaking changes. Breaking changes include:
- Renaming or removing a setting
- Changing the type of a setting
- Adding a new required setting (without a default value). Note: all settings should have a default value... so this should not happen.