Contributing to SciPy¶
This document aims to give an overview of how to contribute to SciPy. It tries to answer commonly asked questions, and provide some insight into how the community process works in practice. Readers who are familiar with the SciPy community and are experienced Python coders may want to jump straight to the git workflow documentation.
There are a lot of ways you can contribute:
- Contributing new code
- Fixing bugs and other maintenance work
- Improving the documentation
- Reviewing open pull requests
- Triaging issues
- Working on the scipy.org website
- Answering questions and participating on the scipy-dev and scipy-user mailing lists.
Contributing new code¶
If you have been working with the scientific Python toolstack for a while, you probably have some code lying around of which you think “this could be useful for others too”. Perhaps it’s a good idea then to contribute it to SciPy or another open source project. The first question to ask is then, where does this code belong? That question is hard to answer here, so we start with a more specific one: what code is suitable for putting into SciPy? Almost all of the new code added to scipy has in common that it’s potentially useful in multiple scientific domains and it fits in the scope of existing scipy submodules. In principle new submodules can be added too, but this is far less common. For code that is specific to a single application, there may be an existing project that can use the code. Some scikits (scikit-learn, scikit-image, statsmodels, etc.) are good examples here; they have a narrower focus and because of that more domain-specific code than SciPy.
Now if you have code that you would like to see included in SciPy, how do you go about it? After checking that your code can be distributed in SciPy under a compatible license (see FAQ for details), the first step is to discuss on the scipy-dev mailing list. All new features, as well as changes to existing code, are discussed and decided on there. You can, and probably should, already start this discussion before your code is finished.
Assuming the outcome of the discussion on the mailing list is positive and you have a function or piece of code that does what you need it to do, what next? Before code is added to SciPy, it at least has to have good documentation, unit tests and correct code style.
- Unit tests
- In principle you should aim to create unit tests that exercise all the code that you are adding. This gives some degree of confidence that your code runs correctly, also on Python versions and hardware or OSes that you don’t have available yourself. An extensive description of how to write unit tests is given in the NumPy testing guidelines.
- Clear and complete documentation is essential in order for users to be able to find and understand the code. Documentation for individual functions and classes – which includes at least a basic description, type and meaning of all parameters and returns values, and usage examples in doctest format – is put in docstrings. Those docstrings can be read within the interpreter, and are compiled into a reference guide in html and pdf format. Higher-level documentation for key (areas of) functionality is provided in tutorial format and/or in module docstrings. A guide on how to write documentation is given in how to document.
- Code style
- Uniformity of style in which code is written is important to others trying to understand the code. SciPy follows the standard Python guidelines for code style, PEP8. In order to check that your code conforms to PEP8, you can use the pep8 package style checker. Most IDEs and text editors have settings that can help you follow PEP8, for example by translating tabs by four spaces. Using pyflakes to check your code is also a good idea.
At the end of this document a checklist is given that may help to check if your code fulfills all requirements for inclusion in SciPy.
Another question you may have is: where exactly do I put my code? To answer
this, it is useful to understand how the SciPy public API (application
programming interface) is defined. For most modules the API is two levels
deep, which means your new function should appear as
my_new_func can be put in an existing or
new file under
/scipy/<submodule>/, its name is added to the
list in that file (which lists all public functions in the file), and those
public functions are then imported in
private functions/classes should have a leading underscore (
_) in their
name. A more detailed description of what the public API of SciPy is, is given
in SciPy API.
Once you think your code is ready for inclusion in SciPy, you can send a pull request (PR) on Github. We won’t go into the details of how to work with git here, this is described well in the git workflow section of the NumPy documentation and on the Github help pages. When you send the PR for a new feature, be sure to also mention this on the scipy-dev mailing list. This can prompt interested people to help review your PR. Assuming that you already got positive feedback before on the general idea of your code/feature, the purpose of the code review is to ensure that the code is correct, efficient and meets the requirements outlined above. In many cases the code review happens relatively quickly, but it’s possible that it stalls. If you have addressed all feedback already given, it’s perfectly fine to ask on the mailing list again for review (after a reasonable amount of time, say a couple of weeks, has passed). Once the review is completed, the PR is merged into the “master” branch of SciPy.
The above describes the requirements and process for adding code to SciPy. It doesn’t yet answer the question though how decisions are made exactly. The basic answer is: decisions are made by consensus, by everyone who chooses to participate in the discussion on the mailing list. This includes developers, other users and yourself. Aiming for consensus in the discussion is important – SciPy is a project by and for the scientific Python community. In those rare cases that agreement cannot be reached, the maintainers of the module in question can decide the issue.
Contributing by helping maintain existing code¶
The previous section talked specifically about adding new functionality to SciPy. A large part of that discussion also applies to maintenance of existing code. Maintenance means fixing bugs, improving code quality, documenting existing functionality better, adding missing unit tests, keeping build scripts up-to-date, etc. The SciPy issue list contains all reported bugs, build/documentation issues, etc. Fixing issues helps improve the overall quality of SciPy, and is also a good way of getting familiar with the project. You may also want to fix a bug because you ran into it and need the function in question to work correctly.
The discussion on code style and unit testing above applies equally to bug fixes. It is usually best to start by writing a unit test that shows the problem, i.e. it should pass but doesn’t. Once you have that, you can fix the code so that the test does pass. That should be enough to send a PR for this issue. Unlike when adding new code, discussing this on the mailing list may not be necessary - if the old behavior of the code is clearly incorrect, no one will object to having it fixed. It may be necessary to add some warning or deprecation message for the changed behavior. This should be part of the review process.
Pull requests that only change code style, e.g. fixing some PEP8 issues in a file, are discouraged. Such PRs are often not worth cluttering the git annotate history, and take reviewer time that may be better spent in other ways. Code style cleanups of code that is touched as part of a functional change are fine however.
Reviewing pull requests¶
Reviewing open pull requests (PRs) is very welcome, and a valuable way to help increase the speed at which the project moves forward. If you have specific knowledge/experience in a particular area (say “optimization algorithms” or “special functions”) then reviewing PRs in that area is especially valuable - sometimes PRs with technical code have to wait for a long time to get merged due to a shortage of appropriate reviewers.
We encourage everyone to get involved in the review process; it’s also a great way to get familiar with the code base. Reviewers should ask themselves some or all of the following questions:
- Was this change adequately discussed (relevant for new features and changes in existing behavior)?
- Is the feature scientifically sound? Algorithms may be known to work based on literature; otherwise, closer look at correctness is valuable.
- Is the intended behavior clear under all conditions (e.g. unexpected inputs like empty arrays or nan/inf values)?
- Does the code meet the quality, test and documentation expectation outline under Contributing new code?
If we do not know you yet, consider introducing yourself.
Other ways to contribute¶
There are many ways to contribute other than contributing code.
Triaging issues (investigating bug reports for validity and possible actions to take) is also a useful activity. SciPy has many hundreds of open issues; closing invalid ones and correctly labeling valid ones (ideally with some first thoughts in a comment) allows prioritizing maintenance work and finding related issues easily when working on an existing function or submodule.
Participating in discussions on the scipy-user and scipy-dev mailing lists is a contribution in itself. Everyone who writes to those lists with a problem or an idea would like to get responses, and writing such responses makes the project and community function better and appear more welcoming.
The scipy.org website contains a lot of information on both SciPy the project and SciPy the community, and it can always use a new pair of hands. The sources for the website live in their own separate repo: https://github.com/scipy/scipy.org
Recommended development setup¶
Since Scipy contains parts written in C, C++, and Fortran that need to be compiled before use, make sure you have the necessary compilers and Python development headers installed. Having compiled code also means that importing Scipy from the development sources needs some additional steps, which are explained below.
First fork a copy of the main Scipy repository in Github onto your own account and then create your local repository via:
$ git clone email@example.com:YOURUSERNAME/scipy.git scipy $ cd scipy $ git remote add upstream git://github.com/scipy/scipy.git
Second to code review pull requests it is helpful to have a local copy of the code changes in the pull request. The preferred method to bring a PR from the github repository to your local repo in a new branch:
$ git fetch upstream pull/PULL_REQUEST_ID/head:NEW_BRANCH_NAME
The value of PULL_REQUEST_ID will be the PR number and the NEW_BRANCH_NAME will be the name of the branch in your local repository where the diffs will reside.
Now you have a branch in your local development area to code review in python.
To build the development version of Scipy and run tests, spawn interactive shells with the Python import paths properly set up etc., do one of:
$ python runtests.py -v $ python runtests.py -v -s optimize $ python runtests.py -v -t scipy.special.tests.test_basic::test_xlogy $ python runtests.py --ipython $ python runtests.py --python somescript.py $ python runtests.py --bench
This builds Scipy first, so the first time it may take some time. If
-n, the tests are run against the version of Scipy (if
any) found on current PYTHONPATH. Note: if you run into a build issue,
more detailed build documentation can be found in :doc:`building/index` and at
runtests.py is the recommended approach to running tests.
There are also a number of alternatives to it, for example in-place
build or installing to a virtualenv. See the FAQ below for details.
Some of the tests in Scipy are very slow and need to be separately enabled. See the FAQ below for details.
All SciPy modules should follow the following conventions. In the
following, a SciPy module is defined as a Python package, say
yyy, that is located in the scipy/ directory.
Ideally, each SciPy module should be as self-contained as possible. That is, it should have minimal dependencies on other packages or modules. Even dependencies on other SciPy modules should be kept to a minimum. A dependency on NumPy is of course assumed.
- A file
- A directory
tests/that contains files
test_<name>.pycorresponding to modules
- A file
Private modules should be prefixed with an underscore
_, for instance
User-visible functions should have good documentation following the NumPy documentation style, see how to document
__init__.pyof the module should contain the main reference documentation in its docstring. This is connected to the Sphinx documentation under
doc/via Sphinx’s automodule directive.
The reference documentation should first give a categorized list of the contents of the module using
autosummary::directives, and after that explain points essential for understanding the use of the module.
Tutorial-style documentation with extensive examples should be separate, and put under
See the existing Scipy submodules for guidance.
For further details on NumPy distutils, see: