|
| 1 | +# Contributing guide |
| 2 | + |
| 3 | +Scanpy provides extensive [developer documentation][scanpy developer guide], most of which applies to this repo, too. |
| 4 | +This document will not reproduce the entire content from there. Instead, it aims at summarizing the most important |
| 5 | +information to get you started on contributing. |
| 6 | + |
| 7 | +We assume that you are already familiar with git and with making pull requests on GitHub. If not, please refer |
| 8 | +to the [scanpy developer guide][]. |
| 9 | + |
| 10 | +## Installing dev dependencies |
| 11 | + |
| 12 | +In addition to the packages needed to _use_ this package, you need additional python packages to _run tests_ and _build |
| 13 | +the documentation_. It's easy to install them using `pip`: |
| 14 | + |
| 15 | +```bash |
| 16 | +cd {{ cookiecutter.project_name }} |
| 17 | +pip install -e ".[dev,test,doc]" |
| 18 | +``` |
| 19 | + |
| 20 | +## Code-style |
| 21 | + |
| 22 | +This template uses [pre-commit][] to enforce consistent code-styles. On every commit, pre-commit checks will either |
| 23 | +automatically fix issues with the code, or raise an error message. See [pre-commit checks](template_usage.md#pre-commit-checks) for |
| 24 | +a full list of checks enabled for this repository. |
| 25 | + |
| 26 | +To enable pre-commit locally, simply run |
| 27 | + |
| 28 | +```bash |
| 29 | +pre-commit install |
| 30 | +``` |
| 31 | + |
| 32 | +in the root of the repository. Pre-commit will automatically download all dependencies when it is run for the first time. |
| 33 | + |
| 34 | +Alternatively, you can rely on the [pre-commit.ci][] service enabled on GitHub. If you didn't run `pre-commit` before |
| 35 | +pushing changes to GitHub it will automatically commit fixes to your pull request, or show an error message. |
| 36 | + |
| 37 | +If pre-commit.ci added a commit on a branch you still have been working on locally, simply use |
| 38 | + |
| 39 | +```bash |
| 40 | +git pull --rebase |
| 41 | +``` |
| 42 | + |
| 43 | +to integrate the changes into yours. |
| 44 | +While the [pre-commit.ci][] is useful, we strongly encourage installing and running pre-commit locally first to understand its usage. |
| 45 | + |
| 46 | +Finally, most editors have an _autoformat on save_ feature. Consider enabling this option for [black][black-editors] |
| 47 | +and [prettier][prettier-editors]. |
| 48 | + |
| 49 | +[black-editors]: https://black.readthedocs.io/en/stable/integrations/editors.html |
| 50 | +[prettier-editors]: https://prettier.io/docs/en/editors.html |
| 51 | + |
| 52 | +## Writing tests |
| 53 | + |
| 54 | +```{note} |
| 55 | +Remember to first install the package with `pip install '-e[dev,test]'` |
| 56 | +``` |
| 57 | + |
| 58 | +This package uses the [pytest][] for automated testing. Please [write tests][scanpy-test-docs] for every function added |
| 59 | +to the package. |
| 60 | + |
| 61 | +Most IDEs integrate with pytest and provide a GUI to run tests. Alternatively, you can run all tests from the |
| 62 | +command line by executing |
| 63 | + |
| 64 | +```bash |
| 65 | +pytest |
| 66 | +``` |
| 67 | + |
| 68 | +in the root of the repository. Continuous integration will automatically run the tests on all pull requests. |
| 69 | + |
| 70 | +[scanpy-test-docs]: https://scanpy.readthedocs.io/en/latest/dev/testing.html#writing-tests |
| 71 | + |
| 72 | +## Publishing a release |
| 73 | + |
| 74 | +### Updating the version number |
| 75 | + |
| 76 | +Before making a release, you need to update the version number. Please adhere to [Semantic Versioning][semver], in brief |
| 77 | + |
| 78 | +> Given a version number MAJOR.MINOR.PATCH, increment the: |
| 79 | +> |
| 80 | +> 1. MAJOR version when you make incompatible API changes, |
| 81 | +> 2. MINOR version when you add functionality in a backwards compatible manner, and |
| 82 | +> 3. PATCH version when you make backwards compatible bug fixes. |
| 83 | +> |
| 84 | +> Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. |
| 85 | +
|
| 86 | +We use [bump2version][] to automatically update the version number in all places and automatically create a git tag. |
| 87 | +Run one of the following commands in the root of the repository |
| 88 | + |
| 89 | +```bash |
| 90 | +bump2version patch |
| 91 | +bump2version minor |
| 92 | +bump2version major |
| 93 | +``` |
| 94 | + |
| 95 | +Once you are done, run |
| 96 | + |
| 97 | +``` |
| 98 | +git push --tags |
| 99 | +``` |
| 100 | + |
| 101 | +to publish the created tag on GitHub. |
| 102 | + |
| 103 | +[bump2version]: https://github.com/c4urself/bump2version |
| 104 | + |
| 105 | +### Building and publishing the package on PyPI |
| 106 | + |
| 107 | +Python packages are not distributed as source code, but as _distributions_. The most common distribution format is the so-called _wheel_. To build a _wheel_, run |
| 108 | + |
| 109 | +```bash |
| 110 | +python -m build |
| 111 | +``` |
| 112 | + |
| 113 | +This command creates a _source archive_ and a _wheel_, which are required for publishing your package to [PyPI][]. These files are created directly in the root of the repository. |
| 114 | + |
| 115 | +Before uploading them to [PyPI][] you can check that your _distribution_ is valid by running: |
| 116 | + |
| 117 | +```bash |
| 118 | +twine check dist/* |
| 119 | +``` |
| 120 | + |
| 121 | +and finally publishing it with: |
| 122 | + |
| 123 | +```bash |
| 124 | +twine upload dist/* |
| 125 | +``` |
| 126 | + |
| 127 | +Provide your username and password when requested and then go check out your package on [PyPI][]! |
| 128 | + |
| 129 | +For more information, follow the [Python packaging tutorial][]. |
| 130 | + |
| 131 | +It is possible to automate this with GitHub actions, see also [this feature request][pypi-feature-request] |
| 132 | +in the cookiecutter-scverse template. |
| 133 | + |
| 134 | +[python packaging tutorial]: https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives |
| 135 | +[pypi-feature-request]: https://github.com/scverse/cookiecutter-scverse/issues/88 |
| 136 | + |
| 137 | +## Writing documentation |
| 138 | + |
| 139 | +Please write documentation for new or changed features and use-cases. This project uses [sphinx][] with the following features: |
| 140 | + |
| 141 | +- the [myst][] extension allows to write documentation in markdown/Markedly Structured Text |
| 142 | +- [Numpy-style docstrings][numpydoc] (through the [napoloen][numpydoc-napoleon] extension). |
| 143 | +- Jupyter notebooks as tutorials through [myst-nb][] (See [Tutorials with myst-nb](#tutorials-with-myst-nb-and-jupyter-notebooks)) |
| 144 | +- [Sphinx autodoc typehints][], to automatically reference annotated input and output types |
| 145 | + |
| 146 | +See the [scanpy developer docs](https://scanpy.readthedocs.io/en/latest/dev/documentation.html) for more information |
| 147 | +on how to write documentation. |
| 148 | + |
| 149 | +### Tutorials with myst-nb and jupyter notebooks |
| 150 | + |
| 151 | +The documentation is set-up to render jupyter notebooks stored in the `docs/notebooks` directory using [myst-nb][]. |
| 152 | +Currently, only notebooks in `.ipynb` format are supported that will be included with both their input and output cells. |
| 153 | +It is your reponsibility to update and re-run the notebook whenever necessary. |
| 154 | + |
| 155 | +If you are interested in automatically running notebooks as part of the continuous integration, please check |
| 156 | +out [this feature request](https://github.com/scverse/cookiecutter-scverse/issues/40) in the `cookiecutter-scverse` |
| 157 | +repository. |
| 158 | + |
| 159 | +#### Hints |
| 160 | + |
| 161 | +- If you refer to objects from other packages, please add an entry to `intersphinx_mapping` in `docs/conf.py`. Only |
| 162 | + if you do so can sphinx automatically create a link to the external documentation. |
| 163 | +- If building the documentation fails because of a missing link that is outside your control, you can add an entry to |
| 164 | + the `nitpick_ignore` list in `docs/conf.py` |
| 165 | + |
| 166 | +#### Building the docs locally |
| 167 | + |
| 168 | +```bash |
| 169 | +cd docs |
| 170 | +make html |
| 171 | +open _build/html/index.html |
| 172 | +``` |
| 173 | + |
| 174 | +<!-- Links --> |
| 175 | + |
| 176 | +[scanpy developer guide]: https://scanpy.readthedocs.io/en/latest/dev/index.html |
| 177 | +[cookiecutter-scverse-instance]: https://cookiecutter-scverse-instance.readthedocs.io/en/latest/template_usage.html |
| 178 | +[github quickstart guide]: https://docs.github.com/en/get-started/quickstart/create-a-repo?tool=webui |
| 179 | +[codecov]: https://about.codecov.io/sign-up/ |
| 180 | +[codecov docs]: https://docs.codecov.com/docs |
| 181 | +[codecov bot]: https://docs.codecov.com/docs/team-bot |
| 182 | +[codecov app]: https://github.com/apps/codecov |
| 183 | +[pre-commit.ci]: https://pre-commit.ci/ |
| 184 | +[readthedocs.org]: https://readthedocs.org/ |
| 185 | +[myst-nb]: https://myst-nb.readthedocs.io/en/latest/ |
| 186 | +[jupytext]: https://jupytext.readthedocs.io/en/latest/ |
| 187 | +[pre-commit]: https://pre-commit.com/ |
| 188 | +[anndata]: https://github.com/scverse/anndata |
| 189 | +[mudata]: https://github.com/scverse/mudata |
| 190 | +[pytest]: https://docs.pytest.org/ |
| 191 | +[semver]: https://semver.org/ |
| 192 | +[sphinx]: https://www.sphinx-doc.org/en/master/ |
| 193 | +[myst]: https://myst-parser.readthedocs.io/en/latest/intro.html |
| 194 | +[numpydoc-napoleon]: https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html |
| 195 | +[numpydoc]: https://numpydoc.readthedocs.io/en/latest/format.html |
| 196 | +[sphinx autodoc typehints]: https://github.com/tox-dev/sphinx-autodoc-typehints |
| 197 | +[pypi]: https://pypi.org/ |
0 commit comments