Development
Contents
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 |
|
Format the code. |
flake8 |
|
Check the code for linting issues. |
isort |
|
Sort the imports. |
mypy |
|
Check the types. |
pytest |
|
Run the unit tests. |
sphinx-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? |
---|---|---|
|
Run unit tests for all Python versions. |
Yes |
|
Check whether the documentation builds without warnings. |
No |
|
Check the code for formatting issues. |
Yes |
|
Check the order of the import statements |
Yes |
|
Check the code for linting issues. |
Yes |
|
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 |
|
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/*