diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2163a74ac4..7236b6cac2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -72,6 +72,8 @@ jobs: run: python -m pip install -U tox - name: Run lint run: tox -elint + - name: Lint docs + run: tox -edocs-lint -- -W docs: name: docs runs-on: ubuntu-latest diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 728d50509e..1f978af76f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -89,7 +89,7 @@ python when running. Additionally, the environment that tox sets up matches the 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 for a -specific python version such as 3.10: `tox -epy310`. +specific python version such as 3.10: `tox -e py310`. 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 @@ -138,13 +138,13 @@ The qiskit-experiments repository uses `black` for code formatting and style and `pylint` for linting. You can run these checks locally with ``` -tox -elint +tox -e lint ``` If there is a code formatting issue identified by black you can just run ``black`` -locally to fix this (or ``tox -eblack`` which will install it and run it). +locally to fix this (or ``tox -e black`` which will install it and run it). -Because `pylint` analysis can be slow, there is also a `tox -elint-incr` target, which +Because `pylint` analysis can be slow, there is also a `tox -e lint-incr` target, which 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 @@ -341,8 +341,9 @@ https://github.com/Qiskit-Extensions/qiskit-experiments` and `git fetch upstream There are a few other build options available: -* `tox -edocs-minimal`: build documentation without executing Jupyter code cells -* `tox -edocs-parallel`: do a full build with multiprocessing (may crash on Macs) +* `tox -e docs-minimal`: build documentation without executing Jupyter code cells +* `tox -e docs-parallel`: do a full build with multiprocessing (may crash on Macs) +* `tox -e docs-lint`: lint docs and check for broken links ### Deprecation policy diff --git a/docs/conf.py b/docs/conf.py index 0570307794..4bf1adbd0d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,7 +16,6 @@ import os import sys -import subprocess import datetime # -- Path setup -------------------------------------------------------------- diff --git a/docs/lint/conf.py b/docs/lint/conf.py new file mode 100644 index 0000000000..e407b4c8c5 --- /dev/null +++ b/docs/lint/conf.py @@ -0,0 +1,163 @@ +# This is the configuration file to run sphinx linting for `tox -edocs-nitpick`. +# It will output warnings for each missing reference. + +import sys, os, datetime + +sys.path.insert(0, os.path.abspath("../")) +sys.path.append(os.path.abspath("../_ext")) +sys.path.append(os.path.abspath("../../")) + +# Set env flag so that we can doc functions that may otherwise not be loaded +# see for example interactive visualizations in qiskit.visualization. +os.environ["QISKIT_DOCS"] = "TRUE" + +# -- Project information ----------------------------------------------------- +# The short X.Y version +version = "0.5" +# The full version, including alpha/beta/rc tags +release = "0.5.0" +project = f"Qiskit Experiments {version}" +copyright = f"2021-{datetime.date.today().year}, Qiskit Development Team" # pylint: disable=redefined-builtin +author = "Qiskit Development Team" + + +project = "Qiskit Experiments" +nitpicky = True + +# within nit-picking build, do not refer to any intersphinx object +intersphinx_mapping = {} + +extensions = [ + "sphinx.ext.napoleon", + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.mathjax", + "sphinx.ext.viewcode", + "sphinx.ext.extlinks", + "jupyter_sphinx", + "reno.sphinxext", + "sphinx_design", + "sphinx.ext.intersphinx", + "nbsphinx", + "autoref", + "autodoc_experiment", + "autodoc_analysis", + "autodoc_visualization", + "jupyter_execute_custom", +] + +# Minimal options to let the build run successfully +nbsphinx_timeout = 360 +nbsphinx_execute = os.getenv("QISKIT_DOCS_BUILD_TUTORIALS", "never") +nbsphinx_widgets_path = "" +exclude_patterns = ["_build", "**.ipynb_checkpoints"] +napoleon_custom_sections = [("data keys", "params_style"), ("style parameters", "params_style")] +autosummary_generate = True +autodoc_default_options = {"inherited-members": None} +numfig = True +numfig_format = {"table": "Table %s"} +language = "en" +exclude_patterns = ["_build", "**.ipynb_checkpoints"] +pygments_style = "colorful" +add_module_names = False +modindex_common_prefix = ["qiskit_experiments."] +html_theme = "qiskit_sphinx_theme" # use the theme in subdir 'theme' +html_context = { + "analytics_enabled": True, + "expandable_sidebar": True, +} +html_last_updated_fmt = "%Y/%m/%d" +html_theme_options = { + "logo_only": True, + "display_version": True, + "prev_next_buttons_location": "bottom", + "style_external_links": True, +} +autoclass_content = "both" +intersphinx_mapping = { + "matplotlib": ("https://matplotlib.org/stable/", None), + "qiskit": ("https://qiskit.org/documentation/", None), + "uncertainties": ("https://pythonhosted.org/uncertainties", None), +} +if os.getenv("EXPERIMENTS_DEV_DOCS", None): + rst_prolog = """ +.. note:: + This is the documentation for the current state of the development branch + of Qiskit Experiments. The documentation or APIs here can change prior to being + released. +""" + + +def setup(app): + app.connect("autodoc-skip-member", maybe_skip_member) + + +# Hardcoded list of class variables to skip in autodoc to avoid warnings +# Should come up with better way to address this + +from qiskit_experiments.curve_analysis import ParameterRepr +from qiskit_experiments.curve_analysis import SeriesDef + + +def maybe_skip_member(app, what, name, obj, skip, options): + skip_names = [ + "analysis", + "set_run_options", + "data_allocation", + "labels", + "shots", + "x", + "y", + "y_err", + "name", + "filter_kwargs", + "fit_func", + "signature", + ] + skip_members = [ + ParameterRepr.repr, + ParameterRepr.unit, + SeriesDef.plot_color, + SeriesDef.plot_symbol, + SeriesDef.model_description, + SeriesDef.canvas, + ] + if not skip: + return (name in skip_names or obj in skip_members) and what == "attribute" + return skip + + +### + +linkcheck_ignore = [ + r"manuals/index.html", + "tutorials/index.html", + "howtos/index.html", + "cloud_service.html", + "apidocs/index.html", +] + +# Ignore these objects +nitpick_ignore_regex = [ + ("py:.*", "qiskit.*"), + ("py:.*", "numpy.*"), + ("py:.*", "sklearn.*"), + ("py:.*", "scipy.*"), + ("py:.*", "datetime.*"), + ("py:.*", "IBM.*"), + ("py:.*", ".*\._.*"), + ("py:.*", "_.*"), + ("py:.*", "lmfit.*"), + ("py:.*", "uncertainties.*"), + ("py:.*", ".*__.*"), + ("py:.*", "typing.*"), + ("py:.*", ".*Error"), + ("py:.*", "Ellipsis"), + ("py:.*", "matplotlib.*"), +] + +# Deprecated objects that should be ignored in the release notes +nitpick_ignore_regex += [ + ("py:*", "MplCurveDrawer.*"), + ("py:.*", "CliffordUtils.*"), +] diff --git a/docs/manuals/measurement/readout_mitigation.rst b/docs/manuals/measurement/readout_mitigation.rst index a97b5e844b..a2cc8c3e8c 100644 --- a/docs/manuals/measurement/readout_mitigation.rst +++ b/docs/manuals/measurement/readout_mitigation.rst @@ -180,4 +180,4 @@ See also * API documentation: :mod:`~qiskit_experiments.library.characterization.LocalReadoutError`, :mod:`~qiskit_experiments.library.characterization.CorrelatedReadoutError` -* Qiskit Textbook: `Measurement Error Mitigation `__ +* Qiskit Textbook: `Measurement Error Mitigation `__ diff --git a/docs/manuals/verification/quantum_volume.rst b/docs/manuals/verification/quantum_volume.rst index a4ea74e771..f15fd0ff41 100644 --- a/docs/manuals/verification/quantum_volume.rst +++ b/docs/manuals/verification/quantum_volume.rst @@ -190,5 +190,5 @@ See also -------- * API documentation: :mod:`~qiskit_experiments.library.quantum_volume` -* Qiskit Textbook: `Measuring Quantum Volume `__ +* Qiskit Textbook: `Measuring Quantum Volume `__ diff --git a/docs/tutorials/calibrations.rst b/docs/tutorials/calibrations.rst index 02dc1613be..9ff3d5ab00 100644 --- a/docs/tutorials/calibrations.rst +++ b/docs/tutorials/calibrations.rst @@ -491,7 +491,7 @@ See also -------- * API documentation: :mod:`~qiskit_experiments.calibration_management` and :mod:`~qiskit_experiments.library.calibration` -* Qiskit Textbook: `Calibrating Qubits with Qiskit Pulse `__ +* Qiskit Textbook: `Calibrating Qubits with Qiskit Pulse `__ diff --git a/qiskit_experiments/framework/matplotlib.py b/qiskit_experiments/framework/matplotlib.py index dd98fe3652..ed43ceb493 100644 --- a/qiskit_experiments/framework/matplotlib.py +++ b/qiskit_experiments/framework/matplotlib.py @@ -19,7 +19,7 @@ default_figure_canvas = FigureCanvasSVG # pylint: disable=invalid-name """Matplotlib canvas to use when rendering a figure. This needs to be a canvas for a `non-interactive backend -`_. +https://matplotlib.org/stable/users/explain/backends.html#the-builtin-backends>`_. The default is `FigureCanvasSVG`.""" diff --git a/qiskit_experiments/library/characterization/cr_hamiltonian.py b/qiskit_experiments/library/characterization/cr_hamiltonian.py index 11aeb4bc63..34b3d1cd98 100644 --- a/qiskit_experiments/library/characterization/cr_hamiltonian.py +++ b/qiskit_experiments/library/characterization/cr_hamiltonian.py @@ -124,7 +124,7 @@ class CrossResonanceHamiltonian(BaseExperiment): # section: manual .. ref_website:: Qiskit Textbook 6.7, - https://qiskit.org/textbook/ch-quantum-hardware/hamiltonian-tomography.html + https://learn.qiskit.org/course/quantum-hardware-pulses/hamiltonian-tomography """ # Number of CR pulses. The flat top duration per pulse is divided by this number. diff --git a/qiskit_experiments/library/characterization/multi_state_discrimination.py b/qiskit_experiments/library/characterization/multi_state_discrimination.py index f4e2689f7b..9962d52b03 100644 --- a/qiskit_experiments/library/characterization/multi_state_discrimination.py +++ b/qiskit_experiments/library/characterization/multi_state_discrimination.py @@ -56,7 +56,7 @@ class MultiStateDiscrimination(BaseExperiment): # section: reference `Qiskit Textbook\ - `_ + `_ """ diff --git a/qiskit_experiments/library/characterization/rabi.py b/qiskit_experiments/library/characterization/rabi.py index 2b2d73ae10..641cedcbc1 100644 --- a/qiskit_experiments/library/characterization/rabi.py +++ b/qiskit_experiments/library/characterization/rabi.py @@ -51,8 +51,8 @@ class Rabi(BaseExperiment, RestlessMixin): # section: manual :ref:`Rabi Calibration` - See also `Qiskit Textbook `_ + See also `Qiskit Textbook + `_ for the pulse level programming of a Rabi experiment. # section: analysis_ref diff --git a/qiskit_experiments/library/quantum_volume/qv_experiment.py b/qiskit_experiments/library/quantum_volume/qv_experiment.py index 0770c2bbcf..163c0e8492 100644 --- a/qiskit_experiments/library/quantum_volume/qv_experiment.py +++ b/qiskit_experiments/library/quantum_volume/qv_experiment.py @@ -42,7 +42,7 @@ class QuantumVolume(BaseExperiment): The Quantum Volume is determined by the largest circuit depth :math:`d_{max}`, and equals to :math:`2^{d_{max}}`. See `Qiskit Textbook - `_ + `_ for an explanation on the QV protocol. In the QV experiment we generate :class:`~qiskit.circuit.library.QuantumVolume` circuits on diff --git a/qiskit_experiments/library/randomized_benchmarking/standard_rb.py b/qiskit_experiments/library/randomized_benchmarking/standard_rb.py index 60bb8e23aa..e3718a9229 100644 --- a/qiskit_experiments/library/randomized_benchmarking/standard_rb.py +++ b/qiskit_experiments/library/randomized_benchmarking/standard_rb.py @@ -61,7 +61,7 @@ class StandardRB(BaseExperiment, RestlessMixin): Randomized Benchmarking (RB) is an efficient and robust method for estimating the average error rate of a set of quantum gate operations. See `Qiskit Textbook - `_ + `_ for an explanation on the RB method. A standard RB experiment generates sequences of random Cliffords diff --git a/releasenotes/notes/0.2/0_2_release-eef5e3ba256fc750.yaml b/releasenotes/notes/0.2/0_2_release-eef5e3ba256fc750.yaml index 333fcb785d..6def023058 100644 --- a/releasenotes/notes/0.2/0_2_release-eef5e3ba256fc750.yaml +++ b/releasenotes/notes/0.2/0_2_release-eef5e3ba256fc750.yaml @@ -19,7 +19,7 @@ features: ``qiskit_experiments.framework.matplotlib.default_figure_canvas`` to the desired canvas. Note that it has to be a canvas for one of the `non-interactive backend - `_. + `_. For example, you can set ``default_figure_canvas`` to :class:`~matplotlib.backends.backend_agg.FigureCanvasAgg` to use the ``AGG`` backend. diff --git a/requirements-dev.txt b/requirements-dev.txt index 4e07866fd9..20fbef2f1e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -20,6 +20,7 @@ pylatexenc multimethod scikit-learn sphinx-copybutton +sphinxcontrib-jupyter # Pin versions below because of build errors ipykernel<=6.21.3 jupyter-client<=8.0.3 diff --git a/tox.ini b/tox.ini index 6839e04a93..13e9f718f9 100644 --- a/tox.ini +++ b/tox.ini @@ -75,6 +75,17 @@ setenv = commands = sphinx-build -T -W --keep-going -b html {posargs} docs/ docs/_build/html +[testenv:docs-lint] +passenv = EXPERIMENTS_DEV_DOCS +setenv = + QISKIT_DOCS_SKIP_EXECUTE = 1 +commands = + sphinx-build -c docs/lint -T --keep-going -b linkcheck {posargs} docs/ docs/_build/html + +[pycodestyle] +max-line-length = 100 + + [testenv:docs-clean] skip_install = true deps =