pact-python-ffi 0.5.4.1__tar.gz → 0.5.8.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.8.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
@@ -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,42 @@ 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 parameter of
390
+ `pactffi_register_plugin_log_callback` as an opaque struct passed by
391
+ value, which cannot be compiled. The Rust signature is
392
+ `Option<extern "C" fn(...)>`, whose ABI is a nullable function pointer.
393
+ See https://github.com/pact-foundation/pact-reference/issues/544.
394
+
395
+ Args:
396
+ source:
397
+ The contents of the upstream `pact.h`.
398
+
399
+ Returns:
400
+ The header contents with the callback declared as a function
401
+ pointer.
402
+ """
403
+ opaque = "typedef struct Option_PluginLogCallback Option_PluginLogCallback;"
404
+ if opaque not in source:
405
+ return source
406
+ self.app.display_debug("Patching Option_PluginLogCallback in pact.h")
407
+ return source.replace(
408
+ opaque,
409
+ "typedef void (*PluginLogCallback)("
410
+ "const char *plugin_instance_id, "
411
+ "const char *test_run_id, "
412
+ "const char *level, "
413
+ "const char *target, "
414
+ "const char *message);",
415
+ ).replace(
416
+ "void pactffi_register_plugin_log_callback("
417
+ "struct Option_PluginLogCallback callback);",
418
+ "void pactffi_register_plugin_log_callback(PluginLogCallback callback);",
419
+ )
420
+
371
421
  def _download(self, url: str) -> Path:
372
422
  """
373
423
  Download the target URL.