Repository: scikit-activeml/scikit-activeml (language: python)

Issue:
FR: Check Compatibility with Python 3.12
### Describe the workflow you want to enable

Other common libraries, e.g., scikit-learn, already support Python 3.12. Accordingly, we should check how we also can support this Python version.

### Describe your proposed solution

We need to run our tests with Python 3.12 and must scan our requirements for their supported Python versions.

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 7aed6021..3d4deb23 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -9,7 +9,7 @@ jobs:
     strategy:
       max-parallel: 4
       matrix:
-        python-version: [ '3.8', '3.9', '3.10', '3.11']
+        python-version: [ '3.9', '3.10', '3.11', '3.12' ]
 
     steps:
     - uses: actions/checkout@v4
diff --git a/README.rst b/README.rst
index 9fb05170..805fed20 100644
--- a/README.rst
+++ b/README.rst
@@ -8,7 +8,7 @@
 .. |Codecov| image:: https://codecov.io/gh/scikit-activeml/scikit-activeml/branch/master/graph/badge.svg
    :target: https://app.codecov.io/gh/scikit-activeml/scikit-activeml
 
-.. |PythonVersion| image:: https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-blue.svg
+.. |PythonVersion| image:: https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg
    :target: https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-blue
 
 .. |PyPi| image:: https://badge.fury.io/py/scikit-activeml.svg
diff --git a/requirements.txt b/requirements.txt
index e547a64f..ae64c955 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
-joblib>=1.2
-numpy>=1.24
-scipy>=1.9.2
-scikit-learn>=1.2
-matplotlib>=3.6.1
-iteration-utilities>=0.11
-makefun>=1.15.2
\ No newline at end of file
+joblib>=1.4.0
+numpy>=1.26
+scipy>=1.11.3
+scikit-learn>=1.3.2
+matplotlib>=3.7.3
+iteration-utilities>=0.12.0
+makefun>=1.15.3
\ No newline at end of file
diff --git a/requirements_max.txt b/requirements_max.txt
index 4865a56d..6ab58cf1 100644
--- a/requirements_max.txt
+++ b/requirements_max.txt
@@ -1,7 +1,7 @@
 joblib<=1.4.2
-numpy<=1.26.4
+numpy<=2.0.0
 scipy<=1.14.0
 scikit-learn<=1.5.1
-matplotlib<=3.7.2
+matplotlib<=3.9.1
 iteration-utilities<=0.12.1
-makefun<=1.15.2
\ No newline at end of file
+makefun<=1.15.4
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 9bc8ea03..b3113190 100644
--- a/setup.py
+++ b/setup.py
@@ -28,9 +28,10 @@ def requirements():
         "Intended Audience :: Developers",
         "License :: OSI Approved :: BSD License",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
+        "Programming Language :: Python :: 3.11",
+        "Programming Language :: Python :: 3.12",
         "Operating System :: OS Independent",
     ],
     keywords=[
@@ -43,7 +44,7 @@ def requirements():
     ],
     url="https://github.com/scikit-activeml/scikit-activeml",
     author="Marek Herde",
-    python_requires=">=3.8",
+    python_requires=">=3.9",
     author_email="marek.herde@uni-kassel.de",
     license="BSD 3-Clause License",
     packages=setuptools.find_packages(),


Test patch:
diff --git a/skactiveml/visualization/tests/test_feature_space.py b/skactiveml/visualization/tests/test_feature_space.py
index 2a69bf9c..d4820e32 100644
--- a/skactiveml/visualization/tests/test_feature_space.py
+++ b/skactiveml/visualization/tests/test_feature_space.py
@@ -763,7 +763,7 @@ def test_without_candidates(self):
         comparison = compare_images(
             self.path_prefix + "dec_bound_wo_cand_expected.pdf",
             self.path_prefix + "dec_bound_wo_cand.pdf",
-            tol=0,
+            tol=0.05,
         )
         self.assertIsNone(comparison)
 
@@ -792,7 +792,7 @@ def test_with_candidates(self):
         comparison = compare_images(
             self.path_prefix + "dec_bound_w_cand_expected.pdf",
             self.path_prefix + "dec_bound_w_cand.pdf",
-            tol=0,
+            tol=0.05,
         )
         self.assertIsNone(comparison)
 
@@ -833,7 +833,7 @@ def test_multi_class(self):
         comparison = compare_images(
             self.path_prefix + "dec_bound_multiclass.pdf",
             self.path_prefix + "dec_bound_multiclass_expected.pdf",
-            tol=0,
+            tol=1.0,
         )
         self.assertIsNone(comparison)
 
@@ -865,7 +865,7 @@ def test_svc(self):
         comparison = compare_images(
             self.path_prefix + "dec_bound_svc_expected.pdf",
             self.path_prefix + "dec_bound_svc.pdf",
-            tol=0,
+            tol=0.05,
         )
         self.assertIsNone(comparison)
 
@@ -885,7 +885,7 @@ def test_multi_with_axes(self):
         comparison = compare_images(
             self.path_prefix + "multi_with_axes_expected.pdf",
             self.path_prefix + "multi_with_axes.pdf",
-            tol=0,
+            tol=0.05,
         )
         self.assertIsNone(comparison)
 
@@ -903,7 +903,7 @@ def test_multi_without_axes(self):
         comparison = compare_images(
             self.path_prefix + "multi_without_axes_expected.pdf",
             self.path_prefix + "multi_without_axes.pdf",
-            tol=0,
+            tol=0.05,
         )
         self.assertIsNone(comparison)
 
@@ -922,7 +922,7 @@ def test_multi_without_axes_cand(self):
         comparison = compare_images(
             self.path_prefix + "multi_without_axes_cand_expected.pdf",
             self.path_prefix + "multi_without_axes_cand.pdf",
-            tol=0,
+            tol=0.05,
         )
         self.assertIsNone(comparison)
 
@@ -967,7 +967,7 @@ def test_stream(self):
         comparison = compare_images(
             self.path_prefix + "dec_bound_w_cand_stream_expected.pdf",
             self.path_prefix + "dec_bound_w_cand_stream.pdf",
-            tol=0,
+            tol=0.05,
         )
         self.assertIsNone(comparison)