# Contributing to scikit-decide
We welcome all contributions to scikit-decide.
You can help by:
- fixing bugs (see issues (opens new window) with label "bug"),
- adding new domains or solvers to the hub in
skdecide/hub/
, - improving the documentation,
- adding and improving educational notebooks in
notebooks/
.
This is not exhaustive.
The project is hosted on https://github.com/airbus/scikit-decide (opens new window). Contributions to the repository are made by submitting pull requests.
This guide is organized as follows:
- Setting up your development environment
- Guidelines to follow when preparing a contribution
- Submitting pull requests to put your contribution in the main repository
# Setting up your development environment
# Installing from source in developer mode
Disclaimer: The following process has only been tested on Linux/MacOS platforms.
In order to install scikit-decide from the source so that your modification to the library are taken into account, we recommmend using poetry.
# Prerequisites for C++
To build the c++ part of the library, you need a minimal environment with c++ compiler, cmake, and boost. To be able to use parallelism based on openMP, you should also install libomp. For instance, on macOS it is done via:
xcode-select --install
brew install cmake
brew install boost
brew install libomp
You must also set some environment variables to instruct the build process on how to find boost and openMP. For instance, on macOS, it is done via:
export Boost_ROOT=$(brew --cellar boost)/$(brew list --versions boost | tr ' ' '\n' | tail -1)
export OpenMP_ROOT=$(brew --cellar libomp)/$(brew list --versions libomp | tr ' ' '\n' | tail -1)
export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp"
export CFLAGS="$CFLAGS -I$OpenMP_ROOT/include"
export CXXFLAGS="$CXXFLAGS -I$OpenMP_ROOT/include"
export LDFLAGS="$LDFLAGS -Wl,-rpath,$OpenMP_ROOT/lib -L$OpenMP_ROOT/lib -lomp"
# Installation with pyenv + poetry
Here are the steps to follow:
Clone the source and got to the "scikit-decide" root directory.
git clone --recurse-submodules -j8 https://github.com/airbus/scikit-decide.git cd scikit-decide
Set proper python version (e.g. 3.12.2) for the scikit-decide project.
pyenv local 3.12.2
Update pip installer (the one that
pyenv
makes you use).pip install -U pip
Use poetry to install the project:
Install poetry (opens new window).
curl -sSL https://install.python-poetry.org | python3 - export PATH="$HOME/.local/bin:$PATH" # add path to poetry
Install poetry-dynamic-versioning in poetry root env
poetry self add poetry-dynamic-versioning
Specify to poetry the python version to use so that it creates the appropriate virtual environment.
poetry env use 3.12.2
Install all dependencies as defined in
poetry.lock
, build and install the c++ library.rm -rf build # removing previous build poetry install --extras all
# Alternate installation with conda + poetry
You can also use conda rather than pyenv. It can be useful when you cannot install poetry via the above method, as it can also be installed by conda via the conda-forge channel.
Clone the source and got to the "scikit-decide" root directory.
git clone --recurse-submodules -j8 https://github.com/airbus/scikit-decide.git cd scikit-decide
Create and activate a conda environment with the proper python version for the scikit-decide project.
conda create -n test_dev_skdecide python=3.12.2 conda activate test_dev_skdecide
Update pip installer
pip install -U pip
Install poetry in the environment
conda install -c conda-forge poetry
Install poetry-dynamic-versioning in poetry root env
poetry self add poetry-dynamic-versioning
Install all dependencies as defined in
poetry.lock
, build and install the c++ library.rm -rf build # removing previous build poetry install --extras all
# Use of developer mode installation
Now you are able to use the library in developer mode (i.e. with code modifications directly taken into account)
by prefixing all commands with poetry run
.
For instance:
- to see the list of installed packages:
poetry run pip list
(NB: you can also usepoetry show
) - to run the tutorial script from examples:
poetry run python examples/tutorial.py
# Building the docs locally
The documentation is using VuePress (opens new window) to generate an interactive static website.
Some pages are generated from code thanks to the Python script docs/autodoc.py
.
# Install the library in developer mode.
See above to install scikit-decide with poetry.
# Install the documentation dependencies
The Python dependencies should have been installed in previous step, but you still need to install the JavaScript ones (including VuePress).
First, get Yarn (package manager) by following these installation steps (opens new window).
Make sure you are in the "scikit-decide" root directory and install documentation dependencies:
yarn install
# Define environment variables for binder and colab links
In order to define appropriate links for notebooks (github source + launching on binder), we need several environment variables:
- AUTODOC_BINDER_ENV_GH_REPO_NAME: name of the github repository hosting the binder environment
- AUTODOC_BINDER_ENV_GH_BRANCH: branch hosting the binder environment
- AUTODOC_NOTEBOOKS_REPO_URL: url of the content repository for the notebooks
- AUTODOC_NOTEBOOKS_BRANCH: branch containing the notebooks
For instance:
export AUTODOC_BINDER_ENV_GH_REPO_NAME="airbus/scikit-decide"
export AUTODOC_BINDER_ENV_GH_BRANCH="binder"
current_repo_url_withdotgit=$(git remote get-url origin)
export AUTODOC_NOTEBOOKS_REPO_URL=${current_repo_url_withdotgit/.git/}
export AUTODOC_NOTEBOOKS_BRANCH=$(git branch --show-current)
# Build the docs
Make sure you are in the "scikit-decide" root directory and using the virtual environment where you installed scikit-decide.
If you used poetry, that means prepending python commands with poetry run
.
Then generate and serve locally the documentation with:
poetry run yarn docs:dev
The above command will call python docs/autodoc.py
hence the use of poetry run
.
NB: you can encounter an error when using Node version >=17 :
node:internal/crypto/hash:71
this[kHandle] = new _Hash(algorithm, xofLen);
^
In that case, typing the command below may help you:
export NODE_OPTIONS=--openssl-legacy-provider
Open your web browser to access the documentation (by default on http://localhost:8080/scikit-decide/).
# Running unit tests
The unit tests are gathered in tests/
folder and run with pytest (opens new window).
Providing you installed the library in developer mode as described above,
pytest should have been already installed by poetry.
From the "scikit-decide" root directory, run unit tests with:
poetry run pytest tests
# Running notebooks as tests
One can test programmatically that notebooks are not broken thanks to nbmake (opens new window) extension for pytest.
poetry run pytest --nbmake notebooks -v
# Guidelines to follow when preparing a contribution
# Coding style and code linting
To help maintaining the same coding style across the project, some code linters are used via pre-commit (opens new window).
It is used by CI to run checks at each push, but can also be used locally.
Once installed, you can run it on all files with
pre-commit run --all-files
Beware that doing so, you are actually modifying the files.
You can also use it when committing:
- stage your changes:
git add your_files
, - run pre-commit on the staged files:
pre-commit run
, - check the changes made,
- accept them by adding modified files:
git add -u
, - commit:
git commit
.
This can also be done automatically at each commit if you add pre-commit to git hooks with pre-commit install
.
Beware that when doing so,
- the changes will be refused if pre-commit actually modifies the files,
- you can then accept the modifications with
git add -u
, - you can still force a commit that violates pre-commit checks with
git commit -n
orgit commit --no-verify
.
If you prefer run pre-commit manually, you can remove the hooks with pre-commit uninstall
.
# Notebooks
We try to give some introductory examples via notebooks available in the corresponding notebooks/
directory.
The list of these notebooks is automatically inserted in the documentation with a title and a description. These are actually extracted from the first cell. To enable that, each notebook should
- start with a markdown cell,
- its first line being the title starting with one number sign ("# "),
- the remaining lines being used as the description.
For instance:
# Great notebook title
A quick description of the main features of the notebook.
Can be on several lines.
Can include a nice thumbnail.
![Notebook_thumbnail](https://airbus.github.io/scikit-decide/maze.png)
# Adding unit tests
- Whenever adding some code, think to add some tests to the
tests/
folder. - Whenever fixing a bug, think to add a test that crashes before fixing the bug and does not afterwards.
Follow above instructions to run them with pytest.
# Submitting pull requests
When you think you are ready to merge your modifications into the main repository, you will have to open a pull request (PR). We can summarize the process as follows:
- Fork the repository on github.
- Clone your fork on your computer.
- Make your changes and push them to your fork.
- Do the necessary checks (see below).
- Reorganize your commits (see below).
- Submit your pull request (see github documentation (opens new window)).
- See if all CI checks passed on your PR.
- Wait for a review.
- Take the comments and required changes into account.
Note that a PR needs at least one review by a core developer to be merged.
You may want to add a reference to the main repository to fetch from it and (re)base your changes on it:
git remote add upstream https://github.com/airbus/scikit-decide
This post (opens new window) points out good practices to follow to submit great pull requests and review them efficiently.
# Prior checks
Before submitting your pull request, think to
- run the unit tests,
- check the documentation locally if you modified it,
- check you respect the coding styles by running linters.
If you do not, you will still be able to see the status of your PR as CI will do these checks for you.
# Reorganizing commits
On your way to implement your contribution, you will probably have lots of commits, some modifying other ones from the same PR, or only modifying the code style.
At the end of your work, consider reorganizing them by
- squashing them into one or only a few logical commits,
- having a separate commit to reformat previous existing code if necessary,
- rewritting commit messages so that it explains the changes made and why, the "how" part being explained by the code itself (see this post (opens new window) about what a commit message should and should not contain),
- rebasing on upstream repository master branch if it diverged too much by the time you finished.
You can use git rebase -i
to do that, as explained in git documentation (opens new window).