Developer Guide#
This guide walks you through setting up a WISER development environment and covers the full contributor workflow from first clone to merged PR.
Reading order for new contributors:
This page — install conda, set up the dev environment, run WISER from source
Contributing & Code Quality — code style, PR process, review standards
Testing & QA — running tests, writing tests, CI
CI/CD and Releases — how releases are built and shipped (see also: macOS Code Signing)
System Design — architecture overview for deeper changes 6Design Documents — longer-form design rationale
Developer Environment Setup#
This section covers environment setup for all platforms — lockfiles, conda environments, dependency management, and platform-specific build and distribution steps.
For macOS code signing, see macOS Code Signing.
Prerequisites#
You will need conda and Python installed. You will need to do
pip install conda-lock and pip install pyyaml. It is recommended to do
this inside a conda environment. You will also need make available in your
terminal. Based on your operating system, look up how to install make.
Lockfiles#
In WISER under /etc there are two very important files for environment setup:
dev-conda-lock.yml and prod-conda-lock.yml. These are the lockfiles for
development and production respectively. You should be very hesitant to change
these files. You should also never directly edit them!
If you want to change the dependencies that these lockfiles have, you will first have to decide if the dependency should go into the prod lockfile or the dev lockfile. Dependencies in the prod lockfile are needed for WISER to run in production. Dependencies in the dev lockfile are needed to run WISER from source on GitHub and do all of the tasks a developer would do — like run the tests or generate Sphinx docs. Then you will have to follow the instructions below for each type of dependency you want to change.
Changing Production (prod) Dependencies#
To change dependencies for production, go into the file etc/wiser-prod.yml and
add the dependency. The dependency will either have to be a dependency on conda
that we can get from conda-forge, or a dependency that we can get from pip. Add
your dependency and version to the .yml file in the appropriate location (under
dependencies if it is from conda, and under pip if it is from PyPI).
It is encouraged to use as accurate a version number as you can (try to use major.minor.patch). We do not want our dependency versions to jump a lot when we add a new dependency. However, having big jumps in dependency versions may be unavoidable for important/large dependencies like Python, but we would still want to do this infrequently. This is important because plugin creators must partially base their plugin dependencies off of WISER’s dependencies.
Changing Development (dev) Dependencies#
To change dependencies for development, first go to the file
etc/wiser-dev-additions.txt and add the dependency either under the
dependencies: line (for conda-forge dependencies) or under the pip: line
for pip dependencies. Follow the example at the top of the file. Note that you
only use one equal sign to specify versions in this file. You would then go to
the root directory and run:
python src/devtools/make_dev_env.py etc/wiser-prod.yml etc/wiser-dev-additions.txt etc/wiser-dev.yml
This command will generate wiser-dev.yml, combining the packages in
wiser-dev-additions with those in wiser-prod.yml. You can also go into the
etc/ folder and run make dev-yaml.
Regenerating the Lock File#
To regenerate the dev lockfile, run conda-lock lock -f wiser-dev.yml and then
rename the lock file to dev-conda-lock.yml. To regenerate the prod lockfile,
run conda-lock lock -f wiser-prod.yml and rename the lockfile to
prod-conda-lock.yml.
You can also go into the etc/ folder and run make create-lockfiles to
create both the dev and the prod lockfiles. To create just the dev lockfile,
run make dev-lockfile; to create just the prod lockfile, run
make prod-lockfile. If you run make dev-lockfile or make create-lockfiles
and the dev .yml file has not been created yet, these commands will create it
first.
Installing Environment from Lockfile#
Once you have the lock files, run:
conda-lock install -n <conda-env-name> dev-conda-lock.yml
where conda-env-name is the name of the conda environment you want to install
into. You can also add --force-platform <OS-name> to specify a target OS. For
example, to build an Intel conda environment on an ARM Mac:
conda-lock install -n wiser-intel --force-platform osx-64 dev-conda-lock.yml
The text osx-64 targets Intel Mac.
If you are on macOS, to fully ensure your conda environment is the right
platform, you may also need to run conda config --env --set subdir osx-64
(for Intel) or conda config --env --set subdir osx-arm64 (for ARM) while
inside the conda environment. These commands only need to be run once.
You can also run make install-dev-env to install the dev conda environment,
or make install-prod-env to install the prod conda environment. On macOS, use
make install-dev-env ENV=intel or make install-dev-env ENV=arm to
explicitly target Intel or ARM. If the dev .yml and lockfiles have not been
created, these install commands will create them first.
Running WISER#
Once you have the above steps done and are in the appropriate conda environment,
go into the src folder and run:
python -m wiser
WISER should start running. If it is your first time running it after your computer has started, it may take a little longer.
Platform-Specific Build & Distribution#
macOS#
You will need conda and Python installed, along with pip install conda-lock
and pip install pyyaml. You will also need make installed. Once you have
all of this, go into the /etc folder and run make install-dev-env. If you
are on an ARM Mac and want your dev environment to target Intel Macs, run
make install-dev-env ENV=intel.
Important Build Targets#
Before you can run WISER, you must generate various files required by the Qt
runtime. These include a resources.py file containing all icons used in the
project, and a number of *_ui.py files which contain UI view code generated
from the corresponding *.ui files created with
Qt Designer. These files are
generated into the src/wiser/gui/generated/ directory.
WISER uses make to automate various build steps. To generate these files, go
to the top directory of the WISER project and run:
# Just typing 'make' will also run the 'generated' target.
make generated
At this point, you should be able to run WISER:
cd src
python -m wiser
Building a Distributable .dmg#
First make sure you are in the wiser-prod conda environment. Create this
environment by going into the /etc folder and running either
make install-prod-env ENV=intel or make install-prod-env ENV=arm depending
on your CPU architecture. Then activate the environment:
conda activate wiser-prod-arm # macOS ARM
conda activate wiser-prod-intel # macOS Intel
Then go back to the top-level directory of the WISER project and build:
make dist-mac
You can test the Mac application like this:
open dist/WISER.app
To clean up all generated files and distributable directories from the top-level directory:
make clean
Windows#
You will need conda and Python installed, along with pip install conda-lock
and pip install pyyaml. You will also need make installed. Once you have
all of this, go into the /etc folder and run make install-dev-env.
How to Install Conda#
Anaconda is a widely used Python package and library manager for Windows and scientific computing. In previous versions of WISER, the full Anaconda3 installation had some issues, but between WISER versions 1.1b1 and 1.4b1 it has worked. If Anaconda does not work for you, use the Miniconda installer.
IDE#
The IDE that WISER is currently developed on is Visual Studio Code, although other IDEs should work as well.
Installer — NSIS#
The Nullsoft Scriptable Install System (NSIS) is used to build the WISER installer. The installer installs at the user level.
Installing on Windows#
As of release 2.1b1, WISER is installed into a versioned location chosen by the installer (Program Files, AppData, or another writable folder). The installer uses versioned registry keys so that multiple different versions of WISER can coexist on the same machine without overwriting each other’s uninstall registration. Uninstalling one version removes only that version’s files, shortcuts, and registry key; other installed versions are unaffected.
WISER writes app data (config files, log files, numba cache) to a location
independent of the install directory and dependent on the WISER version — for
example %LOCALAPPDATA%/WISER-{version} on Windows. If two copies of the same
version are installed, they share that app-data directory.
Code Signing#
To code-sign the WISER installer, the
Windows 10 SDK
needs to be installed so that the SignTool utility is available. Code signing
occurs in /install-win/win-install.nsi. Both the WISER installer and
uninstaller are code-signed. The sign command used in that script is:
"C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool" sign /sha1 "${SHA1_THUMBPRINT}" /fd SHA256 /t http://timestamp.sectigo.com "%1"
where %1 is replaced by the installer filename (e.g. Install-WISER-1.4b1.exe).
Building the Project#
Open an Anaconda terminal window:
Start → “Anaconda3 (64-bit)” → “Anaconda Prompt (Miniconda3)”
Ensure you are in the wiser-prod conda environment. Create it by going to the
/etcfolder and runningmake install-prod-env, then:conda activate wiser-prod
Figure out how to run
makefrom the Anaconda terminal. Using GNU Make:c:\Program Files (x86)\GnuWin32\bin\make.exe
Go to the project directory for WISER, for example:
C:\Users\<username>\WISER
Clean up any existing build artifacts.
This is currently a manual process because the
cleantarget does not work on Windows yet.Delete these items:
build directory dist directory Install-WISER-*.exe src\wiser\gui\generated\*.py
Build the project:
"c:\Program Files (x86)\GnuWin32\bin\make.exe" dist-win
This should result in the creation of an NSIS installer in the local directory.
NOTE: On Python 3.9 and PySide2 5.13.2, uiparser.py (at
C:\ProgramData\Miniconda3\Lib\site-packages\pyside2uic\uiparser.py) has a
call to elem.getiterator() on line 797 that must be changed to elem.iter().
That file requires Administrator permissions to edit. WISER does not currently
use PySide2 5.13.2, but this is noted for reference.
Linux#
You will need conda and Python installed, along with pip install conda-lock
and pip install pyyaml. You will also need git and make installed, and
build-essential is recommended. Once you have all of this, go into the /etc
folder and run make install-dev-env.
Supported Distributions and Architectures#
WISER builds target Ubuntu 20.04, Debian 11, and Fedora 39. Builds should generally work on future versions of these distributions due to their backwards compatibility goals. Supported Instruction Set Architectures (ISAs) are amd64 (x86_64) and aarch64 (arm64).
Development has been tested on Ubuntu 22.04.5 amd64. The instructions below should work for other Linux distributions.
How to Install Conda on Linux#
Follow the instructions at https://www.anaconda.com/docs/getting-started/miniconda/main to install Miniconda. Then follow the Installing Environment from Lockfile section above to set up your conda environments.
How to Build WISER#
Once you have your conda environments set up, activate the wiser-prod
environment and run make build-linux from the root directory of the
repository. This produces a Linux build targeting your current distribution
and ISA.
It is recommended to use the GitHub Action to create your Linux build, as it
handles dynamic library dependency issues that you will likely encounter when
building locally with make build-linux.
The build output is placed under /dist. To test it, go to /dist/WISER and
run:
./WISER_Bin
Continuous Deployment#
Official WISER releases for Linux are produced by the GitHub Action
Build and Smoke WISER. The process:
A matrix strategy runs jobs in parallel targeting Ubuntu 20.04 + amd64, Debian 11 + amd64, Fedora 39 + amd64, Ubuntu 20.04 + arm64, Debian 11 + arm64, and Fedora 39 + arm64.
For each target,
./build_linux_multistage.shis run with the OS and ISA, which runs the corresponding Docker bake target indocker_bake.hcl. The Dockerfile produces an output artifact at/app/WISER.tar.gzin the container../build_linux_multistage.shcopies/app/WISER.tar.gzto the host. It contains:install_wiser_appimage.sh— installs the .AppImage on the user’s machineRUN.txt— directions for running WISERSHA256SUMS— SHA256 for verifyingWISER-x86_64.AppImageWISER-x86_64.AppImage— the actual application
The GitHub Action uploads
WISER.tar.gzto GitHub. Note that the upload always re-zips the file, which is slightly redundant since it is already compressed.
Other Useful Tools#
GitHub CLI Tool#
The GitHub CLI Tool provides the gh command, which is used to download and
sign artifacts from the deployment pipeline. Installation instructions can be
found at https://github.com/cli/cli#installation.
Listing Out Dependencies from Lockfile#
You may need to create a .yml file to show end users what production dependencies WISER has. Run:
conda-lock render --kind env -p osx-64 -p osx-arm64 -p win-64 prod-conda-lock.yml
This prints the dependencies for the specified platforms. Excluding all
-p <OS-version> arguments will automatically create .yml files for all
operating systems that prod-conda-lock.yml supports.
NOTE: The .yml files produced by conda-lock render cannot be
substituted for the conda-lock.yml files. Installing a conda environment based
on those rendered .yml files is not always reproducible.