diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 69216c270c..9bd4f2dca9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,7 +55,7 @@ We recommend first reading the "[Developing](https://scikit-hep.org/pyhf/develop You can install the development environment (which includes a number of extra) libraries and all others needed to run the tests via `pip`: ```console -python -m pip install --upgrade --editable .[complete] +python -m pip install --upgrade --editable '.[develop]' ``` To make the PR process much smoother we also strongly recommend that you setup the Git pre-commit hook for [Black](https://github.com/psf/black) by running diff --git a/binder/postBuild b/binder/postBuild index 50f54b1874..c7af738a91 100644 --- a/binder/postBuild +++ b/binder/postBuild @@ -1,2 +1,2 @@ -python -m pip install --upgrade .[complete] +python -m pip install --upgrade '.[all]' python -m pip install altair diff --git a/binder/runtime.txt b/binder/runtime.txt index 55090899d0..67ebc4e9a6 100644 --- a/binder/runtime.txt +++ b/binder/runtime.txt @@ -1 +1 @@ -python-3.10 +python-3.11 diff --git a/docs/development.rst b/docs/development.rst index 0dba51e151..a35b2cba96 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -7,7 +7,7 @@ Developer Environment To develop, we suggest using Python `virtual environments `__ -together with ``pip``. +together with ``pip`` and steered by `nox `__. Once the virtual environment is activated and you have `SSH keys setup with GitHub `__, clone the repo from GitHub @@ -20,7 +20,7 @@ and install all necessary packages for development .. code-block:: console - python -m pip install --upgrade --editable .[complete] + python -m pip install --upgrade --editable '.[develop]' Then setup the Git `pre-commit `__ hooks by running @@ -33,6 +33,30 @@ inside of the virtual environment. through time, so pre-commit will automatically update itself when you run it locally after the hooks were updated. +It is then suggested that you use ``nox`` to actually run all development operations +in "sessions" defined in ``noxfile.py``. +To list all of the available sessions run + +.. code-block:: console + + nox --list + +Linting +------- + +Linting and code formatting is handled by ``pre-commit``. +To run the linting either run ``pre-commit`` + +.. code-block:: console + + pre-commit run --all-files + +or use ``nox`` + +.. code-block:: console + + nox --session lint + Testing ------- @@ -73,7 +97,7 @@ contrib module, or notebooks, and so instead to test the core codebase a develop .. code-block:: console - pytest --ignore tests/benchmarks/ --ignore tests/contrib --ignore tests/test_notebooks.py + nox --session tests --python 3.11 Contrib module matplotlib image tests ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -83,7 +107,14 @@ To run the visualization tests for the ``contrib`` module with the ``pytest-mpl` .. code-block:: console - pytest tests/contrib --mpl --mpl-baseline-path tests/contrib/baseline --mpl-generate-summary html + nox --session tests --python 3.11 -- contrib + +If the image files need to be regenerated, run the tests with the +``--mpl-generate-path=tests/contrib/baseline`` option or just run + +.. code-block:: console + + nox --session regenerate Doctest ^^^^^^^ @@ -97,6 +128,52 @@ For example, to run ``doctest`` on the JAX backend run pytest src/pyhf/tensor/jax_backend.py +Coverage +~~~~~~~~ + +To measure coverage for the codebase run the tests under ``coverage`` with + +.. code-block:: console + + coverage run --module pytest + +or pass ``coverage`` as a positional argument to the ``nox`` ``tests`` session + +.. code-block:: console + + nox --session tests --python 3.11 -- coverage + +Coverage Report +^^^^^^^^^^^^^^^ + +To generate a coverage report after running the tests under ``coverage`` run + +.. code-block:: console + + coverage + +or to also generate XML and HTML versions of the report run the coverage ``nox`` session + +.. code-block:: console + + nox --session coverage + +Documentation +------------- + +To build the docs run + +.. code-block:: console + + nox --session docs + +To view the built docs locally, open the resulting ``docs/_build/html/index.html`` file +in a web browser or run + +.. code-block:: console + + nox --session docs -- serve + Publishing ---------- diff --git a/docs/examples/notebooks/learn/InterpolationCodes.ipynb b/docs/examples/notebooks/learn/InterpolationCodes.ipynb index 2c57b94035..07868c080f 100644 --- a/docs/examples/notebooks/learn/InterpolationCodes.ipynb +++ b/docs/examples/notebooks/learn/InterpolationCodes.ipynb @@ -4,19 +4,11 @@ "cell_type": "code", "execution_count": 1, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Populating the interactive namespace from numpy and matplotlib\n" - ] - } - ], + "outputs": [], "source": [ - "%pylab inline\n", - "from ipywidgets import interact\n", "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from ipywidgets import interact\n", "from mpl_toolkits.mplot3d import Axes3D" ] }, diff --git a/docs/installation.rst b/docs/installation.rst index a3e14e7371..3cd820bc41 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -32,28 +32,28 @@ Install latest stable release from `PyPI `__... .. code-block:: console - python -m pip install pyhf[tensorflow] + python -m pip install 'pyhf[tensorflow]' ... with PyTorch backend ++++++++++++++++++++++++ .. code-block:: console - python -m pip install pyhf[torch] + python -m pip install 'pyhf[torch]' ... with JAX backend ++++++++++++++++++++ .. code-block:: console - python -m pip install pyhf[jax] + python -m pip install 'pyhf[jax]' ... with all backends +++++++++++++++++++++ .. code-block:: console - python -m pip install pyhf[backends] + python -m pip install 'pyhf[backends]' ... with xml import/export functionality @@ -61,7 +61,7 @@ Install latest stable release from `PyPI `__... .. code-block:: console - python -m pip install pyhf[xmlio] + python -m pip install 'pyhf[xmlio]' Install latest development version from `GitHub `__... @@ -72,35 +72,35 @@ Install latest development version from `GitHub `_. (PR :pr:`2145`) -* The ``tensorflow`` extra (``'pyhf[tensorlfow]'``) now automatically installs +* The ``tensorflow`` extra (``'pyhf[tensorflow]'``) now automatically installs ``tensorflow-macos`` for Apple silicon machines. (PR :pr:`2119`) diff --git a/src/pyhf/cli/complete.py b/src/pyhf/cli/complete.py index 4b21bd3bff..58fda5604f 100644 --- a/src/pyhf/cli/complete.py +++ b/src/pyhf/cli/complete.py @@ -21,9 +21,9 @@ def cli(shell): @click.command(help='Generate shell completion code.', name='completions') @click.argument('shell', default=None) def cli(shell): - '''Placeholder for shell completion code generatioon function if necessary dependency is missing.''' + """Placeholder for shell completion code generatioon function if necessary dependency is missing.""" click.secho( - 'This requires the click_completion module.\n' - 'You can install it with the shellcomplete extra:\n' - 'python -m pip install pyhf[shellcomplete]' + "This requires the click_completion module.\n" + "You can install it with the shellcomplete extra:\n" + "python -m pip install 'pyhf[shellcomplete]'" ) diff --git a/src/pyhf/cli/rootio.py b/src/pyhf/cli/rootio.py index 053304f381..95d8872a84 100644 --- a/src/pyhf/cli/rootio.py +++ b/src/pyhf/cli/rootio.py @@ -50,7 +50,7 @@ def xml2json( except ImportError: log.error( "xml2json requires uproot, please install pyhf using the " - "xmlio extra: python -m pip install pyhf[xmlio]", + "xmlio extra: python -m pip install 'pyhf[xmlio]'", exc_info=True, ) from pyhf import readxml @@ -86,7 +86,7 @@ def json2xml(workspace, output_dir, specroot, dataroot, resultprefix, patch): except ImportError: log.error( "json2xml requires uproot, please install pyhf using the " - "xmlio extra: python -m pip install pyhf[xmlio]", + "xmlio extra: python -m pip install 'pyhf[xmlio]'", exc_info=True, ) from pyhf import writexml diff --git a/src/pyhf/contrib/cli.py b/src/pyhf/contrib/cli.py index 967cb43902..eaf2bb7e23 100644 --- a/src/pyhf/contrib/cli.py +++ b/src/pyhf/contrib/cli.py @@ -24,7 +24,7 @@ def cli(): .. code-block:: shell - $ python -m pip install pyhf[contrib] + $ python -m pip install 'pyhf[contrib]' """ from pyhf.contrib import utils # Guard CLI from missing extra # noqa: F401 @@ -72,6 +72,6 @@ def download(archive_url, output_directory, verbose, force, compress): except AttributeError: log.error( "\nInstallation of the contrib extra is required to use the contrib CLI API" - + "\nPlease install with: python -m pip install pyhf[contrib]\n", + + "\nPlease install with: python -m pip install 'pyhf[contrib]'\n", exc_info=True, ) diff --git a/src/pyhf/contrib/utils.py b/src/pyhf/contrib/utils.py index da6daedd32..b810b94aa6 100644 --- a/src/pyhf/contrib/utils.py +++ b/src/pyhf/contrib/utils.py @@ -128,6 +128,6 @@ def download(archive_url, output_directory, force=False, compress=False): except ModuleNotFoundError: log.error( "\nInstallation of the contrib extra is required to use pyhf.contrib.utils.download" - + "\nPlease install with: python -m pip install pyhf[contrib]\n", + + "\nPlease install with: python -m pip install 'pyhf[contrib]'\n", exc_info=True, ) diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 4ff8d7fd03..780b35809a 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -632,7 +632,7 @@ def test_missing_contrib_extra(caplog): for line in [ "import of requests halted; None in sys.modules", "Installation of the contrib extra is required to use pyhf.contrib.utils.download", - "Please install with: python -m pip install pyhf[contrib]", + "Please install with: python -m pip install 'pyhf[contrib]'", ]: assert line in caplog.text caplog.clear() @@ -672,7 +672,7 @@ def test_missing_contrib_download(caplog): for line in [ "module 'pyhf.contrib.utils' has no attribute 'download'", "Installation of the contrib extra is required to use the contrib CLI API", - "Please install with: python -m pip install pyhf[contrib]", + "Please install with: python -m pip install 'pyhf[contrib]'", ]: assert line in caplog.text caplog.clear()