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
20 changes: 20 additions & 0 deletions pact-python-ffi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@ Note that this _only_ includes changes to the Python FFI interface. For changes
<!-- markdownlint-disable emph-style -->
<!-- markdownlint-disable strong-style -->

## [pact-python-ffi/0.5.10.0] _2026-10-15_

### 🚀 Features

- [**breaking**] Remove pact.v2 compatibility module
> `pact.v2`, the `compat-v2` extra and the `pact-verifier` console script are removed. Migrate to the `pact` API (see MIGRATION.md) or pin `pact-python<4`.
- Update bindings to Pact FFI 0.5.10

### 📚 Documentation

- _(ffi)_ Remove duplicated docstring sections

### ⚙️ Miscellaneous Tasks

- Require python 3.11 or newer

### Contributors

- @JP-Ellis

## [pact-python-ffi/0.5.8.0] _2026-09-17_

### 🚀 Features
Expand Down
57 changes: 33 additions & 24 deletions pact-python-ffi/hatch_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,37 +386,46 @@ def _patch_header(self, source: str) -> str:
"""
Patch the upstream header so that CFFI can compile it.

The upstream `pact.h` emits the callback parameter of
`pactffi_register_plugin_log_callback` as an opaque struct passed by
value, which cannot be compiled. The Rust signature is
`Option<extern "C" fn(...)>`, whose ABI is a nullable function pointer.
See https://github.com/pact-foundation/pact-reference/issues/544.
The upstream `pact.h` emits the callback parameters of
`pactffi_register_plugin_log_callback` and
`pactffi_register_log_callback` as opaque structs passed by value, which
cannot be compiled. The Rust signatures are `Option<extern "C" fn(...)>`,
whose ABI is a nullable function pointer. See
https://github.com/pact-foundation/pact-reference/issues/544.

Args:
source:
The contents of the upstream `pact.h`.

Returns:
The header contents with the callback declared as a function
pointer.
The header contents with the callbacks declared as function
pointers.
"""
opaque = "typedef struct Option_PluginLogCallback Option_PluginLogCallback;"
if opaque not in source:
return source
self.app.display_debug("Patching Option_PluginLogCallback in pact.h")
return source.replace(
opaque,
"typedef void (*PluginLogCallback)("
"const char *plugin_instance_id, "
"const char *test_run_id, "
"const char *level, "
"const char *target, "
"const char *message);",
).replace(
"void pactffi_register_plugin_log_callback("
"struct Option_PluginLogCallback callback);",
"void pactffi_register_plugin_log_callback(PluginLogCallback callback);",
)
for callback, register, first_arg in (
(
"PluginLogCallback",
"pactffi_register_plugin_log_callback",
"plugin_instance_id",
),
("LogCallback", "pactffi_register_log_callback", "log_id"),
):
opaque = f"typedef struct Option_{callback} Option_{callback};"
if opaque not in source:
continue
self.app.display_debug(f"Patching Option_{callback} in pact.h")
source = source.replace(
opaque,
f"typedef void (*{callback})("
f"const char *{first_arg}, "
"const char *test_run_id, "
"const char *level, "
"const char *target, "
"const char *message);",
).replace(
f"void {register}(struct Option_{callback} callback);",
f"void {register}({callback} callback);",
)
return source

def _download(self, url: str) -> Path:
"""
Expand Down
2 changes: 1 addition & 1 deletion pact-python-ffi/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[project]
name = "pact-python-ffi"
version = "0.5.8.0"
version = "0.5.10.0"
description = "Python bindings for the Pact FFI library"
readme = "README.md"
license = "MIT"
Expand Down
Loading
Loading