pact-python-ffi 0.5.4.1__tar.gz → 0.5.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: pact-python-ffi
3
- Version: 0.5.4.1
3
+ Version: 0.5.10.0
4
4
  Summary: Python bindings for the Pact FFI library
5
5
  Project-URL: Bug Tracker, https://github.com/pact-foundation/pact-python/issues
6
6
  Project-URL: Changelog, https://github.com/pact-foundation/pact-python/blob/main/pact-python-ffi/CHANGELOG.md
@@ -21,13 +21,13 @@ Classifier: Operating System :: Microsoft :: Windows
21
21
  Classifier: Operating System :: POSIX :: Linux
22
22
  Classifier: Programming Language :: Python
23
23
  Classifier: Programming Language :: Python :: 3 :: Only
24
- Classifier: Programming Language :: Python :: 3.10
25
24
  Classifier: Programming Language :: Python :: 3.11
26
25
  Classifier: Programming Language :: Python :: 3.12
27
26
  Classifier: Programming Language :: Python :: 3.13
28
27
  Classifier: Programming Language :: Python :: 3.14
28
+ Classifier: Programming Language :: Python :: 3.15
29
29
  Classifier: Topic :: Software Development :: Testing
30
- Requires-Python: >=3.10
30
+ Requires-Python: >=3.11
31
31
  Requires-Dist: cffi~=2.0
32
32
  Description-Content-Type: text/markdown
33
33
 
@@ -135,8 +135,22 @@ class PactBuildHook(BuildHookInterface[Any]):
135
135
  Get the platform tag from the current system tags.
136
136
 
137
137
  This is used to determine the target platform for the Pact library.
138
+
139
+ On Linux, the generic `linux_{arch}` tag conveys no information about
140
+ the platform's C library, so the more specific `manylinux`/`musllinux`
141
+ tag is preferred when one is available.
142
+
143
+ Returns:
144
+ The most specific platform tag supported by the current system.
138
145
  """
139
- return next(t.platform for t in sys_tags())
146
+ platforms = (t.platform for t in sys_tags())
147
+ preferred = next(platforms)
148
+ if preferred.startswith("linux_"):
149
+ return next(
150
+ (p for p in platforms if not p.startswith("linux_")),
151
+ preferred,
152
+ )
153
+ return preferred
140
154
 
141
155
  def _install(self, version: str) -> Mapping[str, str]:
142
156
  """
@@ -320,12 +334,12 @@ class PactBuildHook(BuildHookInterface[Any]):
320
334
  else:
321
335
  extra_libs = []
322
336
 
337
+ source = self._patch_header(header.read_text())
338
+
323
339
  ffibuilder = cffi.FFI()
324
340
  ffibuilder.cdef(
325
341
  "\n".join(
326
- line
327
- for line in header.read_text().splitlines()
328
- if not line.strip().startswith("#")
342
+ line for line in source.splitlines() if not line.strip().startswith("#")
329
343
  )
330
344
  )
331
345
 
@@ -348,7 +362,7 @@ class PactBuildHook(BuildHookInterface[Any]):
348
362
 
349
363
  ffibuilder.set_source(
350
364
  "ffi",
351
- header.read_text(),
365
+ source,
352
366
  libraries=["pact_ffi", *extra_libs],
353
367
  library_dirs=[str(lib.parent)],
354
368
  extra_link_args=linker_args,
@@ -368,6 +382,51 @@ class PactBuildHook(BuildHookInterface[Any]):
368
382
  self.app.display_debug(f"Compiled CFFI bindings to {extension}")
369
383
  return extension
370
384
 
385
+ def _patch_header(self, source: str) -> str:
386
+ """
387
+ Patch the upstream header so that CFFI can compile it.
388
+
389
+ The upstream `pact.h` emits the callback parameters of
390
+ `pactffi_register_plugin_log_callback` and
391
+ `pactffi_register_log_callback` as opaque structs passed by value, which
392
+ cannot be compiled. The Rust signatures are `Option<extern "C" fn(...)>`,
393
+ whose ABI is a nullable function pointer. See
394
+ https://github.com/pact-foundation/pact-reference/issues/544.
395
+
396
+ Args:
397
+ source:
398
+ The contents of the upstream `pact.h`.
399
+
400
+ Returns:
401
+ The header contents with the callbacks declared as function
402
+ pointers.
403
+ """
404
+ for callback, register, first_arg in (
405
+ (
406
+ "PluginLogCallback",
407
+ "pactffi_register_plugin_log_callback",
408
+ "plugin_instance_id",
409
+ ),
410
+ ("LogCallback", "pactffi_register_log_callback", "log_id"),
411
+ ):
412
+ opaque = f"typedef struct Option_{callback} Option_{callback};"
413
+ if opaque not in source:
414
+ continue
415
+ self.app.display_debug(f"Patching Option_{callback} in pact.h")
416
+ source = source.replace(
417
+ opaque,
418
+ f"typedef void (*{callback})("
419
+ f"const char *{first_arg}, "
420
+ "const char *test_run_id, "
421
+ "const char *level, "
422
+ "const char *target, "
423
+ "const char *message);",
424
+ ).replace(
425
+ f"void {register}(struct Option_{callback} callback);",
426
+ f"void {register}({callback} callback);",
427
+ )
428
+ return source
429
+
371
430
  def _download(self, url: str) -> Path:
372
431
  """
373
432
  Download the target URL.