mirror of https://github.com/Qiskit/qiskit.git
585 lines
30 KiB
Markdown
585 lines
30 KiB
Markdown
# Contributing
|
|
|
|
First read the overall project contributing guidelines. These are all
|
|
included in the qiskit documentation:
|
|
|
|
https://qiskit.org/documentation/contributing_to_qiskit.html
|
|
|
|
## Contributing to Qiskit Terra
|
|
|
|
In addition to the general guidelines there are specific details for
|
|
contributing to terra, these are documented below.
|
|
|
|
### Contents
|
|
* [Choose an issue to work on](#Choose-an-issue-to-work-on)
|
|
* [Pull request checklist](#pull-request-checklist)
|
|
* [Changelog generation](#changelog-generation)
|
|
* [Release Notes](#release-notes)
|
|
* [Installing Qiskit Terra from source](#installing-qiskit-terra-from-source)
|
|
* [Test](#test)
|
|
* [Snapshot testing for visualizations](#snapshot-testing-for-visualizations)
|
|
* [Style and Lint](#style-and-lint)
|
|
* [Development Cycle](#development-cycle)
|
|
* [Branches](#branches)
|
|
* [Release Cycle](#release-cycle)
|
|
* [Adding deprecation warnings](#adding-deprecation-warnings)
|
|
* [Using dependencies](#using-dependencies)
|
|
* [Adding a requirement](#adding-a-requirement)
|
|
* [Adding an optional dependency](#adding-an-optional-dependency)
|
|
* [Checking for optionals](#checking-for-optionals)
|
|
* [Dealing with git blame ignore list](#dealing-with-the-git-blame-ignore-list)
|
|
|
|
### Choose an issue to work on
|
|
Qiskit Terra uses the following labels to help non-maintainers find issues best suited to their interests and experience level:
|
|
|
|
* [good first issue](https://github.com/Qiskit/qiskit-terra/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) - these issues are typically the simplest available to work on, perfect for newcomers. They should already be fully scoped, with a clear approach outlined in the descriptions.
|
|
* [help wanted](https://github.com/Qiskit/qiskit-terra/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) - these issues are generally more complex than good first issues. They typically cover work that core maintainers don't currently have capacity to implement and may require more investigation/discussion. These are a great option for experienced contributors looking for something a bit more challenging.
|
|
* [short project](https://github.com/Qiskit/qiskit-terra/issues?q=is%3Aopen+is%3Aissue+label%3A%22short+project%22) - these issues are bigger pieces of work that require greater time commitment. Good options for hackathons, internship projects etc.
|
|
|
|
### Pull request checklist
|
|
|
|
When submitting a pull request and you feel it is ready for review,
|
|
please ensure that:
|
|
|
|
1. The code follows the code style of the project and successfully
|
|
passes the tests. For convenience, you can execute `tox` locally,
|
|
which will run these checks and report any issues.
|
|
|
|
If your code fails the local style checks (specifically the black
|
|
code formatting check) you can use `tox -eblack` to automatically
|
|
fix update the code formatting.
|
|
2. The documentation has been updated accordingly. In particular, if a
|
|
function or class has been modified during the PR, please update the
|
|
*docstring* accordingly.
|
|
|
|
If your pull request is adding a new class, function, or module that is
|
|
intended to be user facing ensure that you've also added those to a
|
|
documentation `autosummary` index to include it in the api documentation.
|
|
For more details you can refer to:
|
|
|
|
https://qiskit.org/documentation/contributing_to_qiskit.html#documentation-structure
|
|
|
|
|
|
3. If it makes sense for your change that you have added new tests that
|
|
cover the changes.
|
|
4. Ensure that if your change has an end user facing impact (new feature,
|
|
deprecation, removal etc) that you have added a reno release note for that
|
|
change and that the PR is tagged for the changelog.
|
|
|
|
### Changelog generation
|
|
|
|
The changelog is automatically generated as part of the release process
|
|
automation. This works through a combination of the git log and the pull
|
|
request. When a release is tagged and pushed to github the release automation
|
|
bot looks at all commit messages from the git log for the release. It takes the
|
|
PR numbers from the git log (assuming a squash merge) and checks if that PR had
|
|
a `Changelog:` label on it. If there is a label it will add the git commit
|
|
message summary line from the git log for the release to the changelog.
|
|
|
|
If there are multiple `Changelog:` tags on a PR the git commit message summary
|
|
line from the git log will be used for each changelog category tagged.
|
|
|
|
The current categories for each label are as follows:
|
|
|
|
| PR Label | Changelog Category |
|
|
| -----------------------|--------------------|
|
|
| Changelog: Deprecation | Deprecated |
|
|
| Changelog: New Feature | Added |
|
|
| Changelog: API Change | Changed |
|
|
| Changelog: Removal | Removed |
|
|
| Changelog: Bugfix | Fixed |
|
|
|
|
### Release Notes
|
|
|
|
When making any end user facing changes in a contribution we have to make sure
|
|
we document that when we release a new version of qiskit-terra. The expectation
|
|
is that if your code contribution has user facing changes that you will write
|
|
the release documentation for these changes. This documentation must explain
|
|
what was changed, why it was changed, and how users can either use or adapt
|
|
to the change. The idea behind release documentation is that when a naive
|
|
user with limited internal knowledge of the project is upgrading from the
|
|
previous release to the new one, they should be able to read the release notes,
|
|
understand if they need to update their program which uses qiskit, and how they
|
|
would go about doing that. It ideally should explain why they need to make
|
|
this change too, to provide the necessary context.
|
|
|
|
To make sure we don't forget a release note or if the details of user facing
|
|
changes over a release cycle we require that all user facing changes include
|
|
documentation at the same time as the code. To accomplish this we use the
|
|
[reno](https://docs.openstack.org/reno/latest/) tool which enables a git based
|
|
workflow for writing and compiling release notes.
|
|
|
|
#### Adding a new release note
|
|
|
|
Making a new release note is quite straightforward. Ensure that you have reno
|
|
installed with:
|
|
|
|
pip install -U reno
|
|
|
|
Once you have reno installed you can make a new release note by running in
|
|
your local repository checkout's root:
|
|
|
|
reno new short-description-string
|
|
|
|
where short-description-string is a brief string (with no spaces) that describes
|
|
what's in the release note. This will become the prefix for the release note
|
|
file. Once that is run it will create a new yaml file in releasenotes/notes.
|
|
Then open that yaml file in a text editor and write the release note. The basic
|
|
structure of a release note is restructured text in yaml lists under category
|
|
keys. You add individual items under each category and they will be grouped
|
|
automatically by release when the release notes are compiled. A single file
|
|
can have as many entries in it as needed, but to avoid potential conflicts
|
|
you'll want to create a new file for each pull request that has user facing
|
|
changes. When you open the newly created file it will be a full template of
|
|
the different categories with a description of a category as a single entry
|
|
in each category. You'll want to delete all the sections you aren't using and
|
|
update the contents for those you are. For example, the end result should
|
|
look something like:
|
|
|
|
```yaml
|
|
features:
|
|
- |
|
|
Introduced a new feature foo, that adds support for doing something to
|
|
:class:`.QuantumCircuit` objects. It can be used by using the foo function,
|
|
for example::
|
|
|
|
from qiskit import foo
|
|
from qiskit import QuantumCircuit
|
|
foo(QuantumCircuit())
|
|
|
|
- |
|
|
The :class:`.QuantumCircuit` class has a new method :meth:`~.QuantumCircuit.foo`.
|
|
This is the equivalent of calling the :func:`~qiskit.foo` to do something to your
|
|
:class:`.QuantumCircuit`. This is the equivalent of running :func:`~qiskit.foo`
|
|
on your circuit, but provides the convenience of running it natively on
|
|
an object. For example::
|
|
|
|
from qiskit import QuantumCircuit
|
|
|
|
circ = QuantumCircuit()
|
|
circ.foo()
|
|
|
|
deprecations:
|
|
- |
|
|
The ``qiskit.bar`` module has been deprecated and will be removed in a
|
|
future release. Its sole function, ``foobar()`` has been superseded by the
|
|
:func:`~qiskit.foo` function which provides similar functionality but with
|
|
more accurate results and better performance. You should update your
|
|
:func:`~qiskit.bar.foobar` calls to :func:`~qiskit.foo`.
|
|
```
|
|
|
|
You can also look at other release notes for other examples.
|
|
|
|
Note that you can use sphinx [restructured text syntax](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html).
|
|
In fact, you can use any restructured text feature in them (code sections, tables,
|
|
enumerated lists, bulleted list, etc) to express what is being changed as
|
|
needed. In general you want the release notes to include as much detail as
|
|
needed so that users will understand what has changed, why it changed, and how
|
|
they'll have to update their code.
|
|
|
|
After you've finished writing your release notes you'll want to add the note
|
|
file to your commit with `git add` and commit them to your PR branch to make
|
|
sure they're included with the code in your PR.
|
|
|
|
##### Linking to issues
|
|
|
|
If you need to link to an issue or other github artifact as part of the release
|
|
note this should be done using an inline link with the text being the issue
|
|
number. For example you would write a release note with a link to issue 12345
|
|
as:
|
|
|
|
```yaml
|
|
fixes:
|
|
- |
|
|
Fixes a race condition in the function ``foo()``. Refer to
|
|
`#12345 <https://github.com/Qiskit/qiskit-terra/issues/12345>` for more
|
|
details.
|
|
```
|
|
|
|
#### Generating the release notes
|
|
|
|
After release notes have been added, you can use reno to see what the full output
|
|
of the release notes is. In general the output from reno that we'll get is a rst
|
|
(ReStructuredText) file that can be compiled by
|
|
[sphinx](https://www.sphinx-doc.org/en/master/). To generate the rst file you
|
|
use the ``reno report`` command. If you want to generate the full terra release
|
|
notes for all releases (since we started using reno during 0.9) you just run:
|
|
|
|
reno report
|
|
|
|
but you can also use the ``--version`` argument to view a single release (after
|
|
it has been tagged:
|
|
|
|
reno report --version 0.9.0
|
|
|
|
At release time ``reno report`` is used to generate the release notes for the
|
|
release and the output will be submitted as a pull request to the documentation
|
|
repository's [release notes file](
|
|
https://github.com/Qiskit/qiskit/blob/master/docs/release_notes.rst)
|
|
|
|
#### Building release notes locally
|
|
|
|
Building The release notes are part of the standard qiskit-terra documentation
|
|
builds. To check what the rendered html output of the release notes will look
|
|
like for the current state of the repo you can run: `tox -edocs` which will
|
|
build all the documentation into `docs/_build/html` and the release notes in
|
|
particular will be located at `docs/_build/html/release_notes.html`
|
|
|
|
## Installing Qiskit Terra from source
|
|
|
|
Qiskit Terra is primarily written in Python but there are some core routines
|
|
that are written in the [Rust](https://www.rust-lang.org/) programming
|
|
language to improve the runtime performance. For the released versions of
|
|
qiskit-terra we publish precompiled binaries on the
|
|
[Python Package Index](https://pypi.org/) for all the supported platforms
|
|
which only requires a functional Python environment to install. However, when
|
|
building and installing from source you will need a rust compiler installed. You can do this very easily
|
|
using rustup: https://rustup.rs/ which provides a single tool to install and
|
|
configure the latest version of the rust compiler.
|
|
[Other installation methods](https://forge.rust-lang.org/infra/other-installation-methods.html)
|
|
exist too. For Windows users, besides rustup, you will also need install
|
|
the Visual C++ build tools so that Rust can link against the system c/c++
|
|
libraries. You can see more details on this in the
|
|
[rustup documentation](https://rust-lang.github.io/rustup/installation/windows.html).
|
|
|
|
If you use Rustup, it will automatically install the correct Rust version
|
|
currently used by the project.
|
|
|
|
Once you have a Rust compiler installed, you can rely on the normal Python
|
|
build/install steps to install Qiskit Terra. This means you just run
|
|
`pip install .` in your local git clone to build and install Qiskit Terra.
|
|
|
|
Do note that if you do use develop mode/editable install (via `python setup.py develop` or `pip install -e .`) the Rust extension will be built in debug mode
|
|
without any optimizations enabled. This will result in poor runtime performance.
|
|
If you'd like to use an editable install with an optimized binary you can
|
|
run `python setup.py build_rust --release --inplace` after you install in
|
|
editable mode to recompile the rust extensions in release mode.
|
|
|
|
Note that in order to run `python setup.py ...` commands you need have build
|
|
dependency packages installed in your environment, which are listed in the
|
|
`pyproject.toml` file under the `[build-system]` section.
|
|
|
|
|
|
## Test
|
|
|
|
Once you've made a code change, it is important to verify that your change
|
|
does not break any existing tests and that any new tests that you've added
|
|
also run successfully. Before you open a new pull request for your change,
|
|
you'll want to run the test suite locally.
|
|
|
|
The easiest way to run the test suite is to use
|
|
[**tox**](https://tox.readthedocs.io/en/latest/#). You can install tox
|
|
with pip: `pip install -U tox`. Tox provides several advantages, but the
|
|
biggest one is that it builds an isolated virtualenv for running tests. This
|
|
means it does not pollute your system python when running. Additionally, the
|
|
environment that tox sets up matches the CI environment more closely and it
|
|
runs the tests in parallel (resulting in much faster execution). To run tests
|
|
on all installed supported python versions and lint/style checks you can simply
|
|
run `tox`. Or if you just want to run the tests once run for a specific python
|
|
version: `tox -epy310` (or replace py310 with the python version you want to use,
|
|
py39 or py311).
|
|
|
|
If you just want to run a subset of tests you can pass a selection regex to
|
|
the test runner. For example, if you want to run all tests that have "dag" in
|
|
the test id you can run: `tox -epy310 -- dag`. You can pass arguments directly to
|
|
the test runner after the bare `--`. To see all the options on test selection
|
|
you can refer to the stestr manual:
|
|
https://stestr.readthedocs.io/en/stable/MANUAL.html#test-selection
|
|
|
|
If you want to run a single test module, test class, or individual test method
|
|
you can do this faster with the `-n`/`--no-discover` option. For example:
|
|
|
|
to run a module:
|
|
```
|
|
tox -epy310 -- -n test.python.test_examples
|
|
```
|
|
or to run the same module by path:
|
|
|
|
```
|
|
tox -epy310 -- -n test/python/test_examples.py
|
|
```
|
|
to run a class:
|
|
|
|
```
|
|
tox -epy310 -- -n test.python.test_examples.TestPythonExamples
|
|
```
|
|
to run a method:
|
|
```
|
|
tox -epy310 -- -n test.python.test_examples.TestPythonExamples.test_all_examples
|
|
```
|
|
|
|
Alternatively there is a makefile provided to run tests, however this
|
|
does not perform any environment setup. It also doesn't run tests in
|
|
parallel and doesn't provide an option to easily modify the tests run.
|
|
For executing the tests with the makefile, a `make test` target is available.
|
|
The execution of the tests (both via the make target and during manual
|
|
invocation) takes into account the `LOG_LEVEL` environment variable. If
|
|
present, a `.log` file will be created on the test directory with the
|
|
output of the log calls, which will also be printed to stdout. You can
|
|
adjust the verbosity via the content of that variable, for example:
|
|
|
|
Linux and Mac:
|
|
|
|
``` {.bash}
|
|
$ cd out
|
|
out$ LOG_LEVEL="DEBUG" ARGS="-V" make test
|
|
```
|
|
|
|
Windows:
|
|
|
|
``` {.bash}
|
|
$ cd out
|
|
C:\..\out> set LOG_LEVEL="DEBUG"
|
|
C:\..\out> set ARGS="-V"
|
|
C:\..\out> make test
|
|
```
|
|
|
|
For executing a simple python test manually, we don\'t need to change
|
|
the directory to `out`, just run this command:
|
|
|
|
Linux and Mac:
|
|
|
|
``` {.bash}
|
|
$ LOG_LEVEL=INFO python -m unittest test/python/circuit/test_circuit_operations.py
|
|
```
|
|
|
|
Windows:
|
|
|
|
``` {.bash}
|
|
C:\..\> set LOG_LEVEL="INFO"
|
|
C:\..\> python -m unittest test/python/circuit/test_circuit_operations.py
|
|
```
|
|
|
|
##### STDOUT/STDERR and logging capture
|
|
|
|
When running tests in parallel using `stestr` either via tox, the Makefile
|
|
(`make test_ci`), or in CI we set the env variable
|
|
`QISKIT_TEST_CAPTURE_STREAMS` which will capture any text written to stdout,
|
|
stderr, and log messages and add them as attachments to the tests run so
|
|
output can be associated with the test case it originated from. However, if
|
|
you run tests with `stestr` outside of these mechanisms by default the streams
|
|
are not captured. To enable stream capture just set the
|
|
`QISKIT_TEST_CAPTURE_STREAMS` env variable to `1`. If this environment
|
|
variable is set outside of running with `stestr` the streams (STDOUT, STDERR,
|
|
and logging) will still be captured but **not** displayed in the test runners
|
|
output. If you are using the stdlib unittest runner a similar result can be
|
|
accomplished by using the
|
|
[`--buffer`](https://docs.python.org/3/library/unittest.html#command-line-options)
|
|
option (e.g. `python -m unittest discover --buffer ./test/python`).
|
|
|
|
##### Test Skip Options
|
|
|
|
How and which tests are executed is controlled by an environment
|
|
variable, `QISKIT_TESTS`:
|
|
|
|
Option | Description | Default
|
|
------ | ----------- | -------
|
|
`run_slow` | It runs tests tagged as *slow*. | `False`
|
|
|
|
It is possible to provide more than one option separated with commas.
|
|
|
|
Alternatively, the `make test_ci` target can be used instead of
|
|
`make test` in order to run in a setup that replicates the configuration
|
|
we used in our CI systems more closely.
|
|
|
|
### Snapshot Testing for Visualizations
|
|
|
|
If you are working on code that makes changes to any matplotlib visualisations
|
|
you will need to check that your changes don't break any snapshot tests, and add
|
|
new tests where necessary. You can do this as follows:
|
|
|
|
1. Make sure you have pushed your latest changes to your remote branch.
|
|
2. Go to link: `https://mybinder.org/v2/gh/<github_user>/<repo>/<branch>?urlpath=apps/test/ipynb/mpl_tester.ipynb`. For example, if your GitHub username is `username`, your forked repo has the same name the original, and your branch is `my_awesome_new_feature`, you should visit https://mybinder.org/v2/gh/username/qiskit-terra/my_awesome_new_feature?urlpath=apps/test/ipynb/mpl_tester.ipynb.
|
|
This opens a Jupyter Notebook application running in the cloud that automatically runs
|
|
the snapshot tests (note this may take some time to finish loading).
|
|
3. Each test result provides a set of 3 images (left: reference image, middle: your test result, right: differences). In the list of tests the passed tests are collapsed and failed tests are expanded. If a test fails, you will see a situation like this:
|
|
|
|
<img width="995" alt="Screenshot_2021-03-26_at_14 13 54" src="https://user-images.githubusercontent.com/23662430/112663508-d363e800-8e50-11eb-9478-6d665d0ff086.png">
|
|
4. Fix any broken tests. Working on code for one aspect of the visualisations
|
|
can sometimes result in minor changes elsewhere to spacing etc. In these cases
|
|
you just need to update the reference images as follows:
|
|
- download the mismatched images (link at top of Jupyter Notebook output)
|
|
- unzip the folder
|
|
- copy and paste the new images into `qiskit-terra/test/ipynb/mpl/references`,
|
|
replacing the existing reference images
|
|
- add, commit and push your changes, then restart the Jupyter Notebook app in your browser. The
|
|
tests should now pass.
|
|
5. Add new snapshot tests covering your new features, extensions, or bugfixes.
|
|
- add your new snapshot tests to `test/ipynb/mpl/test_circuit_matplotlib_drawer.py`
|
|
, where you can also find existing tests to use as a guide.
|
|
- commit and push your changes, restart the Jupyter Notebook app in your browser.
|
|
As this is the first time you run your new tests there won't be any reference
|
|
images to compare to. Instead you should see an option in the list of tests
|
|
to download the new images, like so:
|
|
|
|
<img width="1002" alt="Screenshot_2021-03-26_at_15 38 31" src="https://user-images.githubusercontent.com/23662430/112665215-b9c3a000-8e52-11eb-89e7-b18550718522.png">
|
|
|
|
- download the new images, then copy and paste into `qiskit-terra/test/ipynb/mpl/references`
|
|
- add, commit and push your changes, restart the Jupyter Notebook app in your browser. The
|
|
new tests should now pass.
|
|
|
|
Note: If you have run `test/ipynb/mpl_tester.ipynb` locally it is possible some file metadata has changed, **please do not commit and push changes to this file unless they were intentional**.
|
|
|
|
## Style and lint
|
|
|
|
Qiskit Terra uses three tools for verify code formatting and lint checking. The
|
|
first tool is [black](https://github.com/psf/black) which is a code formatting
|
|
tool that will automatically update the code formatting to a consistent style.
|
|
The second tool is [pylint](https://www.pylint.org/) which is a code linter
|
|
which does a deeper analysis of the Python code to find both style issues and
|
|
potential bugs and other common issues in Python. The third tool is the linter
|
|
[ruff](https://github.com/charliermarsh/ruff), which has been recently
|
|
introduced into Qiskit Terra on an experimental basis. Only a very small number
|
|
of rules are enabled.
|
|
|
|
You can check that your local modifications conform to the style rules by
|
|
running `tox -elint` which will run `black`, `ruff`, and `pylint` to check the
|
|
local code formatting and lint. If black returns a code formatting error you can
|
|
run `tox -eblack` to automatically update the code formatting to conform to the
|
|
style. However, if `ruff` or `pylint` return any error you will have to fix
|
|
these issues by manually updating your code.
|
|
|
|
Because `pylint` analysis can be slow, there is also a `tox -elint-incr` target,
|
|
which runs `black` and `ruff` just as `tox -elint` does, but only applies
|
|
`pylint` to files which have changed from the source github. On rare occasions
|
|
this will miss some issues that would have been caught by checking the complete
|
|
source tree, but makes up for this by being much faster (and those rare
|
|
oversights will still be caught by the CI after you open a pull request).
|
|
|
|
Because they are so fast, it is sometimes convenient to run the tools `black` and `ruff` separately
|
|
rather than via `tox`. If you have installed the development packages in your python environment via
|
|
`pip install -r requirements-dev.txt`, then `ruff` and `black` will be available and can be run from
|
|
the command line. See [`tox.ini`](tox.ini) for how `tox` invokes them.
|
|
|
|
## Development Cycle
|
|
|
|
The development cycle for qiskit-terra is all handled in the open using
|
|
the project boards in Github for project management. We use milestones
|
|
in Github to track work for specific releases. The features or other changes
|
|
that we want to include in a release will be tagged and discussed in Github.
|
|
As we're preparing a new release we'll document what has changed since the
|
|
previous version in the release notes.
|
|
|
|
### Branches
|
|
|
|
* `main`:
|
|
|
|
The main branch is used for development of the next version of qiskit-terra.
|
|
It will be updated frequently and should not be considered stable. The API
|
|
can and will change on main as we introduce and refine new features.
|
|
|
|
* `stable/*` branches:
|
|
Branches under `stable/*` are used to maintain released versions of qiskit-terra.
|
|
It contains the version of the code corresponding to the latest release for
|
|
that minor version on pypi. For example, stable/0.8 contains the code for the
|
|
0.8.2 release on pypi. The API on these branches are stable and the only changes
|
|
merged to it are bugfixes.
|
|
|
|
### Release cycle
|
|
|
|
In the lead up to a release there are a few things to keep in mind. Prior to
|
|
the release date there is a feature, removal, and deprecation proposal freeze
|
|
date. This date in each release cycle is the last day where a new PR adding a
|
|
new feature, removing something, or adding a new deprecation can be proposed (in
|
|
a ready for review state) for potential inclusion in the release. If a new
|
|
PR is opened after this date it will not be considered for inclusion in that
|
|
release. Note, that meeting these deadlines does not guarantee inclusion in a
|
|
release: they are preconditions. You can refer to the milestone page for each
|
|
release to see these dates for each release (for example for 0.21.0 the page is:
|
|
https://github.com/Qiskit/qiskit-terra/milestone/23).
|
|
|
|
After the proposal freeze a release review period will begin, during this time
|
|
release candidate PRs will be reviewed as we finalize the feature set and merge
|
|
the last PRs for the release. Following the review period a release candidate will be
|
|
tagged and published. This release candidate is pre-release that enables users and
|
|
developers to test the release ahead of time. When the pre-release is tagged the release
|
|
automation will publish the pre-release to PyPI (but only get installed on user request),
|
|
create the `stable/*` branch, and generate a pre-release changelog/release page. At
|
|
this point the `main` opens up for development of the next release. The `stable/*`
|
|
branches should only receive changes in the form of bug fixes at this point. If there
|
|
is a need additional release candidates can be published from `stable/*` and when the
|
|
release is ready a full release will be tagged and published from `stable/*`.
|
|
|
|
## Adding deprecation warnings
|
|
The qiskit-terra code is part of Qiskit and, therefore, the [Qiskit Deprecation Policy](https://qiskit.org/documentation/contributing_to_qiskit.html#deprecation-policy) fully applies here. Additionally, qiskit-terra does not allow `DeprecationWarning`s in its testsuite. If you are deprecating code, you should add a test to use the new/non-deprecated method (most of the time based on the existing test of the deprecated method) and alter the existing test to check that the deprecated method still works as expected, [using `assertWarns`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertWarns). The `assertWarns` context will silence the deprecation warning while checking that it raises.
|
|
|
|
For example, if `Obj.method1` is being deprecated in favour of `Obj.method2`, the existing test (or tests) for `method1` might look like this:
|
|
|
|
```python
|
|
def test_method1(self):
|
|
result = Obj.method1()
|
|
self.assertEqual(result, <expected>)
|
|
```
|
|
|
|
Deprecating `method1` means that `Obj.method1()` now raises a deprecation warning and the test will not pass. The existing test should be updated and a new test added for `method2`:
|
|
|
|
|
|
```python
|
|
def test_method1_deprecated(self):
|
|
with self.assertWarns(DeprecationWarning):
|
|
result = Obj.method1()
|
|
self.assertEqual(result, <expected>)
|
|
|
|
def test_method2(self):
|
|
result = Obj.method2()
|
|
self.assertEqual(result, <expected>)
|
|
```
|
|
|
|
`test_method1_deprecated` can be removed after `Obj.method1` is removed (following the [Qiskit Deprecation Policy](https://qiskit.org/documentation/contributing_to_qiskit.html#deprecation-policy)).
|
|
|
|
## Using dependencies
|
|
|
|
We distinguish between "requirements" and "optional dependencies" in qiskit-terra.
|
|
A requirement is a package that is absolutely necessary for core functionality in qiskit-terra, such as Numpy or Scipy.
|
|
An optional dependency is a package that is used for specialized functionality, which might not be needed by all users.
|
|
If a new feature has a new dependency, it is almost certainly optional.
|
|
|
|
### Adding a requirement
|
|
|
|
Any new requirement must have broad system support; it needs to be supported on all the Python versions and operating systems that qiskit-terra supports.
|
|
It also cannot impose many version restrictions on other packages.
|
|
Users often install qiskit-terra into virtual environments with many different packages in, and we need to ensure that neither we, nor any of our requirements, conflict with their other packages.
|
|
When adding a new requirement, you must add it to [`requirements.txt`](requirements.txt) with as loose a constraint on the allowed versions as possible.
|
|
|
|
### Adding an optional dependency
|
|
|
|
New features can also use optional dependencies, which might be used only in very limited parts of qiskit-terra.
|
|
These are not required to use the rest of the package, and so should not be added to `requirements.txt`.
|
|
Instead, if several optional dependencies are grouped together to provide one feature, you can consider adding an "extra" to the package metadata, such as the `visualization` extra that installs Matplotlib and Seaborn (amongst others).
|
|
To do this, modify the [`setup.py`](setup.py) file, adding another entry in the `extras_require` keyword argument to `setup()` at the bottom of the file.
|
|
You do not need to be quite as accepting of all versions here, but it is still a good idea to be as permissive as you possibly can be.
|
|
You should also add a new "tester" to [`qiskit.utils.optionals`](qiskit/utils/optionals.py), for use in the next section.
|
|
|
|
### Checking for optionals
|
|
|
|
You cannot `import` an optional dependency at the top of a file, because if it is not installed, it will raise an error and qiskit-terra will be unusable.
|
|
We also largely want to avoid importing packages until they are actually used; if we import a lot of packages during `import qiskit`, it becomes sluggish for the user if they have a large environment.
|
|
Instead, you should use [one of the "lazy testers" for optional dependencies](https://qiskit.org/documentation/apidoc/utils.html#module-qiskit.utils.optionals), and import your optional dependency inside the function or class that uses it, as in the examples within that link.
|
|
Very lightweight _requirements_ can be imported at the tops of files, but even this should be limited; it's always ok to `import numpy`, but Scipy modules are relatively heavy, so only import them within functions that use them.
|
|
|
|
|
|
## Dealing with the git blame ignore list
|
|
|
|
In the qiskit-terra repository we maintain a list of commits for git blame
|
|
to ignore. This is mostly commits that are code style changes that don't
|
|
change the functionality but just change the code formatting (for example,
|
|
when we migrated to use black for code formatting). This file,
|
|
`.git-blame-ignore-revs` just contains a list of commit SHA1s you can tell git
|
|
to ignore when using the `git blame` command. This can be done one time
|
|
with something like
|
|
|
|
```
|
|
git blame --ignore-revs-file .git-blame-ignore-revs qiskit/version.py
|
|
|
|
```
|
|
|
|
from the root of the repository. If you'd like to enable this by default you
|
|
can update your local repository's configuration with:
|
|
|
|
```
|
|
git config blame.ignoreRevsFile .git-blame-ignore-revs
|
|
```
|
|
|
|
which will update your local repositories configuration to use the ignore list
|
|
by default.
|