Development#

Setting up the development environment#

Make sure that all the Python versions supported by the plugin (3.8 to 3.10 at the time of writing) are installed on your computer and available to tox. asdf and python-launcher can be of help in this regard.

Clone the project’s repository

git clone git@github.com:saltastroops/imephu.git

Create a virtual repository named .venv in the cloned project:

cd imephu
python -m venv .venv

While in principle another name could be chosen for the virtual environment, python-launcher will automatically pick up and use the virtual environment if it is called .venv.

Activate the virtual environment (just in case it isn’t picked up):

source .venv/bin/activate

Now you can install the development requirements:

python -m pip install --upgrade pip
python -m pip install -r requirements-dev.txt

Finally, install the project package itself:

python -m pip install -e .

Development tools#

After setting up the development environment, you have a variety of tools at your disposal. They are listed here along with the commands for using them.

Tool

Command

Use

black

black src tests

Format the code.

flake8

flake8 src tests

Check the code for linting issues.

isort

isort src tests

Sort the imports.

mypy

mypy src tests

Check the types.

pytest

pytest

Run the unit tests.

sphinx-build

sphinx-build docs docs/build

Build the documentation.

Testing with tox#

The following table lists the various tests which can be run with tox. The third column states whether you can replace the default positional arguments with your own ones. In most cases there should be no need for this, though.

Command

Use

Own positional arguments?

tox

Run unit tests for all Python versions.

Yes

tox -e docs

Check whether the documentation builds without warnings.

No

tox -e format

Check the code for formatting issues.

Yes

tox -e imports

Check the order of the import statements

Yes

tox -e lint

Check the code for linting issues.

Yes

tox -e typecheck

Check the types in the code (apart from tests).

Yes

Unit testing#

Note

The project setup includes coverage for unit tests run with tox. This is not the case when pytest is run straight from the command line, as test coverage interferes with debugger breakpoints, causing code execution not to be paused at them. However, you may still include coverage by using the --cov flag.

Most of the unit tests create a finder chart, save it and compare it to a previously saved version, asserting nothing has changed. The pytest plugin pytest-regressions is used for simplifying the task. The files created by this plugin should be put under version control.

The first time you save a particular finder chart, you will get an error like File not found in data directory, created:. In theory, you would expect that the next test run is passing. In practice, there is a problem. The FinderChart class internally uses AstroPy’s mpl_normalize function, which is non-deterministic. This implies that the files generated by saving finder charts are not deterministic either; different runs of the code will create files which look the same, but have a different byte content (and even a different file size).

The solution is to set a random seed for the unit test:

import numpy as np

np.random.seed(0)

Bear in mind that this is setting NumPy’s global random seed, which may affect other code (but shouldn’t in the context of this project).

Rather than trying to remember to always set the random seed (and to remember how to use pytest-regressions), you can just use the check_finder fixture:

from imephu.finder_chart import FinderChart

def test_create_finder_chart(fits_file, check_finder) -> None:
    fc = FinderChart(fits_file)
    check_finder(fc)

If you need to update the files generated by pytest-regressions, you may run pytest with the --force-regen flag:

pytest --force-regen

In case you are using parametrized tests and want to have more meaningful names for the generated files, you may use the ids keyword of the parametrized marker.

Fixtures#

The following fixtures are defined in conftest.py.

Fixture

Description

check_finder

Function comparing a finder chart against a previously saved version, asserting nothing has changed. (Technically, the saved png file is compared.)

fits_file

Path of a FITS file that can be used for generating a finder chart.

Publishing the package#

Publishing manually#

In order to publish imephu from your machine, first install twine, if you haven’t done so already:

pipx install twine

Then remove the dist folder if need be:

rm -r dist

Build the package:

pyproject-build --sdist

If you have your own PyPI server, say https://pypi.example.com, create a file .pypirc in your home directory with the following content:

[distutils]
index-servers =
    pypi
    testpypi
    saao

[pypi]
repository = https://upload.pypi.org/legacy/

[testpypi]
repository = https://test.pypi.org/legacy/

[example]
repository = https://pypi.example.com/

You can then use twine to upload the package:

twine upload -r https://pypi.example.com dist/*

Afterwards you can install imephu from your PyPI server with

python -m pip install --index-url https://pypi.example.com/

Upload the package to Test PyPI:

twine upload -r testpypi dist/*

You can then install imephu from Test PyPI with

python -m pip install --index-url https://test.pypi.org/simple/ imephu

If all looks good, you can publish your package:

twine upload dist/*