/usr/lib/python3/dist-packages/scipy/HACKING.rst.txt is in python3-scipy 0.18.1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | =====================
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.
.. note::
You may want to check the latest version of this guide, which is
available at:
https://github.com/scipy/scipy/blob/master/HACKING.rst.txt
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.
1. 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`_.
2. Documentation
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`_.
3. 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
``scipy.submodule.my_new_func``. ``my_new_func`` can be put in an existing or
new file under ``/scipy/<submodule>/``, its name is added to the ``__all__``
list in that file (which lists all public functions in the file), and those
public functions are then imported in ``/scipy/<submodule>/__init__.py``. Any
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 or style,
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.
Other ways to contribute
========================
There are many ways to contribute other than contributing code. Participating
in discussions on the scipy-user and scipy-dev *mailing lists* is a contribution
in itself. The `scipy.org`_ *website* contains a lot of information on the
SciPy community and can always use a new pair of hands.
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 git@github.com:YOURUSERNAME/scipy.git scipy
$ cd scipy
$ git remote add upstream git://github.com/scipy/scipy.git
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.py: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
you specify ``-n``, the tests are run against the version of Scipy (if
any) found on current PYTHONPATH.
Using ``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.
SciPy structure
===============
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.
* Directory ``yyy/`` contains:
- A file ``setup.py`` that defines
``configuration(parent_package='',top_path=None)`` function
for `numpy.distutils`.
- A directory ``tests/`` that contains files ``test_<name>.py``
corresponding to modules ``yyy/<name>{.py,.so,/}``.
* Private modules should be prefixed with an underscore ``_``,
for instance ``yyy/_somemodule.py``.
* User-visible functions should have good documentation following
the Numpy documentation style, see `how to document`_
* The ``__init__.py`` of 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 ``doc/source/tutorial/``
See the existing Scipy submodules for guidance.
For further details on Numpy distutils, see:
https://github.com/numpy/numpy/blob/master/doc/DISTUTILS.rst.txt
Useful links, FAQ, checklist
============================
Checklist before submitting a PR
--------------------------------
- Are there unit tests with good code coverage?
- Do all public function have docstrings including examples?
- Is the code style correct (PEP8, pyflakes)
- Is the new functionality tagged with ``.. versionadded:: X.Y.Z`` (with
X.Y.Z the version number of the next release - can be found in setup.py)?
- Is the new functionality mentioned in the release notes of the next
release?
- Is the new functionality added to the reference guide?
- In case of larger additions, is there a tutorial or more extensive
module-level description?
- In case compiled code is added, is it integrated correctly via setup.py
(and preferably also Bento configuration files - bento.info and bscript)?
- If you are a first-time contributor, did you add yourself to THANKS.txt?
Please note that this is perfectly normal and desirable - the aim is to
give every single contributor credit, and if you don't add yourself it's
simply extra work for the reviewer (or worse, the reviewer may forget).
- Did you check that the code can be distributed under a BSD license?
Useful SciPy documents
----------------------
- The `how to document`_ guidelines
- NumPy/SciPy `testing guidelines`_
- `SciPy API`_
- SciPy `maintainers`_
- NumPy/SciPy `git workflow`_
FAQ
---
*I based my code on existing Matlab/R/... code I found online, is this OK?*
It depends. SciPy is distributed under a BSD license, so if the code that you
based your code on is also BSD licensed or has a BSD-compatible license (MIT,
Apache, ...) then it's OK. Code which is GPL-licensed, has no clear license,
requires citation or is free for academic use only can't be included in SciPy.
Therefore if you copied existing code with such a license or made a direct
translation to Python of it, your code can't be included. See also `license
compatibility`_.
*Why is SciPy under the BSD license and not, say, the GPL?*
Like Python, SciPy uses a "permissive" open source license, which allows
proprietary re-use. While this allows companies to use and modify the software
without giving anything back, it is felt that the larger user base results in
more contributions overall, and companies often publish their modifications
anyway, without being required to. See John Hunter's `BSD pitch`_.
*How do I set up a development version of SciPy in parallel to a released
version that I use to do my job/research?*
One simple way to achieve this is to install the released version in
site-packages, by using a binary installer or pip for example, and set
up the development version in a virtualenv. First install
`virtualenv`_ (optionally use `virtualenvwrapper`_), then create your
virtualenv (named scipy-dev here) with::
$ virtualenv scipy-dev
Now, whenever you want to switch to the virtual environment, you can use the
command ``source scipy-dev/bin/activate``, and ``deactivate`` to exit from the
virtual environment and back to your previous shell. With scipy-dev
activated, install first Scipy's dependencies::
$ pip install Numpy Nose Cython
After that, you can install a development version of Scipy, for example via::
$ python setup.py install
The installation goes to the virtual environment.
*How do I set up an in-place build for development*
For development, you can set up an in-place build so that changes made to
``.py`` files have effect without rebuild. First, run::
$ python setup.py build_ext -i
Then you need to point your PYTHONPATH environment variable to this directory.
Some IDEs (Spyder for example) have utilities to manage PYTHONPATH. On Linux
and OSX, you can run the command::
$ export PYTHONPATH=$PWD
and on Windows
$ set PYTHONPATH=/path/to/scipy
Now editing a Python source file in SciPy allows you to immediately
test and use your changes (in ``.py`` files), by simply restarting the
interpreter.
*Can I use a programming language other than Python to speed up my code?*
Yes. The languages used in SciPy are Python, Cython, C, C++ and Fortran. All
of these have their pros and cons. If Python really doesn't offer enough
performance, one of those languages can be used. Important concerns when
using compiled languages are maintainability and portability. For
maintainability, Cython is clearly preferred over C/C++/Fortran. Cython and C
are more portable than C++/Fortran. A lot of the existing C and Fortran code
in SciPy is older, battle-tested code that was only wrapped in (but not
specifically written for) Python/SciPy. Therefore the basic advice is: use
Cython. If there's specific reasons why C/C++/Fortran should be preferred,
please discuss those reasons first.
*How do I debug code written in C/C++/Fortran inside Scipy?*
The easiest way to do this is to first write a Python script that
invokes the C code whose execution you want to debug. For instance
``mytest.py``::
from scipy.special import hyp2f1
print(hyp2f1(5.0, 1.0, -1.8, 0.95))
Now, you can run::
gdb --args python runtests.py -g --python mytest.py
If you didn't compile with debug symbols enabled before, remove the
``build`` directory first. While in the debugger::
(gdb) break cephes_hyp2f1
(gdb) run
The execution will now stop at the corresponding C function and you
can step through it as usual. Instead of plain ``gdb`` you can of
course use your favourite alternative debugger; run it on the
``python`` binary with arguments ``runtests.py -g --python mytest.py``.
*How do I enable additional tests in Scipy?*
Some of the tests in Scipy's test suite are very slow and not enabled
by default. You can run the full suite via::
$ python runtests.py -g -m full
This invokes the test suite ``import scipy; scipy.test("full")``,
enabling also slow tests.
There is an additional level of very slow tests (several minutes),
which are disabled also in this case. They can be enabled by setting
the environment variable ``SCIPY_XSLOW=1`` before running the test
suite.
*How do I write tests with test generators?*
The Nose_ test framework supports so-called test generators, which can come
useful if you need to have multiple tests where just a parameter changes.
Using test generators so that they are more useful than harmful is tricky, and
we recommend the following pattern::
def test_something():
some_array = (...)
def check(some_param):
c = compute_result(some_array, some_param)
known_result = (...)
assert_allclose(c, known_result)
for some_param in ['a', 'b', 'c']:
yield check, some_param
We require the following:
- All asserts and all computation that is tested must only be reached after a
yield. (Rationale: the generator body is part of no test, and a failure in it
will show neither the test name nor for what parameters the test failed.)
- Arrays must not be passed as yield parameters. Either use variables from
outer scope (eg. with some index passed to yield), or capsulate test data to
a class with a sensible ``__repr__``. (Rationale: Nose truncates the printed
form of arrays in test output, and this makes it impossible to know for what
parameters a test failed. Arrays are big, and clutter test output
unnecessarily.)
- Test generators cannot be used in test classes inheriting from
unittest.TestCase; either use object as base class, or use standalone test
functions. (Rationale: Nose does not run test generators in
TestCase-inheriting classes.)
If in doubt, do not use test generators. You can track for what parameter
things failed also by passing ``err_msg=repr((param1, param2, ...))`` to the
various assert functions.
.. _scikit-learn: http://scikit-learn.org
.. _scikit-image: http://scikit-image.org/
.. _statsmodels: http://statsmodels.sourceforge.net/
.. _testing guidelines: https://github.com/numpy/numpy/blob/master/doc/TESTS.rst.txt
.. _how to document: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
.. _PEP8: http://www.python.org/dev/peps/pep-0008/
.. _pep8 package: http://pypi.python.org/pypi/pep8
.. _pyflakes: http://pypi.python.org/pypi/pyflakes
.. _SciPy API: https://docs.scipy.org/doc/scipy/reference/api.html
.. _git workflow: https://docs.scipy.org/doc/numpy/dev/gitwash/index.html
.. _Github help pages: https://help.github.com/articles/set-up-git/
.. _maintainers: https://github.com/scipy/scipy/blob/master/doc/MAINTAINERS.rst.txt
.. _issue list: https://github.com/scipy/scipy/issues
.. _Github: https://github.com/scipy/scipy
.. _scipy.org: https://scipy.org/
.. _scipy.github.com: http://scipy.github.com/
.. _scipy.org-new: https://github.com/scipy/scipy.org-new
.. _documentation wiki: https://docs.scipy.org/scipy/Front%20Page/
.. _SciPy Central: http://scipy-central.org/
.. _license compatibility: https://www.scipy.org/License_Compatibility
.. _doctest: http://www.doughellmann.com/PyMOTW/doctest/
.. _virtualenv: http://www.virtualenv.org/
.. _virtualenvwrapper: http://www.doughellmann.com/projects/virtualenvwrapper/
.. _bsd pitch: http://nipy.sourceforge.net/nipy/stable/faq/johns_bsd_pitch.html
.. _Nose: http://nose.readthedocs.org/en/latest/
|