Contributing to AequilibraE for QGIS#
This page presents some initial instructions on how to setup your system to start contributing to QAequilibraE and lists the requirements for all pull-requests to be merged into main.
Software Design and requirements#
QAequilibraE is built on top of AequilibraE’s main features, and the most important piece of AequilibraE’s backend is, without a doubt, NumPy.
The user might not see or know, but whenever vectorization is not possible through the use of NumPy functions, compiled code written in Cython is developed in order to accelerate computation.
QAequilibraE also observes a strong requirement of only using libraries that are available in the Python installation used by QGIS on Windows.
We have not yet found an ideal source of recommendations for developing QAequilibraE, but a good initial take can be found in this article.
Please notice that QAequilibraE installation MUST WORK at least in the most recent long-term release (LTR).
Development Install#
We recommend using a dedicated virtual environment to develop QAequilibraE, using the version of Python related to the most recent QGIS long-term release. When this section was updated (November/2024), LTR 3.34.12 was coming with a default 3.12.7 Python environment.
We also assume you are using one of PyCharm or VSCode, which are good IDEs for Python. If you are using a different IDE, we would welcome if you could contribute with instructions to set that up.
(For us,) The easiest way of developing a QGIS plugin is using a Docker container to build an image containing
a QGIS installation. When cloning QAequilibraE repository into your local machine you will find a Dockerfile
with this recipe.
git clone https://github.com/AequilibraE/qaequilibrae.git
Then all you have to do is create a virtual environment, and proceed with the requirements’ installation. We understood that the creation of a virtual development environment within a container would be redundant, however after facing some developing issues related to PEP 668, we believe that using a virtual environment would be a good practice.
python3 -m venv .venv --system-site-package
. .venv/bin/activate
python3 -m pip install - U pip setuptools uv
python3 -m pip install -r test/requirements_test.txt
python3 ./ci/dependency_installation.py
export PYTHONPATH=$(pwd)/qaequilibrae/packages:$PYTHONPATH
export QT_QPA_PLATFORM=offscreen
Development Guidelines#
QAequilibraE development (tries) to follow a few standards. A huge effort is being undertaken by the development team to update several portions of the code are still not up to such standards.
Style#
Python code should follow (mostly) the pycodestyle style guide.
Python docstrings should follow the reStructuredText Docstring Format.
We are big fans of auto-code formatting. For that, we use Black.
Negating some of what we have said so far, we use maximum line length of 120 characters.
Imports#
Imports should be one per line.
Imports should be grouped into standard library, third-party, and intra-library imports.
Imports of NumPy should follow the following convention:
import numpy as np
Translatable Strings#
If you are adding or modifying any piece of QAequilibraE’s code that includes translatable strings, which are the
strings displayed in the widget windows, please ensure you use the tr
function to locate the strings. This will
guarantee that the strings are included in our future translations. Currently, only classes that have a self
method
support the localization of strings.
# Indicates that the message "You need at least three centroids to route. " will be
# set for translation.
qgis.utils.iface.messageBar().pushMessage(self.tr("You need at least three centroids to route. "), "", level=3)
# In case you have to insert any text into a string, the best way is to use string format
self.error = self.tr("ID {} is non unique in your selected field").format(str(id))
Strings in QAequilibraE Processing Provider can also be translated. To indicate the strings, import the translation function and configure it to return the context and the message.
from qaequilibrae.i18n.translate import trlt
class YourClassHere():
...
# YourClassHere functions
...
def processAlgorithm(self, parameters, context, model_feedback):
...
feedback.pushInfo(self.tr("Running assignment")) # indicates the translatable string
...
def tr(self, message):
return trlt("TrafficAssignYAML", message)
As for November 2024, QAequilibraE’s translations are all hosted in Transifex. Currently, we are targeting translations in Brazilian Portuguese, Chinese, French, German, Italian, and Spanish. If you want to contribute to QAequilibraE by translating the plugin to other languages or reviewing the existing translations, please let us know in our AequilibraE Google Group, so we can add your language to our translation pool!
In the plugin internationalization page, you can find more information on creating your account and start translating QAequilibraE.
Contributing to AequilibraE for QGIS#
GitHub has a nice visual explanation on how collaboration is done GitHub Flow. (For us,) The most important points there are:
The main branch contains the latest working/release version of QAequilibraE
Work is done in an issue/feature branch (or a fork) and then pushed to a new branch
Automated testing is run using Github Actions. All tests must pass:
Unit testing
Build/packaging tests
Documentation building test
If the tests pass, then a manual pull request can be approved to merge into main
The main branch is protected and therefore can only be written to after the code has been reviewed and approved
No individual has the privileges to push to the main branch
Release versions#
QAequilibraE uses the de-facto Python standard for versioning
MAJOR.MINOR[.MICRO]
MAJOR designates a major revision number for the software. Usually, raising a major revision number means that you are adding a lot of features, breaking backward-compatibility or drastically changing the API.
MINOR usually groups moderate changes to the software like bug fixes or minor improvements. Most of the time, end users can upgrade with no risks their software to a new minor release. In case an API changes, the end users will be notified with deprecation warnings. In other words, API stability is usually a promise between two minor releases.
Some software use a third level: MICRO. This level is used when the release cycle of minor release is quite long. In that case, micro releases are dedicated to bug fixes.
QAequilibraE’s development is happening mostly within the Minor and Micro levels.
Testing#
QAequilibraE testing is done with some tools:
Black, the uncompromising code formatter
pytest, a Python testing tool
pytest-cov, a tool for measuring test code coverage
pytest-qt, a tool for testing PyQt5 applications
pytest-qgis, a tool for writing QGIS tests
To run the tests locally, you will need to figure out what to do…
These same tests are run by GitHub Actions with each push to the repository. These tests need to pass in order to somebody manually review the code before merging it into main (or returning for corrections).
In some cases, test targets need to be updated to match the new results produced by the code since these
are now the correct results. In order to update the test targets, first determine which tests are
failing and then review the failing lines in the source files. These are easy to identify since each
test ultimately comes down to one of Python’s various types of assert
statements. Once you identify
which assert
is failing, you can work your way back through the code that creates the test targets in
order to update it. After updating the test targets, re-run the tests to confirm the new code passes all
the tests.
Documentation#
All the QAequilibraE documentation is (unfortunately) written in reStructuredText and built with Sphinx. Although reStructuredText is often unnecessarily convoluted to write, Sphinx is capable of converting it to standard-looking HTML pages, while also bringing the docstring documentation along for the ride.
To build the documentation, first make sure the required packages are installed:
pip install sphinx pydata-sphinx-theme sphinx-design sphinx-panels sphinx-subfigure
Next, build the documentation in HTML format with the following commands run from the root
folder:
cd docs
make html
Finally#
A LOT of the structure around the documentation was borrowed (copied) from the excellent project ActivitySim.