prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  pyhf json2xml requires pyhf[contrib]
  # Description
  
  ```
  $ pip install pyhf[xmlio]
  $ pyhf json2xml -h
  ERROR:pyhf.contrib.utils:No module named 'requests'
  Installation of the contrib extra is required to use pyhf.contrib.utils.download
  Please install with: python -m pip install pyhf[contrib]
  
  Usage: pyhf json2xml [OPTIONS] [WORKSPACE]
  
    Convert pyhf JSON back to XML + ROOT files.
  
  Options:
    --output-dir PATH
    --specroot TEXT
    --dataroot TEXT
    --resultprefix TEXT
    -p, --patch TEXT
    -h, --help           Show this message and exit.
  ```
  
  # Expected Behavior
  
  Shown the help without any reference to pyhf.contrib as this does not depend on contrib.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/pyhf/contrib/cli.py`
  Content:
  ```
  1 """CLI for functionality that will get migrated out eventually."""
  2 import logging
  3 import click
  4 from pathlib import Path
  5 
  6 from . import utils
  7 
  8 logging.basicConfig()
  9 log = logging.getLogger(__name__)
  10 
  11 
  12 @click.group(name="contrib")
  13 def cli():
  14     """
  15     Contrib experimental operations.
  16 
  17     .. note::
  18 
  19         Requires installation of the ``contrib`` extra.
  20 
  21         .. code-block:: shell
  22 
  23             $ python -m pip install pyhf[contrib]
  24     """
  25 
  26 
  27 @cli.command()
  28 @click.argument("archive-url")
  29 @click.argument("output-directory")
  30 @click.option("-v", "--verbose", is_flag=True, help="Enables verbose mode")
  31 @click.option(
  32     "-f", "--force", is_flag=True, help="Force download from non-approved host"
  33 )
  34 @click.option(
  35     "-c",
  36     "--compress",
  37     is_flag=True,
  38     help="Keep the archive in a compressed tar.gz form",
  39 )
  40 def download(archive_url, output_directory, verbose, force, compress):
  41     """
  42     Download the patchset archive from the remote URL and extract it in a
  43     directory at the path given.
  44 
  45     Example:
  46 
  47     .. code-block:: shell
  48 
  49         $ pyhf contrib download --verbose https://doi.org/10.17182/hepdata.90607.v3/r3 1Lbb-likelihoods
  50 
  51         \b
  52         1Lbb-likelihoods/patchset.json
  53         1Lbb-likelihoods/README.md
  54         1Lbb-likelihoods/BkgOnly.json
  55 
  56     Raises:
  57         :class:`~pyhf.exceptions.InvalidArchiveHost`: if the provided archive host name is not known to be valid
  58     """
  59     try:
  60         utils.download(archive_url, output_directory, force, compress)
  61 
  62         if verbose:
  63             file_list = [str(file) for file in list(Path(output_directory).glob("*"))]
  64             print("\n".join(file_list))
  65     except AttributeError as excep:
  66         exception_info = (
  67             str(excep)
  68             + "\nInstallation of the contrib extra is required to use the contrib CLI API"
  69             + "\nPlease install with: python -m pip install pyhf[contrib]\n"
  70         )
  71         log.error(exception_info)
  72
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/pyhf/contrib/cli.py b/src/pyhf/contrib/cli.py
  --- a/src/pyhf/contrib/cli.py
  +++ b/src/pyhf/contrib/cli.py
  @@ -3,8 +3,6 @@
   import click
   from pathlib import Path
   
  -from . import utils
  -
   logging.basicConfig()
   log = logging.getLogger(__name__)
   
  @@ -22,6 +20,10 @@
   
               $ python -m pip install pyhf[contrib]
       """
  +    from . import utils  # Guard CLI from missing extra
  +
  +    # TODO: https://github.com/scikit-hep/pyhf/issues/863
  +    _ = utils  # Placate pyflakes
   
   
   @cli.command()
  @@ -57,6 +59,8 @@
           :class:`~pyhf.exceptions.InvalidArchiveHost`: if the provided archive host name is not known to be valid
       """
       try:
  +        from . import utils
  +
           utils.download(archive_url, output_directory, force, compress)
   
           if verbose:
  
verification_info: {"golden_diff": "diff --git a/src/pyhf/contrib/cli.py b/src/pyhf/contrib/cli.py\n--- a/src/pyhf/contrib/cli.py\n+++ b/src/pyhf/contrib/cli.py\n@@ -3,8 +3,6 @@\n import click\n from pathlib import Path\n \n-from . import utils\n-\n logging.basicConfig()\n log = logging.getLogger(__name__)\n \n@@ -22,6 +20,10 @@\n \n             $ python -m pip install pyhf[contrib]\n     \"\"\"\n+    from . import utils  # Guard CLI from missing extra\n+\n+    # TODO: https://github.com/scikit-hep/pyhf/issues/863\n+    _ = utils  # Placate pyflakes\n \n \n @cli.command()\n@@ -57,6 +59,8 @@\n         :class:`~pyhf.exceptions.InvalidArchiveHost`: if the provided archive host name is not known to be valid\n     \"\"\"\n     try:\n+        from . import utils\n+\n         utils.download(archive_url, output_directory, force, compress)\n \n         if verbose:\n", "issue": "pyhf json2xml requires pyhf[contrib]\n# Description\r\n\r\n```\r\n$ pip install pyhf[xmlio]\r\n$ pyhf json2xml -h\r\nERROR:pyhf.contrib.utils:No module named 'requests'\r\nInstallation of the contrib extra is required to use pyhf.contrib.utils.download\r\nPlease install with: python -m pip install pyhf[contrib]\r\n\r\nUsage: pyhf json2xml [OPTIONS] [WORKSPACE]\r\n\r\n  Convert pyhf JSON back to XML + ROOT files.\r\n\r\nOptions:\r\n  --output-dir PATH\r\n  --specroot TEXT\r\n  --dataroot TEXT\r\n  --resultprefix TEXT\r\n  -p, --patch TEXT\r\n  -h, --help           Show this message and exit.\r\n```\r\n\r\n# Expected Behavior\r\n\r\nShown the help without any reference to pyhf.contrib as this does not depend on contrib.\n", "before_files": [{"content": "\"\"\"CLI for functionality that will get migrated out eventually.\"\"\"\nimport logging\nimport click\nfrom pathlib import Path\n\nfrom . import utils\n\nlogging.basicConfig()\nlog = logging.getLogger(__name__)\n\n\n@click.group(name=\"contrib\")\ndef cli():\n    \"\"\"\n    Contrib experimental operations.\n\n    .. note::\n\n        Requires installation of the ``contrib`` extra.\n\n        .. code-block:: shell\n\n            $ python -m pip install pyhf[contrib]\n    \"\"\"\n\n\n@cli.command()\n@click.argument(\"archive-url\")\n@click.argument(\"output-directory\")\n@click.option(\"-v\", \"--verbose\", is_flag=True, help=\"Enables verbose mode\")\n@click.option(\n    \"-f\", \"--force\", is_flag=True, help=\"Force download from non-approved host\"\n)\n@click.option(\n    \"-c\",\n    \"--compress\",\n    is_flag=True,\n    help=\"Keep the archive in a compressed tar.gz form\",\n)\ndef download(archive_url, output_directory, verbose, force, compress):\n    \"\"\"\n    Download the patchset archive from the remote URL and extract it in a\n    directory at the path given.\n\n    Example:\n\n    .. code-block:: shell\n\n        $ pyhf contrib download --verbose https://doi.org/10.17182/hepdata.90607.v3/r3 1Lbb-likelihoods\n\n        \\b\n        1Lbb-likelihoods/patchset.json\n        1Lbb-likelihoods/README.md\n        1Lbb-likelihoods/BkgOnly.json\n\n    Raises:\n        :class:`~pyhf.exceptions.InvalidArchiveHost`: if the provided archive host name is not known to be valid\n    \"\"\"\n    try:\n        utils.download(archive_url, output_directory, force, compress)\n\n        if verbose:\n            file_list = [str(file) for file in list(Path(output_directory).glob(\"*\"))]\n            print(\"\\n\".join(file_list))\n    except AttributeError as excep:\n        exception_info = (\n            str(excep)\n            + \"\\nInstallation of the contrib extra is required to use the contrib CLI API\"\n            + \"\\nPlease install with: python -m pip install pyhf[contrib]\\n\"\n        )\n        log.error(exception_info)\n", "path": "src/pyhf/contrib/cli.py"}], "after_files": [{"content": "\"\"\"CLI for functionality that will get migrated out eventually.\"\"\"\nimport logging\nimport click\nfrom pathlib import Path\n\nlogging.basicConfig()\nlog = logging.getLogger(__name__)\n\n\n@click.group(name=\"contrib\")\ndef cli():\n    \"\"\"\n    Contrib experimental operations.\n\n    .. note::\n\n        Requires installation of the ``contrib`` extra.\n\n        .. code-block:: shell\n\n            $ python -m pip install pyhf[contrib]\n    \"\"\"\n    from . import utils  # Guard CLI from missing extra\n\n    # TODO: https://github.com/scikit-hep/pyhf/issues/863\n    _ = utils  # Placate pyflakes\n\n\n@cli.command()\n@click.argument(\"archive-url\")\n@click.argument(\"output-directory\")\n@click.option(\"-v\", \"--verbose\", is_flag=True, help=\"Enables verbose mode\")\n@click.option(\n    \"-f\", \"--force\", is_flag=True, help=\"Force download from non-approved host\"\n)\n@click.option(\n    \"-c\",\n    \"--compress\",\n    is_flag=True,\n    help=\"Keep the archive in a compressed tar.gz form\",\n)\ndef download(archive_url, output_directory, verbose, force, compress):\n    \"\"\"\n    Download the patchset archive from the remote URL and extract it in a\n    directory at the path given.\n\n    Example:\n\n    .. code-block:: shell\n\n        $ pyhf contrib download --verbose https://doi.org/10.17182/hepdata.90607.v3/r3 1Lbb-likelihoods\n\n        \\b\n        1Lbb-likelihoods/patchset.json\n        1Lbb-likelihoods/README.md\n        1Lbb-likelihoods/BkgOnly.json\n\n    Raises:\n        :class:`~pyhf.exceptions.InvalidArchiveHost`: if the provided archive host name is not known to be valid\n    \"\"\"\n    try:\n        from . import utils\n\n        utils.download(archive_url, output_directory, force, compress)\n\n        if verbose:\n            file_list = [str(file) for file in list(Path(output_directory).glob(\"*\"))]\n            print(\"\\n\".join(file_list))\n    except AttributeError as excep:\n        exception_info = (\n            str(excep)\n            + \"\\nInstallation of the contrib extra is required to use the contrib CLI API\"\n            + \"\\nPlease install with: python -m pip install pyhf[contrib]\\n\"\n        )\n        log.error(exception_info)\n", "path": "src/pyhf/contrib/cli.py"}]}