Repository: pact-foundation/pact-python (language: python)

Issue:
Python 3.12 Release
## Description

- [x] CI/CD scripts need to be updated to test against Python 3.12 without allowing for failures.
  - For now, there is no need to add Python 3.13 to the test matrix, as it is not expected to reach beta until May 2024. 
- [x] The hatch `test` environment matrix needs to be updated to include Python 3.12

## Motivation: 🍾 Python 3.12 was released on [2 October 2023](https://docs.python.org/3.12/whatsnew/3.12.html)

This is the first release to fully drop the long-deprecated `distutils` package (see [PEP 632](https://peps.python.org/pep-0632/)). This means that people who are using Pact Python versions prior to `2.1.0` will _not_ be able to install the package from source, as the build script depends on `distutils`.

Users who have pinned an older version of Pact Python and migrate to Python 3.12 will likely face some issues, but a simple `pip install pact-python` (or `pip install --upgrade pact-python`) will fix this.

### Self-service

- [X] I'd be willing to contribute this feature to Pact Python myself.


Discussion / hints:
👋 Hi! The 'smartbear-supported' label has just been added to this issue, which will create an internal tracking ticket in PactFlow's Jira (PACT-1400). We will use this to prioritise and assign a team member to this task. All activity will be public on this ticket. For now, sit tight and we'll update this ticket once we have more information on the next steps. <br/><br/>See our <a href='https://docs.pact.io/help/smartbear'>documentation</a> for more information.

Fix patch:
diff --git a/.cirrus.yml b/.cirrus.yml
index f6ba0c61ef..cbd26fdc31 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -12,11 +12,13 @@ linux_arm64_task:
   env:
     PATH: ${HOME}/.local/bin:${PATH}
     CIRRUS_CLONE_SUBMODULES: "true"
+    HATCH_VERBOSE: 1
     matrix:
       - IMAGE: "python:3.8-slim"
       - IMAGE: "python:3.9-slim"
       - IMAGE: "python:3.10-slim"
       - IMAGE: "python:3.11-slim"
+      - IMAGE: "python:3.12-slim"
   arm_container:
     image: $IMAGE
   install_script:
@@ -37,6 +39,7 @@ macosx_arm64_task:
       - PYTHON: "3.9"
       - PYTHON: "3.10"
       - PYTHON: "3.11"
+      - PYTHON: "3.12"
   install_script:
     - brew update
     - brew install pyenv
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f2d5cd65d5..284125babf 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -15,7 +15,8 @@ concurrency:
   cancel-in-progress: true
 
 env:
-  STABLE_PYTHON_VERSION: "3.11"
+  STABLE_PYTHON_VERSION: "3.12"
+  HATCH_VERBOSE: 1
   CIBW_BUILD_FRONTEND: build
 
 jobs:
diff --git a/pyproject.toml b/pyproject.toml
index e026884fea..44bc2ed979 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -22,11 +22,12 @@ classifiers = [
   "Programming Language :: Python :: 3.9",
   "Programming Language :: Python :: 3.10",
   "Programming Language :: Python :: 3.11",
+  "Programming Language :: Python :: 3.12",
   "Programming Language :: Python :: 3 :: Only",
   "Topic :: Software Development :: Testing",
 ]
 
-requires-python = ">=3.8, <3.12"
+requires-python = ">=3.8"
 
 # Dependencies of Pact Python should be specified using the broadest range
 # compatible version unless:
@@ -87,7 +88,13 @@ dev = [
 ################################################################################
 
 [build-system]
-requires      = ["hatchling", "packaging", "requests", "cffi"]
+requires = [
+  "hatchling",
+  "packaging",
+  "requests",
+  "cffi",
+  "setuptools ; python_version >= '3.12'",
+]
 build-backend = "hatchling.build"
 
 [tool.hatch.version]
@@ -110,8 +117,14 @@ artifacts = ["pact/bin/*", "pact/lib/*", "pact/v3/_ffi.*"]
 # Install dev dependencies in the default environment to simplify the developer
 # workflow.
 [tool.hatch.envs.default]
-features           = ["dev"]
-extra-dependencies = ["hatchling", "packaging", "requests", "cffi"]
+features = ["dev"]
+extra-dependencies = [
+  "hatchling",
+  "packaging",
+  "requests",
+  "cffi",
+  "setuptools ; python_version >= '3.12'",
+]
 
 [tool.hatch.envs.default.scripts]
 lint    = ["black --check --diff {args:.}", "ruff {args:.}", "mypy {args:.}"]
@@ -125,7 +138,7 @@ all     = ["lint", "test", "example"]
 features = ["test"]
 
 [[tool.hatch.envs.test.matrix]]
-python = ["3.8", "3.9", "3.10", "3.11"]
+python = ["3.8", "3.9", "3.10", "3.11", "3.12"]
 
 [tool.hatch.envs.test.scripts]
 test    = "pytest {args:tests/}"


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e63ff5e85d..838cde4a74 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -13,8 +13,9 @@ concurrency:
   cancel-in-progress: true
 
 env:
-  STABLE_PYTHON_VERSION: "3.11"
+  STABLE_PYTHON_VERSION: "3.12"
   PYTEST_ADDOPTS: --color=yes
+  HATCH_VERBOSE: 1
 
 jobs:
   test:
@@ -28,12 +29,12 @@ jobs:
       fail-fast: false
       matrix:
         os: [ubuntu-latest, windows-latest, macos-latest]
-        python-version: ["3.8", "3.9", "3.10", "3.11"]
+        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
         experimental: [false]
         include:
           - # Run tests against the next Python version, but no need for the full list of OSes.
             os: ubuntu-latest
-            python-version: "3.12-dev"
+            python-version: "3.13.0-alpha.0 - 3.13"
             experimental: true
 
     steps:
@@ -59,6 +60,16 @@ jobs:
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
 
+  test-conlusion:
+    name: Test matrix complete
+
+    runs-on: ubuntu-latest
+    needs:
+      - test
+
+    steps:
+      - run: echo "Test matrix completed successfully."
+
   example:
     name: Example