187 lines
6.2 KiB
Diff
187 lines
6.2 KiB
Diff
From a2d19c0234866dc9d4d55abf3009699c258bb72f Mon Sep 17 00:00:00 2001
|
|
From: Matt Davis <6775756+nitzmahone@users.noreply.github.com>
|
|
Date: Mon, 10 Jun 2024 15:24:15 -0700
|
|
Subject: [PATCH] Conditional support for Cython3.x, CI updates (#808)
|
|
|
|
* Cython 3.x support needed for Python 3.13
|
|
* Move CI to a dynamic matrix
|
|
* Use GHA-hosted Apple Silicon runners
|
|
* Move Windows builds to cibuildwheel
|
|
* Implement rudimentary PEP517 config-settings passthru to setuptools with
|
|
custom in-tree setuptools build backend shim (blocked Windows build
|
|
being moved to cibuildwheel).
|
|
* Use build_config.toml to smuggle JSON to cibuildwheel, since it
|
|
trashes JSON via CLI when doing containerized builds.
|
|
---
|
|
.github/actions/dynamatrix/action.yml | 22 +
|
|
.../actions/dynamatrix/matrix_yaml_to_json.py | 71 +++
|
|
.github/workflows/ci.yaml | 596 +++++++++++-------
|
|
.github/workflows/manual_artifact_build.yaml | 446 -------------
|
|
MANIFEST.in | 1 +
|
|
packaging/_pyyaml_pep517.py | 51 ++
|
|
pyproject.toml | 10 +-
|
|
setup.py | 43 +-
|
|
tests/legacy_tests/conftest.py | 6 +-
|
|
tests/legacy_tests/test_appliance.py | 5 +-
|
|
10 files changed, 577 insertions(+), 674 deletions(-)
|
|
create mode 100644 .github/actions/dynamatrix/action.yml
|
|
create mode 100644 .github/actions/dynamatrix/matrix_yaml_to_json.py
|
|
delete mode 100644 .github/workflows/manual_artifact_build.yaml
|
|
create mode 100644 packaging/_pyyaml_pep517.py
|
|
|
|
diff --git a/packaging/_pyyaml_pep517.py b/packaging/_pyyaml_pep517.py
|
|
new file mode 100644
|
|
index 00000000..5f390266
|
|
--- /dev/null
|
|
+++ b/packaging/_pyyaml_pep517.py
|
|
@@ -0,0 +1,51 @@
|
|
+import inspect
|
|
+
|
|
+
|
|
+def _bridge_build_meta():
|
|
+ import functools
|
|
+ import sys
|
|
+
|
|
+ from setuptools import build_meta
|
|
+
|
|
+ self_module = sys.modules[__name__]
|
|
+
|
|
+ for attr_name in build_meta.__all__:
|
|
+ attr_value = getattr(build_meta, attr_name)
|
|
+ if callable(attr_value):
|
|
+ setattr(self_module, attr_name, functools.partial(_expose_config_settings, attr_value))
|
|
+
|
|
+
|
|
+class ActiveConfigSettings:
|
|
+ _current = {}
|
|
+
|
|
+ def __init__(self, config_settings):
|
|
+ self._config = config_settings
|
|
+
|
|
+ def __enter__(self):
|
|
+ type(self)._current = self._config
|
|
+
|
|
+ def __exit__(self, exc_type, exc_val, exc_tb):
|
|
+ type(self)._current = {}
|
|
+
|
|
+ @classmethod
|
|
+ def current(cls):
|
|
+ return cls._current
|
|
+
|
|
+
|
|
+def _expose_config_settings(real_method, *args, **kwargs):
|
|
+ from contextlib import nullcontext
|
|
+ import inspect
|
|
+
|
|
+ sig = inspect.signature(real_method)
|
|
+ boundargs = sig.bind(*args, **kwargs)
|
|
+
|
|
+ config = boundargs.arguments.get('config_settings')
|
|
+
|
|
+ ctx = ActiveConfigSettings(config) if config else nullcontext()
|
|
+
|
|
+ with ctx:
|
|
+ return real_method(*args, **kwargs)
|
|
+
|
|
+
|
|
+_bridge_build_meta()
|
|
+
|
|
diff --git a/pyproject.toml b/pyproject.toml
|
|
index 4bc04c0d..d8e5b969 100644
|
|
--- a/pyproject.toml
|
|
+++ b/pyproject.toml
|
|
@@ -1,3 +1,9 @@
|
|
[build-system]
|
|
-requires = ["setuptools", "wheel", "Cython<3.0"]
|
|
-build-backend = "setuptools.build_meta"
|
|
+requires = [
|
|
+ "setuptools", # FIXME: declare min/max setuptools versions?
|
|
+ "wheel",
|
|
+ "Cython; python_version < '3.13'",
|
|
+ "Cython>=3.0; python_version >= '3.13'"
|
|
+]
|
|
+backend-path = ["packaging"]
|
|
+build-backend = "_pyyaml_pep517"
|
|
diff --git a/setup.py b/setup.py
|
|
index c9b5dc6f..84bc2e46 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -34,6 +34,8 @@
|
|
"Programming Language :: Python :: 3.9",
|
|
"Programming Language :: Python :: 3.10",
|
|
"Programming Language :: Python :: 3.11",
|
|
+ "Programming Language :: Python :: 3.12",
|
|
+ "Programming Language :: Python :: 3.13",
|
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
@@ -82,7 +84,12 @@
|
|
with_cython = True
|
|
try:
|
|
from Cython.Distutils.extension import Extension as _Extension
|
|
- from Cython.Distutils import build_ext as _build_ext
|
|
+ try:
|
|
+ # try old_build_ext from Cython > 3 first, until we can dump it entirely
|
|
+ from Cython.Distutils.old_build_ext import old_build_ext as _build_ext
|
|
+ except ImportError:
|
|
+ # Cython < 3
|
|
+ from Cython.Distutils import build_ext as _build_ext
|
|
with_cython = True
|
|
except ImportError:
|
|
if with_cython:
|
|
@@ -94,6 +101,14 @@
|
|
bdist_wheel = None
|
|
|
|
|
|
+try:
|
|
+ from _pyyaml_pep517 import ActiveConfigSettings
|
|
+except ImportError:
|
|
+ class ActiveConfigSettings:
|
|
+ @staticmethod
|
|
+ def current():
|
|
+ return {}
|
|
+
|
|
# on Windows, disable wheel generation warning noise
|
|
windows_ignore_warnings = [
|
|
"Unknown distribution option: 'python_requires'",
|
|
@@ -173,6 +188,31 @@ def __init__(self, name, sources, feature_name, feature_description,
|
|
|
|
|
|
class build_ext(_build_ext):
|
|
+ def finalize_options(self):
|
|
+ super().finalize_options()
|
|
+ pep517_config = ActiveConfigSettings.current()
|
|
+
|
|
+ build_config = pep517_config.get('pyyaml_build_config')
|
|
+
|
|
+ if build_config:
|
|
+ import json
|
|
+ build_config = json.loads(build_config)
|
|
+ print(f"`pyyaml_build_config`: {build_config}")
|
|
+ else:
|
|
+ build_config = {}
|
|
+ print("No `pyyaml_build_config` setting found.")
|
|
+
|
|
+ for key, value in build_config.items():
|
|
+ existing_value = getattr(self, key, ...)
|
|
+ if existing_value is ...:
|
|
+ print(f"ignoring unknown config key {key!r}")
|
|
+ continue
|
|
+
|
|
+ if existing_value:
|
|
+ print(f"combining {key!r} {existing_value!r} and {value!r}")
|
|
+ value = existing_value + value # FIXME: handle type diff
|
|
+
|
|
+ setattr(self, key, value)
|
|
|
|
def run(self):
|
|
optional = True
|
|
@@ -230,6 +270,7 @@ def build_extensions(self):
|
|
if with_ext is not None and not with_ext:
|
|
continue
|
|
if with_cython:
|
|
+ print(f"BUILDING CYTHON EXT; {self.include_dirs=} {self.library_dirs=} {self.define=}")
|
|
ext.sources = self.cython_sources(ext.sources, ext)
|
|
try:
|
|
self.build_extension(ext)
|