Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
STABLE_PYTHON_VERSION: '313'
STABLE_PYTHON_VERSION: '310'
HATCH_VERBOSE: '1'
FORCE_COLOR: '1'
CIBW_BUILD_FRONTEND: build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-ffi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
STABLE_PYTHON_VERSION: '39'
STABLE_PYTHON_VERSION: '310'
HATCH_VERBOSE: '1'
FORCE_COLOR: '1'
CIBW_BUILD_FRONTEND: build
Expand Down
22 changes: 6 additions & 16 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,11 @@ jobs:
- ubuntu-latest
- windows-latest
python-version:
- '3.9'
- '3.10'
- '3.11'
- '3.12'
- '3.13'
# Python 3.9 aren't supported on macos-latest (ARM)
exclude:
- os: macos-latest
python-version: '3.9'
include:
- os: macos-13
python-version: '3.9'
- '3.14'

steps:
- name: Checkout code
Expand Down Expand Up @@ -106,6 +99,8 @@ jobs:
run: hatch run test.py${{ matrix.python-version }}:test --junit-xml=junit.xml

- name: Run tests (v2)
# Temporary workaround until Pydantic 3.12 is released with Python 3.14 support
if: matrix.python-version != '3.14'
run: hatch run v2-test.py${{ matrix.python-version }}:test --junit-xml=v2-junit.xml

- name: Run tests (CLI)
Expand Down Expand Up @@ -144,18 +139,13 @@ jobs:
- ubuntu-latest
- windows-latest
python-version:
- '3.9'
- '3.10'
- '3.11'
- '3.12'
- '3.13'
# Python 3.9 aren't supported on macos-latest (ARM)
exclude:
- os: macos-latest
python-version: '3.9'
include:
- os: macos-13
python-version: '3.9'
# Temporarily excluded until Pydantic 3.12 is released with Python
# 3.14 support
# - '3.14'

steps:
- name: Checkout code
Expand Down
2 changes: 2 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
only be defined in this file.
"""

from __future__ import annotations

import pytest


Expand Down
4 changes: 3 additions & 1 deletion docs/scripts/other.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
continue silently.
"""

from __future__ import annotations

import subprocess
from pathlib import Path
from typing import TYPE_CHECKING
Expand Down Expand Up @@ -77,7 +79,7 @@ def is_binary(buffer: bytes) -> bool:
if str(dest_path) in EDITOR.files:
continue

fi: "io.IOBase"
fi: io.IOBase
with Path(source_path).open("rb") as fi:
buf = fi.read(2048)

Expand Down
2 changes: 1 addition & 1 deletion examples/http/aiohttp_and_flask/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Use the above links to view additional documentation within.

## Prerequisites

- Python 3.9 or higher
- Python 3.10 or higher
- A dependency manager ([uv](https://docs.astral.sh/uv/) recommended, [pip](https://pip.pypa.io/en/stable/) also works)

## Running the Example
Expand Down
2 changes: 1 addition & 1 deletion examples/http/aiohttp_and_flask/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name = "example-aiohttp-and-flask"
description = "Example of using an aiohttp client and Flask server with Pact Python"

dependencies = ["aiohttp~=3.0", "flask~=3.0", "typing-extensions~=4.0"]
requires-python = ">=3.9"
requires-python = ">=3.10"
version = "1.0.0"

[dependency-groups]
Expand Down
3 changes: 1 addition & 2 deletions examples/http/aiohttp_and_flask/test_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@

if TYPE_CHECKING:
from pathlib import Path

from typing_extensions import TypeAlias
from typing import TypeAlias

ACTION_TYPE: TypeAlias = Literal["setup", "teardown"]

Expand Down
2 changes: 1 addition & 1 deletion examples/http/requests_and_fastapi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ This example is intended for software engineers and engineering managers who wan

## Prerequisites

- Python 3.9 or higher
- Python 3.10 or higher
- A dependency manager ([uv](https://docs.astral.sh/uv/) recommended, [pip](https://pip.pypa.io/en/stable/) also works)

## Running the Example
Expand Down
6 changes: 3 additions & 3 deletions examples/http/requests_and_fastapi/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

import logging
from datetime import datetime, timezone
from typing import Any, ClassVar, Optional
from typing import Any, ClassVar

from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, Field, field_validator
Expand All @@ -53,8 +53,8 @@ class User(BaseModel):
id: int
name: str
created_on: datetime = Field(default_factory=lambda: datetime.now(tz=timezone.utc))
email: Optional[str] = None
ip_address: Optional[str] = None
email: str | None = None
ip_address: str | None = None
hobbies: list[str] = Field(default_factory=list)
admin: bool = False

Expand Down
2 changes: 1 addition & 1 deletion examples/http/requests_and_fastapi/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name = "example-requests-and-fastapi"
description = "Example of using a requests client and FastAPI server with Pact Python"

dependencies = ["requests~=2.0", "fastapi~=0.0", "typing-extensions~=4.0"]
requires-python = ">=3.9"
requires-python = ">=3.10"
version = "1.0.0"

[dependency-groups]
Expand Down
3 changes: 1 addition & 2 deletions examples/http/requests_and_fastapi/test_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@

if TYPE_CHECKING:
from pathlib import Path

from typing_extensions import TypeAlias
from typing import TypeAlias

ACTION_TYPE: TypeAlias = Literal["setup", "teardown"]

Expand Down
2 changes: 2 additions & 0 deletions examples/plugins/proto/person_pb2.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
This file is generated code. Manual changes (except for documentation improvements) will be overwritten if the file is regenerated.
"""

from __future__ import annotations

from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import runtime_version as _runtime_version
Expand Down
2 changes: 2 additions & 0 deletions examples/plugins/proto/person_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
This file is generated and should not be modified manually, except for documentation improvements.
"""

from __future__ import annotations

from typing import Any
import grpc

Expand Down
2 changes: 2 additions & 0 deletions examples/plugins/protobuf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
have a basic understanding of Pact and Protocol Buffers.
"""

from __future__ import annotations

from examples.plugins.proto.person_pb2 import AddressBook, Person


Expand Down
6 changes: 3 additions & 3 deletions pact-python-cli/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python",
"Topic :: Software Development :: Testing",
]

requires-python = ">=3.9"
requires-python = ">=3.10"

[project.urls]
"Bug Tracker" = "https://github.com/pact-foundation/pact-python/issues"
Expand Down Expand Up @@ -128,7 +128,7 @@ requires = ["hatch-vcs", "hatchling", "packaging"]
pre-install-commands = ["uv pip install --group test -e ."]

[[tool.hatch.envs.test.matrix]]
python = ["3.10", "3.11", "3.12", "3.13", "3.9"]
python = ["3.10", "3.11", "3.12", "3.13", "3.14"]

################################################################################
## PyTest Configuration
Expand Down
6 changes: 3 additions & 3 deletions pact-python-ffi/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python",
"Topic :: Software Development :: Testing",
]

requires-python = ">=3.9"
requires-python = ">=3.10"

dependencies = ["cffi~=2.0"]

Expand Down Expand Up @@ -125,7 +125,7 @@ requires = ["hatch-vcs", "hatchling", "packaging", "cffi"]
# platform.windows.env-vars = { PATH = "{root}/src/pact_ffi;{env:PATH}" }

[[tool.hatch.envs.test.matrix]]
python = ["3.10", "3.11", "3.12", "3.13", "3.9"]
python = ["3.10", "3.11", "3.12", "3.13", "3.14"]

################################################################################
## PyTest Configuration
Expand Down
2 changes: 2 additions & 0 deletions pact-python-ffi/tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
are functioning as expected.
"""

from __future__ import annotations

import re

import pytest
Expand Down
15 changes: 8 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python",
"Topic :: Software Development :: Testing",
]

requires-python = ">=3.9"
requires-python = ">=3.10"

# Dependencies of Pact Python should be specified using the broadest range
# compatible version unless:
Expand All @@ -45,7 +45,6 @@ dependencies = [
# External dependencies
"cffi~=2.0",
"yarl~=1.0",
"typing-extensions~=4.0 ; python_version < '3.10'",
]

[project.urls]
Expand Down Expand Up @@ -123,6 +122,8 @@ types = [
"types-grpcio~=1.0",
"types-protobuf~=6.0",
"types-requests~=2.0",
# This is required for Python 3.10 support
"typing-extensions~=4.0",
]

# Dependencies for v2 example and test environments
Expand Down Expand Up @@ -224,7 +225,7 @@ requires = ["hatch-vcs", "hatchling"]
pre-install-commands = ["uv pip install --group test -e ."]

[[tool.hatch.envs.test.matrix]]
python = ["3.10", "3.11", "3.12", "3.13", "3.9"]
python = ["3.10", "3.11", "3.12", "3.13", "3.14"]

# Test environment for running unit tests. This automatically tests against all
# supported Python versions.
Expand All @@ -237,7 +238,7 @@ requires = ["hatch-vcs", "hatchling"]
all = ["example"]

[[tool.hatch.envs.example.matrix]]
python = ["3.10", "3.11", "3.12", "3.13", "3.9"]
python = ["3.10", "3.11", "3.12", "3.13", "3.14"]

[tool.hatch.envs.v2-test]
features = ["v2"]
Expand All @@ -250,7 +251,7 @@ requires = ["hatch-vcs", "hatchling"]
test = "pytest tests/v2 {args}"

[[tool.hatch.envs.v2-test.matrix]]
python = ["3.10", "3.11", "3.12", "3.13", "3.9"]
python = ["3.10", "3.11", "3.12", "3.13", "3.14"]

[tool.hatch.envs.v2-example]
features = ["v2"]
Expand All @@ -263,7 +264,7 @@ requires = ["hatch-vcs", "hatchling"]
example = "pytest examples/v2 {args}"

[[tool.hatch.envs.v2-example.matrix]]
python = ["3.10", "3.11", "3.12", "3.13", "3.9"]
python = ["3.10", "3.11", "3.12", "3.13", "3.14"]

################################################################################
## UV Workspace
Expand Down
2 changes: 2 additions & 0 deletions src/pact/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@
[examples](https://pact-foundation.github.io/pact-python/examples).
"""

from __future__ import annotations

from pact.__version__ import __version__, __version_tuple__
from pact.pact import Pact
from pact.verifier import Verifier
Expand Down
2 changes: 1 addition & 1 deletion src/pact/__version__.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing_extensions import TypeAlias
from typing import TypeAlias

__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]

Expand Down
4 changes: 2 additions & 2 deletions src/pact/_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@
from typing import TYPE_CHECKING, Any, Generic, TypeVar
from urllib.parse import urlparse

from typing_extensions import Self

from pact import __version__
from pact._util import find_free_port
from pact.types import Message

if TYPE_CHECKING:
from types import TracebackType

from typing_extensions import Self


logger = logging.getLogger(__name__)

Expand Down
8 changes: 6 additions & 2 deletions src/pact/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@
notice.
"""

from __future__ import annotations

import inspect
import logging
import socket
import warnings
from collections.abc import Callable, Mapping
from contextlib import closing
from functools import partial
from inspect import Parameter, _ParameterKind
from typing import TypeVar
from typing import TYPE_CHECKING, TypeVar

if TYPE_CHECKING:
from collections.abc import Callable, Mapping

logger = logging.getLogger(__name__)

Expand Down
2 changes: 2 additions & 0 deletions src/pact/interaction/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
in the interaction.
"""

from __future__ import annotations

from pact.interaction._async_message_interaction import AsyncMessageInteraction
from pact.interaction._base import Interaction
from pact.interaction._http_interaction import HttpInteraction
Expand Down
Loading