Repository: conda/conda-package-handling (language: python)

Issue:
Update python matrix (add 3.10, 3.11, 3.12 - drop 3.7)
### Description

- Removes python 3.7
    - Because `conda` no longer supports 3.7
- Adds python 3.10, 3.11, and 3.12
    - All Supported by `conda` now

### Checklist - did you ...

- [x] Add a file to the `news` directory ([using the template](../blob/main/news/TEMPLATE)) for the next release's release notes?
- [ ] Add / update necessary tests?
- [ ] Add / update outdated documentation?
    - I don't see any documentation that shows the python version range

### Extra Note

In `python 3.12` this now raises the following warning:

> `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.`

That relates to https://docs.python.org/3/library/tarfile.html#extraction-filters and specifically in 3.8->3.12 an non-specified filter will default to `fully_trusted` which may not be secure.  I went with *not* altering the behavior in this PR, but a followup issue should be filed/acted on to decide how we want to proceed.

This is a warning that is also present on `3.12` CI for `conda` itself.


Discussion / hints:

Fix patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7d2d35c9..a8b39733 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -19,7 +19,7 @@ repos:
     rev: v3.15.0
     hooks:
       - id: pyupgrade
-        args: ["--py37-plus"]
+        args: ["--py38-plus"]
   - repo: https://github.com/PyCQA/isort
     rev: 5.12.0
     hooks:
diff --git a/news/python-update b/news/python-update
new file mode 100644
index 00000000..c9cf0d4d
--- /dev/null
+++ b/news/python-update
@@ -0,0 +1,19 @@
+### Enhancements
+
+* Added formal support for Python 3.10, 3.11, and 3.12. (#231)
+
+### Bug fixes
+
+* <news item>
+
+### Deprecations
+
+* Removed formal support for Python 3.7. (#231)
+
+### Docs
+
+* <news item>
+
+### Other
+
+* <news item>
diff --git a/setup.py b/setup.py
index f6ae5832..8d1f0309 100644
--- a/setup.py
+++ b/setup.py
@@ -24,7 +24,7 @@
     entry_points={"console_scripts": ["cph=conda_package_handling.cli:main"]},
     keywords="conda-package-handling",
     classifiers=["Programming Language :: Python :: 3"],
-    python_requires=">=3.7",
+    python_requires=">=3.8",
     install_requires=["conda-package-streaming >= 0.9.0"],
     extras_require={
         "docs": ["furo", "sphinx", "sphinx-argparse", "myst-parser", "mdit-py-plugins>=0.3.0"],


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 1957705a..13a63871 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -15,7 +15,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, windows-latest]
-        python-version: [3.7, 3.8, 3.9]
+        python-version: [3.8, 3.9, '3.10', 3.11, 3.12]
 
     steps:
     - uses: actions/checkout@v3
diff --git a/tests/memory_test.py b/tests/memory_test.py
index 38d1e87f..dc2f3e9e 100644
--- a/tests/memory_test.py
+++ b/tests/memory_test.py
@@ -1,6 +1,7 @@
 """
 Simple test for evaluating zstandard binding memory usage.
 """
+
 import io
 import sys
 
diff --git a/tests/test_degraded.py b/tests/test_degraded.py
index 929b8f0b..ca8af288 100644
--- a/tests/test_degraded.py
+++ b/tests/test_degraded.py
@@ -6,6 +6,7 @@
 import importlib
 import subprocess
 import sys
+import warnings
 
 
 def test_degraded():
@@ -17,21 +18,28 @@ def test_degraded():
         # this is only testing conda_package_handling's code, and does not test
         # that conda_package_streaming works without zstandard.
 
-        import conda_package_handling.api
+        with warnings.catch_warnings(record=True) as w:
+            warnings.simplefilter("always")  # Ensure warnings are sent
+            import conda_package_handling.api
 
-        importlib.reload(conda_package_handling.api)
+            importlib.reload(conda_package_handling.api)
 
-        assert conda_package_handling.api.libarchive_enabled is False
+            assert len(w) == 1
+            assert issubclass(w[-1].category, UserWarning)
+            assert "zstandard" in str(w[-1].message)
+            assert conda_package_handling.api.libarchive_enabled is False
 
     finally:
         sys.modules.pop("zstandard", None)
         sys.modules.pop("conda_package_handling.conda_fmt", None)
         sys.modules.pop("conda_package_streaming.transmute", None)
-        import conda_package_handling.api
+        with warnings.catch_warnings(record=True) as w:
+            warnings.simplefilter("always")  # Ensure warnings are sent
+            import conda_package_handling.api
 
-        importlib.reload(conda_package_handling.api)
-
-        assert conda_package_handling.api.libarchive_enabled is True
+            importlib.reload(conda_package_handling.api)
+            assert len(w) == 0
+            assert conda_package_handling.api.libarchive_enabled is True
 
 
 def test_degraded_subprocess():