We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
In Python 3.12 tarfile raises DeprecationWarning: Python 3.14 will, by default, filter extracted tar archives and reject files or modify their metadata.
While testing Python 3.12 in CI

https://github.com/scikit-hep/pyhf/blob/adddb0797c564a0158a8e2e69a58ee1f98604bf7/tests/test_scripts.py#L591-L604

raised

```pytb
>       assert ret.success
E       assert False
E        +  where False = <pytest_console_scripts.RunResult object at 0x29fd18b90>.success
...
DeprecationWarning: Python 3.14 will, by default, filter extracted tar archives and reject files or modify their metadata. Use the filter argument to control this behavior.
```

This should get fixed before Python 3.12 support is added.

--- 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/utils.py`
Content:
```
1 """Helper utilities for common tasks."""
2 
3 import logging
4 import tarfile
5 import zipfile
6 from io import BytesIO
7 from pathlib import Path
8 from shutil import rmtree
9 from urllib.parse import urlsplit
10 
11 from pyhf import exceptions
12 
13 log = logging.getLogger(__name__)
14 
15 __all__ = ["download"]
16 
17 
18 def __dir__():
19     return __all__
20 
21 
22 try:
23     import requests
24 
25     def download(archive_url, output_directory, force=False, compress=False):
26         """
27         Download the patchset archive from the remote URL and extract it in a
28         directory at the path given.
29 
30         Example:
31 
32             >>> from pyhf.contrib.utils import download
33             >>> download("https://doi.org/10.17182/hepdata.90607.v3/r3", "1Lbb-likelihoods")  # doctest: +SKIP
34             >>> import os
35             >>> sorted(os.listdir("1Lbb-likelihoods"))  # doctest: +SKIP
36             ['BkgOnly.json', 'README.md', 'patchset.json']
37             >>> download("https://doi.org/10.17182/hepdata.90607.v3/r3", "1Lbb-likelihoods.tar.gz", compress=True)  # doctest: +SKIP
38             >>> import glob
39             >>> glob.glob("1Lbb-likelihoods.tar.gz")  # doctest: +SKIP
40             ['1Lbb-likelihoods.tar.gz']
41 
42         Args:
43             archive_url (:obj:`str`): The URL of the :class:`~pyhf.patchset.PatchSet` archive to download.
44             output_directory (:obj:`str`): Name of the directory to unpack the archive into.
45             force (:obj:`bool`): Force download from non-approved host. Default is ``False``.
46             compress (:obj:`bool`): Keep the archive in a compressed ``tar.gz`` form. Default is ``False``.
47 
48         Raises:
49             :class:`~pyhf.exceptions.InvalidArchiveHost`: if the provided archive host name is not known to be valid
50         """
51         if not force:
52             valid_hosts = ["www.hepdata.net", "doi.org"]
53             netloc = urlsplit(archive_url).netloc
54             if netloc not in valid_hosts:
55                 raise exceptions.InvalidArchiveHost(
56                     f"{netloc} is not an approved archive host: {', '.join(str(host) for host in valid_hosts)}\n"
57                     + "To download an archive from this host use the --force option."
58                 )
59 
60         # c.f. https://github.com/scikit-hep/pyhf/issues/1491
61         # > Use content negotiation at the landing page for the resource that
62         # > the DOI resolves to. DataCite content negotiation is forwarding all
63         # > requests with unknown content types to the URL registered in the
64         # > handle system.
65         # c.f. https://blog.datacite.org/changes-to-doi-content-negotiation/
66         # The HEPData landing page for the resource file can check if the Accept
67         # request HTTP header matches the content type of the resource file and
68         # return the content directly if so.
69         with requests.get(
70             archive_url, headers={"Accept": "application/x-tar, application/zip"}
71         ) as response:
72             if response.status_code != 200:
73                 raise exceptions.InvalidArchive(
74                     f"{archive_url} gives a response code of {response.status_code}.\n"
75                     + "There is either something temporarily wrong with the archive host"
76                     + f" or {archive_url} is an invalid URL."
77                 )
78 
79             if compress:
80                 with open(output_directory, "wb") as archive:
81                     archive.write(response.content)
82             else:
83                 # Support for file-like objects for tarfile.is_tarfile was added
84                 # in Python 3.9, so as pyhf is currently Python 3.8+ then can't
85                 # do tarfile.is_tarfile(BytesIO(response.content)).
86                 # Instead, just use a 'try except' block to determine if the
87                 # archive is a valid tarfile.
88                 # TODO: Simplify after pyhf is Python 3.9+ only
89                 try:
90                     # Use transparent compression to allow for .tar or .tar.gz
91                     with tarfile.open(
92                         mode="r:*", fileobj=BytesIO(response.content)
93                     ) as archive:
94                         archive.extractall(output_directory)
95                 except tarfile.ReadError:
96                     if not zipfile.is_zipfile(BytesIO(response.content)):
97                         raise exceptions.InvalidArchive(
98                             f"The archive downloaded from {archive_url} is not a tarfile"
99                             + " or a zipfile and so can not be opened as one."
100                         )
101 
102                     output_directory = Path(output_directory)
103                     if output_directory.exists():
104                         rmtree(output_directory)
105                     with zipfile.ZipFile(BytesIO(response.content)) as archive:
106                         archive.extractall(output_directory)
107 
108                         # zipfile.ZipFile.extractall extracts to a directory
109                         # below a target directory, so to match the extraction
110                         # path of tarfile.TarFile.extractall move the extracted
111                         # directory to a temporary path and then replace the
112                         # output directory target with the contents at the
113                         # temporary path.
114                         # The directory is moved instead of being extracted one
115                         # directory up and then renamed as the name of the
116                         # zipfile directory is set at zipfile creation time and
117                         # isn't knowable in advance.
118                         child_path = next(iter(output_directory.iterdir()))
119                         _tmp_path = output_directory.parent.joinpath(
120                             Path(output_directory.name + "__tmp__")
121                         )
122                         child_path.replace(_tmp_path)
123                         # the zipfile could contain remnant __MACOSX directories
124                         # from creation time
125                         rmtree(output_directory)
126                         _tmp_path.replace(output_directory)
127 
128 except ModuleNotFoundError:
129     log.error(
130         "\nInstallation of the contrib extra is required to use pyhf.contrib.utils.download"
131         + "\nPlease install with: python -m pip install 'pyhf[contrib]'\n",
132         exc_info=True,
133     )
134
```
--- 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()

```

diff --git a/src/pyhf/contrib/utils.py b/src/pyhf/contrib/utils.py
--- a/src/pyhf/contrib/utils.py
+++ b/src/pyhf/contrib/utils.py
@@ -91,7 +91,12 @@
                     with tarfile.open(
                         mode="r:*", fileobj=BytesIO(response.content)
                     ) as archive:
-                        archive.extractall(output_directory)
+                        # TODO: Simplify after pyhf is Python 3.12+ only
+                        # c.f. https://docs.python.org/3.12/library/tarfile.html#extraction-filters
+                        if hasattr(tarfile, "data_filter"):
+                            archive.extractall(output_directory, filter="data")
+                        else:
+                            archive.extractall(output_directory)
                 except tarfile.ReadError:
                     if not zipfile.is_zipfile(BytesIO(response.content)):
                         raise exceptions.InvalidArchive(

{"golden_diff": "diff --git a/src/pyhf/contrib/utils.py b/src/pyhf/contrib/utils.py\n--- a/src/pyhf/contrib/utils.py\n+++ b/src/pyhf/contrib/utils.py\n@@ -91,7 +91,12 @@\n                     with tarfile.open(\n                         mode=\"r:*\", fileobj=BytesIO(response.content)\n                     ) as archive:\n-                        archive.extractall(output_directory)\n+                        # TODO: Simplify after pyhf is Python 3.12+ only\n+                        # c.f. https://docs.python.org/3.12/library/tarfile.html#extraction-filters\n+                        if hasattr(tarfile, \"data_filter\"):\n+                            archive.extractall(output_directory, filter=\"data\")\n+                        else:\n+                            archive.extractall(output_directory)\n                 except tarfile.ReadError:\n                     if not zipfile.is_zipfile(BytesIO(response.content)):\n                         raise exceptions.InvalidArchive(\n", "issue": "In Python 3.12 tarfile raises DeprecationWarning: Python 3.14 will, by default, filter extracted tar archives and reject files or modify their metadata.\nWhile testing Python 3.12 in CI\r\n\r\nhttps://github.com/scikit-hep/pyhf/blob/adddb0797c564a0158a8e2e69a58ee1f98604bf7/tests/test_scripts.py#L591-L604\r\n\r\nraised\r\n\r\n```pytb\r\n>       assert ret.success\r\nE       assert False\r\nE        +  where False = <pytest_console_scripts.RunResult object at 0x29fd18b90>.success\r\n...\r\nDeprecationWarning: Python 3.14 will, by default, filter extracted tar archives and reject files or modify their metadata. Use the filter argument to control this behavior.\r\n```\r\n\r\nThis should get fixed before Python 3.12 support is added.\n", "before_files": [{"content": "\"\"\"Helper utilities for common tasks.\"\"\"\n\nimport logging\nimport tarfile\nimport zipfile\nfrom io import BytesIO\nfrom pathlib import Path\nfrom shutil import rmtree\nfrom urllib.parse import urlsplit\n\nfrom pyhf import exceptions\n\nlog = logging.getLogger(__name__)\n\n__all__ = [\"download\"]\n\n\ndef __dir__():\n    return __all__\n\n\ntry:\n    import requests\n\n    def download(archive_url, output_directory, force=False, compress=False):\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            >>> from pyhf.contrib.utils import download\n            >>> download(\"https://doi.org/10.17182/hepdata.90607.v3/r3\", \"1Lbb-likelihoods\")  # doctest: +SKIP\n            >>> import os\n            >>> sorted(os.listdir(\"1Lbb-likelihoods\"))  # doctest: +SKIP\n            ['BkgOnly.json', 'README.md', 'patchset.json']\n            >>> download(\"https://doi.org/10.17182/hepdata.90607.v3/r3\", \"1Lbb-likelihoods.tar.gz\", compress=True)  # doctest: +SKIP\n            >>> import glob\n            >>> glob.glob(\"1Lbb-likelihoods.tar.gz\")  # doctest: +SKIP\n            ['1Lbb-likelihoods.tar.gz']\n\n        Args:\n            archive_url (:obj:`str`): The URL of the :class:`~pyhf.patchset.PatchSet` archive to download.\n            output_directory (:obj:`str`): Name of the directory to unpack the archive into.\n            force (:obj:`bool`): Force download from non-approved host. Default is ``False``.\n            compress (:obj:`bool`): Keep the archive in a compressed ``tar.gz`` form. Default is ``False``.\n\n        Raises:\n            :class:`~pyhf.exceptions.InvalidArchiveHost`: if the provided archive host name is not known to be valid\n        \"\"\"\n        if not force:\n            valid_hosts = [\"www.hepdata.net\", \"doi.org\"]\n            netloc = urlsplit(archive_url).netloc\n            if netloc not in valid_hosts:\n                raise exceptions.InvalidArchiveHost(\n                    f\"{netloc} is not an approved archive host: {', '.join(str(host) for host in valid_hosts)}\\n\"\n                    + \"To download an archive from this host use the --force option.\"\n                )\n\n        # c.f. https://github.com/scikit-hep/pyhf/issues/1491\n        # > Use content negotiation at the landing page for the resource that\n        # > the DOI resolves to. DataCite content negotiation is forwarding all\n        # > requests with unknown content types to the URL registered in the\n        # > handle system.\n        # c.f. https://blog.datacite.org/changes-to-doi-content-negotiation/\n        # The HEPData landing page for the resource file can check if the Accept\n        # request HTTP header matches the content type of the resource file and\n        # return the content directly if so.\n        with requests.get(\n            archive_url, headers={\"Accept\": \"application/x-tar, application/zip\"}\n        ) as response:\n            if response.status_code != 200:\n                raise exceptions.InvalidArchive(\n                    f\"{archive_url} gives a response code of {response.status_code}.\\n\"\n                    + \"There is either something temporarily wrong with the archive host\"\n                    + f\" or {archive_url} is an invalid URL.\"\n                )\n\n            if compress:\n                with open(output_directory, \"wb\") as archive:\n                    archive.write(response.content)\n            else:\n                # Support for file-like objects for tarfile.is_tarfile was added\n                # in Python 3.9, so as pyhf is currently Python 3.8+ then can't\n                # do tarfile.is_tarfile(BytesIO(response.content)).\n                # Instead, just use a 'try except' block to determine if the\n                # archive is a valid tarfile.\n                # TODO: Simplify after pyhf is Python 3.9+ only\n                try:\n                    # Use transparent compression to allow for .tar or .tar.gz\n                    with tarfile.open(\n                        mode=\"r:*\", fileobj=BytesIO(response.content)\n                    ) as archive:\n                        archive.extractall(output_directory)\n                except tarfile.ReadError:\n                    if not zipfile.is_zipfile(BytesIO(response.content)):\n                        raise exceptions.InvalidArchive(\n                            f\"The archive downloaded from {archive_url} is not a tarfile\"\n                            + \" or a zipfile and so can not be opened as one.\"\n                        )\n\n                    output_directory = Path(output_directory)\n                    if output_directory.exists():\n                        rmtree(output_directory)\n                    with zipfile.ZipFile(BytesIO(response.content)) as archive:\n                        archive.extractall(output_directory)\n\n                        # zipfile.ZipFile.extractall extracts to a directory\n                        # below a target directory, so to match the extraction\n                        # path of tarfile.TarFile.extractall move the extracted\n                        # directory to a temporary path and then replace the\n                        # output directory target with the contents at the\n                        # temporary path.\n                        # The directory is moved instead of being extracted one\n                        # directory up and then renamed as the name of the\n                        # zipfile directory is set at zipfile creation time and\n                        # isn't knowable in advance.\n                        child_path = next(iter(output_directory.iterdir()))\n                        _tmp_path = output_directory.parent.joinpath(\n                            Path(output_directory.name + \"__tmp__\")\n                        )\n                        child_path.replace(_tmp_path)\n                        # the zipfile could contain remnant __MACOSX directories\n                        # from creation time\n                        rmtree(output_directory)\n                        _tmp_path.replace(output_directory)\n\nexcept ModuleNotFoundError:\n    log.error(\n        \"\\nInstallation of the contrib extra is required to use pyhf.contrib.utils.download\"\n        + \"\\nPlease install with: python -m pip install 'pyhf[contrib]'\\n\",\n        exc_info=True,\n    )\n", "path": "src/pyhf/contrib/utils.py"}], "after_files": [{"content": "\"\"\"Helper utilities for common tasks.\"\"\"\n\nimport logging\nimport tarfile\nimport zipfile\nfrom io import BytesIO\nfrom pathlib import Path\nfrom shutil import rmtree\nfrom urllib.parse import urlsplit\n\nfrom pyhf import exceptions\n\nlog = logging.getLogger(__name__)\n\n__all__ = [\"download\"]\n\n\ndef __dir__():\n    return __all__\n\n\ntry:\n    import requests\n\n    def download(archive_url, output_directory, force=False, compress=False):\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            >>> from pyhf.contrib.utils import download\n            >>> download(\"https://doi.org/10.17182/hepdata.90607.v3/r3\", \"1Lbb-likelihoods\")  # doctest: +SKIP\n            >>> import os\n            >>> sorted(os.listdir(\"1Lbb-likelihoods\"))  # doctest: +SKIP\n            ['BkgOnly.json', 'README.md', 'patchset.json']\n            >>> download(\"https://doi.org/10.17182/hepdata.90607.v3/r3\", \"1Lbb-likelihoods.tar.gz\", compress=True)  # doctest: +SKIP\n            >>> import glob\n            >>> glob.glob(\"1Lbb-likelihoods.tar.gz\")  # doctest: +SKIP\n            ['1Lbb-likelihoods.tar.gz']\n\n        Args:\n            archive_url (:obj:`str`): The URL of the :class:`~pyhf.patchset.PatchSet` archive to download.\n            output_directory (:obj:`str`): Name of the directory to unpack the archive into.\n            force (:obj:`bool`): Force download from non-approved host. Default is ``False``.\n            compress (:obj:`bool`): Keep the archive in a compressed ``tar.gz`` form. Default is ``False``.\n\n        Raises:\n            :class:`~pyhf.exceptions.InvalidArchiveHost`: if the provided archive host name is not known to be valid\n        \"\"\"\n        if not force:\n            valid_hosts = [\"www.hepdata.net\", \"doi.org\"]\n            netloc = urlsplit(archive_url).netloc\n            if netloc not in valid_hosts:\n                raise exceptions.InvalidArchiveHost(\n                    f\"{netloc} is not an approved archive host: {', '.join(str(host) for host in valid_hosts)}\\n\"\n                    + \"To download an archive from this host use the --force option.\"\n                )\n\n        # c.f. https://github.com/scikit-hep/pyhf/issues/1491\n        # > Use content negotiation at the landing page for the resource that\n        # > the DOI resolves to. DataCite content negotiation is forwarding all\n        # > requests with unknown content types to the URL registered in the\n        # > handle system.\n        # c.f. https://blog.datacite.org/changes-to-doi-content-negotiation/\n        # The HEPData landing page for the resource file can check if the Accept\n        # request HTTP header matches the content type of the resource file and\n        # return the content directly if so.\n        with requests.get(\n            archive_url, headers={\"Accept\": \"application/x-tar, application/zip\"}\n        ) as response:\n            if response.status_code != 200:\n                raise exceptions.InvalidArchive(\n                    f\"{archive_url} gives a response code of {response.status_code}.\\n\"\n                    + \"There is either something temporarily wrong with the archive host\"\n                    + f\" or {archive_url} is an invalid URL.\"\n                )\n\n            if compress:\n                with open(output_directory, \"wb\") as archive:\n                    archive.write(response.content)\n            else:\n                # Support for file-like objects for tarfile.is_tarfile was added\n                # in Python 3.9, so as pyhf is currently Python 3.8+ then can't\n                # do tarfile.is_tarfile(BytesIO(response.content)).\n                # Instead, just use a 'try except' block to determine if the\n                # archive is a valid tarfile.\n                # TODO: Simplify after pyhf is Python 3.9+ only\n                try:\n                    # Use transparent compression to allow for .tar or .tar.gz\n                    with tarfile.open(\n                        mode=\"r:*\", fileobj=BytesIO(response.content)\n                    ) as archive:\n                        # TODO: Simplify after pyhf is Python 3.12+ only\n                        # c.f. https://docs.python.org/3.12/library/tarfile.html#extraction-filters\n                        if hasattr(tarfile, \"data_filter\"):\n                            archive.extractall(output_directory, filter=\"data\")\n                        else:\n                            archive.extractall(output_directory)\n                except tarfile.ReadError:\n                    if not zipfile.is_zipfile(BytesIO(response.content)):\n                        raise exceptions.InvalidArchive(\n                            f\"The archive downloaded from {archive_url} is not a tarfile\"\n                            + \" or a zipfile and so can not be opened as one.\"\n                        )\n\n                    output_directory = Path(output_directory)\n                    if output_directory.exists():\n                        rmtree(output_directory)\n                    with zipfile.ZipFile(BytesIO(response.content)) as archive:\n                        archive.extractall(output_directory)\n\n                        # zipfile.ZipFile.extractall extracts to a directory\n                        # below a target directory, so to match the extraction\n                        # path of tarfile.TarFile.extractall move the extracted\n                        # directory to a temporary path and then replace the\n                        # output directory target with the contents at the\n                        # temporary path.\n                        # The directory is moved instead of being extracted one\n                        # directory up and then renamed as the name of the\n                        # zipfile directory is set at zipfile creation time and\n                        # isn't knowable in advance.\n                        child_path = next(iter(output_directory.iterdir()))\n                        _tmp_path = output_directory.parent.joinpath(\n                            Path(output_directory.name + \"__tmp__\")\n                        )\n                        child_path.replace(_tmp_path)\n                        # the zipfile could contain remnant __MACOSX directories\n                        # from creation time\n                        rmtree(output_directory)\n                        _tmp_path.replace(output_directory)\n\nexcept ModuleNotFoundError:\n    log.error(\n        \"\\nInstallation of the contrib extra is required to use pyhf.contrib.utils.download\"\n        + \"\\nPlease install with: python -m pip install 'pyhf[contrib]'\\n\",\n        exc_info=True,\n    )\n", "path": "src/pyhf/contrib/utils.py"}]}