From f3f9ba34af99f8c857f9c4f1fe95f8485a0e077f Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Sat, 5 Jul 2025 16:15:16 +0200 Subject: [PATCH 01/12] Revert "Ensure we don't use the wheel, which uses older versions of lxml2" This reverts commit 967754b6ec084d3ee5baa73ad256cf19f0f231de. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3490b822..014bfe10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -lxml >= 3.8.0, !=4.7.0 --no-binary=lxml +lxml >= 3.8.0, !=4.7.0 From 40b755f700b413684abca2d71d78a14c9740cfc7 Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Sat, 5 Jul 2025 16:16:24 +0200 Subject: [PATCH 02/12] Update library versions based on lxml 6.0.0 --- .github/workflows/wheels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index af3fb57d..4303504a 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -100,8 +100,8 @@ jobs: include: ${{ fromJson(needs.generate-wheels-matrix.outputs.include) }} env: - PYXMLSEC_LIBXML2_VERSION: 2.13.5 - PYXMLSEC_LIBXSLT_VERSION: 1.1.42 + PYXMLSEC_LIBXML2_VERSION: 2.14.4 + PYXMLSEC_LIBXSLT_VERSION: 1.1.43 steps: - name: Check out the repo From 6e691b36f95b9421ccacf64d6c5ec269bc0a9e43 Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Sat, 5 Jul 2025 16:31:28 +0200 Subject: [PATCH 03/12] Enable ripemd60 As suggested in https://github.com/xmlsec/python-xmlsec/issues/344#issuecomment-2894393505 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 92588ebc..c1cdce44 100644 --- a/setup.py +++ b/setup.py @@ -523,6 +523,7 @@ def prepare_static_build(self, build_platform): '--disable-shared', '--disable-gost', '--enable-md5', + '--enable-ripemd160', '--disable-crypto-dl', '--enable-static=yes', '--enable-shared=no', From d6ea8dec42a870a3971b15e83d65c5c08d5664ac Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Mon, 7 Jul 2025 00:46:52 +0200 Subject: [PATCH 04/12] Fix failing tests in sdist workflows --- .github/workflows/sdist.yml | 6 +++++- .github/workflows/wheels.yml | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sdist.yml b/.github/workflows/sdist.yml index e987cdce..04f22c14 100644 --- a/.github/workflows/sdist.yml +++ b/.github/workflows/sdist.yml @@ -2,7 +2,11 @@ name: sdist on: [push, pull_request] jobs: sdist: - runs-on: ubuntu-latest + # Avoid Ubuntu 24.04 in sdist workflows, because it contains libxmlsec1-dev + # v1.2.39, which has a bug that causes tests/test_pkcs11.py to fail. + # (It thinks the softhsm engine has a public key instead of a private key.) + # libxmlsec1 <=1.2.33 or >=1.2.42 works. TODO: Try 26.04 when available. + runs-on: ubuntu-22.04 strategy: matrix: python: ["3.9", "3.10", "3.11", "3.12", "3.13"] diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 4303504a..f9294fd3 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -19,7 +19,11 @@ permissions: {} jobs: sdist: - runs-on: ubuntu-latest + # Avoid Ubuntu 24.04 in sdist workflows, because it contains libxmlsec1-dev + # v1.2.39, which has a bug that causes tests/test_pkcs11.py to fail. + # (It thinks the softhsm engine has a public key instead of a private key.) + # libxmlsec1 <=1.2.33 or >=1.2.42 works. TODO: Try 26.04 when available. + runs-on: ubuntu-22.04 permissions: contents: write From bcd364cdb8e99f49172eaae67b2572ffaa7b4e61 Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Mon, 7 Jul 2025 01:09:15 +0200 Subject: [PATCH 05/12] Show stdout in setup.py, not only stderr --- setup.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/setup.py b/setup.py index c1cdce44..d5cf53aa 100644 --- a/setup.py +++ b/setup.py @@ -435,17 +435,17 @@ def prepare_static_build(self, build_platform): openssl_config_cmd.append(cross_compiling.triplet) else: openssl_config_cmd.insert(0, './config') - subprocess.check_output(openssl_config_cmd, cwd=str(openssl_dir), env=env) - subprocess.check_output(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(openssl_dir), env=env) - subprocess.check_output( + subprocess.check_call(openssl_config_cmd, cwd=str(openssl_dir), env=env) + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(openssl_dir), env=env) + subprocess.check_call( ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install_sw'], cwd=str(openssl_dir), env=env ) self.info('Building zlib') zlib_dir = next(self.build_libs_dir.glob('zlib-*')) - subprocess.check_output(['./configure', prefix_arg], cwd=str(zlib_dir), env=env) - subprocess.check_output(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(zlib_dir), env=env) - subprocess.check_output(['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(zlib_dir), env=env) + subprocess.check_call(['./configure', prefix_arg], cwd=str(zlib_dir), env=env) + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(zlib_dir), env=env) + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(zlib_dir), env=env) host_arg = "" if cross_compiling: @@ -453,7 +453,7 @@ def prepare_static_build(self, build_platform): self.info('Building libiconv') libiconv_dir = next(self.build_libs_dir.glob('libiconv-*')) - subprocess.check_output( + subprocess.check_call( [ './configure', prefix_arg, @@ -464,14 +464,14 @@ def prepare_static_build(self, build_platform): cwd=str(libiconv_dir), env=env, ) - subprocess.check_output(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libiconv_dir), env=env) - subprocess.check_output( + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libiconv_dir), env=env) + subprocess.check_call( ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libiconv_dir), env=env ) self.info('Building LibXML2') libxml2_dir = next(self.build_libs_dir.glob('libxml2-*')) - subprocess.check_output( + subprocess.check_call( [ './configure', prefix_arg, @@ -486,14 +486,14 @@ def prepare_static_build(self, build_platform): cwd=str(libxml2_dir), env=env, ) - subprocess.check_output(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libxml2_dir), env=env) - subprocess.check_output( + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libxml2_dir), env=env) + subprocess.check_call( ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libxml2_dir), env=env ) self.info('Building libxslt') libxslt_dir = next(self.build_libs_dir.glob('libxslt-*')) - subprocess.check_output( + subprocess.check_call( [ './configure', prefix_arg, @@ -507,8 +507,8 @@ def prepare_static_build(self, build_platform): cwd=str(libxslt_dir), env=env, ) - subprocess.check_output(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libxslt_dir), env=env) - subprocess.check_output( + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libxslt_dir), env=env) + subprocess.check_call( ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libxslt_dir), env=env ) @@ -516,7 +516,7 @@ def prepare_static_build(self, build_platform): ldflags.append('-lpthread') env['LDFLAGS'] = ' '.join(ldflags) xmlsec1_dir = next(self.build_libs_dir.glob('xmlsec1-*')) - subprocess.check_output( + subprocess.check_call( [ './configure', prefix_arg, @@ -537,13 +537,13 @@ def prepare_static_build(self, build_platform): cwd=str(xmlsec1_dir), env=env, ) - subprocess.check_output( + subprocess.check_call( ['make', '-j{}'.format(multiprocessing.cpu_count() + 1)] + ['-I{}'.format(str(self.prefix_dir / 'include')), '-I{}'.format(str(self.prefix_dir / 'include' / 'libxml'))], cwd=str(xmlsec1_dir), env=env, ) - subprocess.check_output( + subprocess.check_call( ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(xmlsec1_dir), env=env ) From c63a4869f9facc60e810a01c3e1cd32d5d14a810 Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Mon, 7 Jul 2025 01:10:56 +0200 Subject: [PATCH 06/12] Download xmlsec1 releases from GitHub The server at www.aleksey.com (Cloudflare?) returns 403 Forbidden errors for some combination of: - missing User-Agent header - GitHub Actions CI runner IP address range - TLS settings (version, cipher suite) used by Python <= 3.9 --- setup.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index d5cf53aa..8383db4d 100644 --- a/setup.py +++ b/setup.py @@ -70,22 +70,18 @@ def latest_release_from_gnome_org_cache(url, lib_name): return '{}/{}'.format(url, latest_source) -def latest_release_from_github_api(repo): - api_url = 'https://api.github.com/repos/{}/releases'.format(repo) +def latest_release_json_from_github_api(repo): + api_url = 'https://api.github.com/repos/{}/releases/latest'.format(repo) # if we are running in CI, pass along the GH_TOKEN, so we don't get rate limited token = os.environ.get("GH_TOKEN") if token: log.info("Using GitHub token to avoid rate limiting") - api_releases = make_request(api_url, token, json_response=True) - releases = [r['tarball_url'] for r in api_releases if r['prerelease'] is False and r['draft'] is False] - if not releases: - raise DistutilsError('No release found for {}'.format(repo)) - return releases[0] + return make_request(api_url, token, json_response=True) def latest_openssl_release(): - return latest_release_from_github_api('openssl/openssl') + return latest_release_json_from_github_api('openssl/openssl')['tarball_url'] def latest_zlib_release(): @@ -105,7 +101,9 @@ def latest_libxslt_release(): def latest_xmlsec_release(): - return latest_release_from_html('https://www.aleksey.com/xmlsec/download/', re.compile('xmlsec1-(?P.*).tar.gz')) + assets = latest_release_json_from_github_api('lsh123/xmlsec')['assets'] + (tar_gz,) = [asset for asset in assets if asset['name'].endswith('.tar.gz')] + return tar_gz['browser_download_url'] class CrossCompileInfo: @@ -381,7 +379,7 @@ def prepare_static_build(self, build_platform): url = latest_xmlsec_release() self.info('{:10}: {}'.format('xmlsec1', 'PYXMLSEC_XMLSEC1_VERSION unset, downloading latest from {}'.format(url))) else: - url = 'https://www.aleksey.com/xmlsec/download/xmlsec1-{}.tar.gz'.format(self.xmlsec1_version) + url = 'https://github.com/lsh123/xmlsec/releases/download/{v}/xmlsec1-{v}.tar.gz'.format(v=self.xmlsec1_version) self.info( '{:10}: {}'.format( 'xmlsec1', 'PYXMLSEC_XMLSEC1_VERSION={}, downloading from {}'.format(self.xmlsec1_version, url) From 7f1e1d9a48bcf2475f34ad67d25c5a7c0a0b7700 Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Mon, 7 Jul 2025 01:14:49 +0200 Subject: [PATCH 07/12] Fix empty argument to ./configure This solves the warning: configure: WARNING: you should use --build, --host, --target --- setup.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 8383db4d..c70381d9 100644 --- a/setup.py +++ b/setup.py @@ -445,9 +445,9 @@ def prepare_static_build(self, build_platform): subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(zlib_dir), env=env) subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(zlib_dir), env=env) - host_arg = "" + host_arg = [] if cross_compiling: - host_arg = '--host={}'.format(cross_compiling.arch) + host_arg = ['--host={}'.format(cross_compiling.arch)] self.info('Building libiconv') libiconv_dir = next(self.build_libs_dir.glob('libiconv-*')) @@ -457,7 +457,7 @@ def prepare_static_build(self, build_platform): prefix_arg, '--disable-dependency-tracking', '--disable-shared', - host_arg, + *host_arg, ], cwd=str(libiconv_dir), env=env, @@ -479,7 +479,7 @@ def prepare_static_build(self, build_platform): '--without-python', '--with-iconv={}'.format(self.prefix_dir), '--with-zlib={}'.format(self.prefix_dir), - host_arg, + *host_arg, ], cwd=str(libxml2_dir), env=env, @@ -500,7 +500,7 @@ def prepare_static_build(self, build_platform): '--without-python', '--without-crypto', '--with-libxml-prefix={}'.format(self.prefix_dir), - host_arg, + *host_arg, ], cwd=str(libxslt_dir), env=env, @@ -530,7 +530,7 @@ def prepare_static_build(self, build_platform): '--with-openssl={}'.format(self.prefix_dir), '--with-libxml={}'.format(self.prefix_dir), '--with-libxslt={}'.format(self.prefix_dir), - host_arg, + *host_arg, ], cwd=str(xmlsec1_dir), env=env, From 9c11b8fbf07131dd4709e0d09af89db64f53af9f Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Mon, 7 Jul 2025 01:16:04 +0200 Subject: [PATCH 08/12] Update wheel availability based on lxml 6.0.0 --- pyproject.toml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8c03f910..540f91c1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,12 +54,10 @@ skip = [ "*-musllinux_i686", # LXML doesn't publish wheels for these platforms, which makes it # difficult for us to build wheels, so we exclude them. - "cp36-manylinux_aarch64", - "cp37-manylinux_aarch64", - "cp36-musllinux_aarch64", - "cp37-musllinux_aarch64", - "cp36-macosx*", - "cp37-macosx*", + "cp36-*", + "cp37-*", + "cp38-manylinux_aarch64", + "cp38-musllinux_aarch64", "cp38-macosx*", ] test-command = "pytest -v --color=yes {package}/tests" From c3f3df2a301ef3e225448fd417aba9b463519cb4 Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Mon, 7 Jul 2025 01:16:36 +0200 Subject: [PATCH 09/12] Fix linuxbrew workflow --- .github/workflows/linuxbrew.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/linuxbrew.yml b/.github/workflows/linuxbrew.yml index d8996fd6..c3ede39b 100644 --- a/.github/workflows/linuxbrew.yml +++ b/.github/workflows/linuxbrew.yml @@ -6,6 +6,9 @@ jobs: strategy: matrix: python: ["3.9", "3.10", "3.11", "3.12", "3.13"] + env: + # For some unknown reason, linuxbrew tries to use "gcc-11" by default, which doesn't exist. + CC: gcc steps: - uses: actions/checkout@v3 - name: Install brew From 749da1146a87bb1d574af2df0ab012ac2bd50476 Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Mon, 7 Jul 2025 01:16:52 +0200 Subject: [PATCH 10/12] Fix macosx workflow --- .github/workflows/macosx.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/macosx.yml b/.github/workflows/macosx.yml index 1b82d22d..f639637e 100644 --- a/.github/workflows/macosx.yml +++ b/.github/workflows/macosx.yml @@ -26,6 +26,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | export PKG_CONFIG_PATH="$(brew --prefix)/opt/libxml2/lib/pkgconfig" + export PYXMLSEC_LIBXML2_VERSION="$(pkg-config --modversion libxml-2.0)" python -m build rm -rf build/ - name: Set environment variables From 4f213157de1fa123b77754f9723709a1ff460c6f Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Mon, 7 Jul 2025 01:17:13 +0200 Subject: [PATCH 11/12] Fix manylinux workflow --- .github/workflows/manylinux.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/manylinux.yml b/.github/workflows/manylinux.yml index a44776b3..db8ea913 100644 --- a/.github/workflows/manylinux.yml +++ b/.github/workflows/manylinux.yml @@ -5,11 +5,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-abi: [cp36-cp36m, cp37-cp37m, cp38-cp38, cp39-cp39, cp310-cp310, cp311-cp311] + python-abi: [cp38-cp38, cp39-cp39, cp310-cp310, cp311-cp311, cp312-cp312, cp313-cp313] image: - manylinux2014_x86_64 - manylinux_2_28_x86_64 - - musllinux_1_1_x86_64 + - musllinux_1_2_x86_64 container: quay.io/pypa/${{ matrix.image }} steps: - uses: actions/checkout@v1 From 8f047912b4a00f5d2f42dc55691d241fbfdd2d53 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 00:16:28 +0000 Subject: [PATCH 12/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- setup.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index c70381d9..8d3d4b94 100644 --- a/setup.py +++ b/setup.py @@ -463,9 +463,7 @@ def prepare_static_build(self, build_platform): env=env, ) subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libiconv_dir), env=env) - subprocess.check_call( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libiconv_dir), env=env - ) + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libiconv_dir), env=env) self.info('Building LibXML2') libxml2_dir = next(self.build_libs_dir.glob('libxml2-*')) @@ -485,9 +483,7 @@ def prepare_static_build(self, build_platform): env=env, ) subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libxml2_dir), env=env) - subprocess.check_call( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libxml2_dir), env=env - ) + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libxml2_dir), env=env) self.info('Building libxslt') libxslt_dir = next(self.build_libs_dir.glob('libxslt-*')) @@ -506,9 +502,7 @@ def prepare_static_build(self, build_platform): env=env, ) subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1)], cwd=str(libxslt_dir), env=env) - subprocess.check_call( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libxslt_dir), env=env - ) + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libxslt_dir), env=env) self.info('Building xmlsec1') ldflags.append('-lpthread') @@ -541,9 +535,7 @@ def prepare_static_build(self, build_platform): cwd=str(xmlsec1_dir), env=env, ) - subprocess.check_call( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(xmlsec1_dir), env=env - ) + subprocess.check_call(['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(xmlsec1_dir), env=env) ext = self.ext_map['xmlsec'] ext.define_macros = [