Setup

Initial setup

Install uv (for example, with Homebrew do brew install uv), then clone the repository and set it up:

$ git clone git@github.com:Gattocrucco/lsqfitgp.git
$ cd lsqfitgp
$ make setup

make setup installs the pre-commit hooks and checks that the Python environment works. The environment, with the versions of the dependencies pinned in uv.lock, is created in .venv by uv the first time it is needed. To run commands that involve the Python installation, do uv run <command>, e.g., uv run ipython. Alternatively, do source .venv/bin/activate to activate the virtual environment in the current shell.

The version of the package is derived from the git tags, so the repository must be cloned with its history.

Pre-defined commands

The Makefile in the root directory contains targets to run the tests and the examples, build the documentation, update the dependencies, and prepare a release. Run make without arguments to list the targets. All targets that simply consist in invoking a tool with the right command line arguments use the ARGS variable to add extra arguments, for example:

$ make tests ARGS='-k test_pigs_fly'

will invoke something like

$ uv run pytest --foo=1 --bar=128 --etc-etc -k test_pigs_fly

make lint runs all the linters through pre-commit, and make ipython starts an IPython shell with the common imports.

Tests

The typical workflow to debug new changes is to first run all tests with

$ make tests

The tests run in parallel with pytest-xdist; set NPROC to change the number of workers, NPROC=0 disables parallelization. If some tests fail, use pytest directly to run and debug only the relevant tests, e.g., with

$ uv run pytest --lf --sw --pdb

where --lf selects only the tests that failed, --sw stops on the first failed test, starting again from it on the next run, and --pdb opens the python debugger at the point where the test failed. Another useful option is -k <pattern>, which selects only tests whose name matches <pattern>.

make tests-old runs the tests with the oldest supported versions of Python and of the dependencies, see Dependencies.

The examples and the code in the documentation are run with make examples and make docscode, which also produce the figures shown in the manual. Then make docs builds the documentation in docs/_build/html.

All these commands save coverage information. make covreport merges it into an html report in htmlcov/index.html, and make covcheck checks the coverage is above some thresholds. The tests are run on each push, and the coverage report and the documentation for the main branch are published online at gattocrucco.github.io/lsqfitgp/htmlcov and gattocrucco.github.io/lsqfitgp/docs. The documentation of each release is published in docs-<version> when its tag is pushed.

Dependencies

The dependencies used for development are pinned in uv.lock. To upgrade them to the latest versions, do make update-deps. This skips versions published in the last week (see COOLDOWN_DAYS in the Makefile).

The minimum supported versions of Python and of the dependencies are the lower bounds in pyproject.toml. make tests-old resolves the dependencies to these lower bounds, and their other dependencies to the latest versions available at OLD_DATE (set in the Makefile). make update-oldest-deps moves OLD_DATE to one year ago, and raises the lower bounds to the latest versions available at that date, and the minimum Python version to the oldest one among the last five releases.

To debug tests that fail with old versions of dependencies, it’s convenient to piggyback on the predefined make target using ARGS:

$ make tests-old ARGS='-n0 -k test_pigs_fly'

For more fine-grained control, it’s useful to invoke directly uv with the --with option, e.g., the following command will start an IPython shell equipped with specific versions of python and jax:

$ uv run --with='jax<0.7,jaxlib<0.7' --isolated --python=3.11 --dev python -m IPython