Repository: canonical-ols/talisker (language: python)

Issue:
Adding support for Python 3.12
The latest LTS version of Ubuntu Noble 24.04 is shipped with Python3 version 3.12.
This package doesn't support 3.12 as importing modules like `talisker.flask` throws a not found module error.

Are there any plans to support this Python3 version?


Discussion / hints:
@goulinkh we are the maintainers of that package, i.e. the store and the launchpad team together.
I see! I will take a look into this then, thanks for the info.

Fix patch:
diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml
index 30f9f349..0b34aac1 100644
--- a/.github/workflows/tox.yml
+++ b/.github/workflows/tox.yml
@@ -1,14 +1,14 @@
 name: Run tox
 
 on:
-    push:
-        branches:
-            - main
-            - master
-    pull_request:
-        branches:
-            - main
-            - master
+  push:
+    branches:
+      - main
+      - master
+  pull_request:
+    branches:
+      - main
+      - master
 
 jobs:
   build:
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-20.04
     strategy:
       matrix:
-        python: [3.5, 3.6, 3.8, "3.10"]
+        python: [3.5, 3.6, 3.8, "3.10", "3.12"]
 
     steps:
       - uses: actions/checkout@v2
diff --git a/Makefile b/Makefile
index c86682d8..bf57816f 100644
--- a/Makefile
+++ b/Makefile
@@ -113,8 +113,8 @@ travis: $(VENV_PATH)
 	$(MAKE) $(LIMBO_REQUIREMENTS)
 	env/bin/tox
 
-github-tox:
-	pip install tox setuptools $(subst requirements,-c requirements,$(REQUIREMENTS))
+github-tox: $(VENV)
+	. $(BIN)/activate && pip install tox setuptools $(subst requirements,-c requirements,$(REQUIREMENTS))
 	$(MAKE) $(LIMBO_REQUIREMENTS)
 	tox
 
diff --git a/requirements.docs.txt b/requirements.docs.txt
index 7628b13e..18dfd3f3 100644
--- a/requirements.docs.txt
+++ b/requirements.docs.txt
@@ -1,1 +1,2 @@
-Sphinx==7.0.1
+Sphinx==5.3.0;python_version=="3.6"
+Sphinx==7.0.1;python_version>"3.6"
diff --git a/setup.cfg b/setup.cfg
index 5e74955c..c17c1c70 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -33,6 +33,7 @@ classifiers =
 	Programming Language :: Python :: 3.6
 	Programming Language :: Python :: 3.8
 	Programming Language :: Python :: 3.10
+	Programming Language :: Python :: 3.12
 	Programming Language :: Python :: Implementation :: CPython
 
 [options]
@@ -43,9 +44,11 @@ test_suite = tests
 package_dir = talisker=talisker
 install_requires =
 	Werkzeug~=1.0;python_version~="3.5.0"
-	Werkzeug<3;python_version>="3.6"
+	Werkzeug<3;python_version>="3.6" and python_version<"3.12"
+	Werkzeug>=3,<4;python_version>="3.12"
 	statsd~=3.3;python_version~="3.5.0"
-	statsd<4;python_version>="3.6"
+	statsd<4;python_version>="3.6" and python_version<"3.12"
+	statsd>=4,<5;python_version>="3.12"
 	requests~=2.25;python_version~="3.5.0"
 	requests<3.0;python_version>"3.5"
 	contextvars~=2.4;python_version>="3.5" and python_version<"3.7"
@@ -54,10 +57,12 @@ install_requires =
 gunicorn =
 	gunicorn>=19.7.0;python_version>"3.6"
 	gunicorn==19.7.0,<21.0;python_version>="3.5" and python_version<"3.8"
+	gunicorn<24.0;python_version>="3.8"
 raven = raven>=6.4.0
 celery =
 	celery~=4.4;python_version~="3.5.0"
-	celery>=4,<5.3;python_version>"3.5"
+	celery>=4,<5.3;python_version>"3.5" and python_version<"3.12"
+	celery>=5,<6;python_version>="3.12"
 django =
 	django~=2.2;python_version~="3.5.0"
 	django<4;python_version>"3.5"
@@ -66,7 +71,8 @@ prometheus =
 	prometheus-client<0.8;python_version>"3.5"
 flask =
 	flask~=1.1;python_version~="3.5.0"
-	flask<3;python_version>"3.5"
+	flask<3;python_version>"3.5" and python_version<"3.12"
+	flask>3,<4;python_version>="3.12"
 	blinker~=1.5;python_version~="3.5.0"
 	blinker<2;python_version>"3.5"
 dev =
diff --git a/setup.py b/setup.py
index 5668f57a..97e114f9 100644
--- a/setup.py
+++ b/setup.py
@@ -118,6 +118,7 @@
         'Programming Language :: Python :: 3.6',
         'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.10',
+        'Programming Language :: Python :: 3.12',
         'Programming Language :: Python :: Implementation :: CPython',
     ],
     description='A common WSGI stack',
@@ -138,7 +139,8 @@
         ],
         celery=[
             'celery~=4.4;python_version~="3.5.0"',
-            'celery>=4,<5.3;python_version>"3.5"',
+            'celery>=4,<5.3;python_version>"3.5" and python_version<"3.12"',
+            'celery>=5,<6;python_version>="3.12"',
         ],
         dev=[
             'logging_tree>=1.9',
@@ -152,7 +154,8 @@
         ],
         flask=[
             'flask~=1.1;python_version~="3.5.0"',
-            'flask<3;python_version>"3.5"',
+            'flask<3;python_version>"3.5" and python_version<"3.12"',
+            'flask>3,<4;python_version>="3.12"',
             'blinker~=1.5;python_version~="3.5.0"',
             'blinker<2;python_version>"3.5"',
         ],
@@ -162,6 +165,7 @@
         gunicorn=[
             'gunicorn>=19.7.0;python_version>"3.6"',
             'gunicorn>=19.7.0,<21.0;python_version>="3.5" and python_version<"3.8"',
+            'gunicorn<24.0;python_version>="3.8"',
         ],
         pg=[
             'sqlparse>=0.4.2',
@@ -178,9 +182,11 @@
     include_package_data=True,
     install_requires=[
         'Werkzeug~=1.0;python_version~="3.5.0"',
-        'Werkzeug<3;python_version>="3.6"',
+        'Werkzeug<3;python_version>="3.6" and python_version<"3.12"',
+	      'Werkzeug>=3,<4;python_version>="3.12"',
         'statsd~=3.3;python_version~="3.5.0"',
-        'statsd<4;python_version>="3.6"',
+	      'statsd<4;python_version>="3.6" and python_version<"3.12"',
+	      'statsd>=4,<5;python_version>="3.12"',
         'requests~=2.25;python_version~="3.5.0"',
         'requests<3.0;python_version>"3.5"',
         'contextvars~=2.4;python_version>="3.5" and python_version<"3.7"',
diff --git a/tox.ini b/tox.ini
index 3ce5f264..bc14ad1c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py35, py36, py38, py310, docs, lint, minimal_dep_version, no-extras
+envlist = py35, py36, py38, py310, py312, docs, lint, minimal_dep_version, no-extras
 skip_missing_interpreters = True
 skipsdist = True
 
@@ -9,6 +9,7 @@ python =
     3.6: py36
     3.8: py38,lint,docs, no-extras
     3.10: py310
+    3.12: py312
 
 [testenv]
 usedevelop = True


Test patch:
diff --git a/tests/test_config.py b/tests/test_config.py
index b5e64573..641faf55 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -22,16 +22,28 @@
 # under the License.
 #
 
+import os
 import sys
+import textwrap
 from ipaddress import ip_network
 from subprocess import check_output as run
-import textwrap
 
 import pytest
 
 from talisker import config
 
 
+# tmpdir.chdir changed behavior in Python 3.12
+# which causes other tests to fail with a module not
+# found error, this makes sure that the original
+# directory is restored after the tests in this file are run.
+@pytest.fixture(scope="module", autouse=True)
+def restore_original_directory():
+    original_dir = os.getcwd()
+    yield
+    os.chdir(original_dir)
+
+
 @pytest.fixture
 def raw():
     return config.Config.DEFAULTS.copy()