diff --git a/.github/workflows/linuxbrew.yml b/.github/workflows/linuxbrew.yml index d8996fd6..b97c726d 100644 --- a/.github/workflows/linuxbrew.yml +++ b/.github/workflows/linuxbrew.yml @@ -1,36 +1,36 @@ -name: linuxbrew -on: [push, pull_request] -jobs: - linuxbrew: - runs-on: ubuntu-latest - strategy: - matrix: - python: ["3.9", "3.10", "3.11", "3.12", "3.13"] - steps: - - uses: actions/checkout@v3 - - name: Install brew - run: | - sudo apt install -y build-essential procps curl file git - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - echo "/home/linuxbrew/.linuxbrew/bin" >> $GITHUB_PATH - - name: Install build dependencies - run: | - brew update - brew install python@${{ matrix.python }} gcc libxml2 libxmlsec1 pkg-config - echo "/home/linuxbrew/.linuxbrew/opt/python@${{ matrix.python }}/libexec/bin" >> $GITHUB_PATH - - name: Build wheel - run: | - python3 -m venv build_venv - source build_venv/bin/activate - pip3 install --upgrade setuptools wheel build - export CFLAGS="-I$(brew --prefix)/include" - export LDFLAGS="-L$(brew --prefix)/lib" - python3 -m build - rm -rf build/ - - name: Run tests - run: | - python3 -m venv test_venv - source test_venv/bin/activate - pip3 install --upgrade --no-binary=lxml -r requirements-test.txt - pip3 install xmlsec --only-binary=xmlsec --no-index --find-links=dist/ - pytest -v --color=yes +# name: linuxbrew +# on: [push, pull_request] +# jobs: +# linuxbrew: +# runs-on: ubuntu-latest +# strategy: +# matrix: +# python: ["3.9", "3.10", "3.11", "3.12", "3.13"] +# steps: +# - uses: actions/checkout@v3 +# - name: Install brew +# run: | +# sudo apt install -y build-essential procps curl file git +# /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +# echo "/home/linuxbrew/.linuxbrew/bin" >> $GITHUB_PATH +# - name: Install build dependencies +# run: | +# brew update +# brew install python@${{ matrix.python }} gcc libxml2 libxmlsec1 pkg-config +# echo "/home/linuxbrew/.linuxbrew/opt/python@${{ matrix.python }}/libexec/bin" >> $GITHUB_PATH +# - name: Build wheel +# run: | +# python3 -m venv build_venv +# source build_venv/bin/activate +# pip3 install --upgrade setuptools wheel build +# export CFLAGS="-I$(brew --prefix)/include" +# export LDFLAGS="-L$(brew --prefix)/lib" +# python3 -m build +# rm -rf build/ +# - name: Run tests +# run: | +# python3 -m venv test_venv +# source test_venv/bin/activate +# pip3 install --upgrade --no-binary=lxml -r requirements-test.txt +# pip3 install xmlsec --only-binary=xmlsec --no-index --find-links=dist/ +# pytest -v --color=yes diff --git a/.github/workflows/macosx.yml b/.github/workflows/macosx.yml index 1b82d22d..fdf193fb 100644 --- a/.github/workflows/macosx.yml +++ b/.github/workflows/macosx.yml @@ -1,50 +1,50 @@ -name: MacOS -on: [push, pull_request] -jobs: - macosx: - runs-on: macos-latest - strategy: - matrix: - python: ["3.9", "3.10", "3.11", "3.12", "3.13"] - static_deps: ["static", ""] - steps: - - uses: actions/checkout@v3 - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python }} - - name: Install build dependencies - run: | - pip install --upgrade pip setuptools wheel build - brew install libxml2 libxmlsec1 pkg-config - - name: Build macosx_x86_64 wheel - env: - CC: clang - CFLAGS: "-fprofile-instr-generate -fcoverage-mapping" - LDFLAGS: "-fprofile-instr-generate -fcoverage-mapping" - PYXMLSEC_STATIC_DEPS: ${{ matrix.static_deps }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - export PKG_CONFIG_PATH="$(brew --prefix)/opt/libxml2/lib/pkgconfig" - python -m build - rm -rf build/ - - name: Set environment variables - shell: bash - run: | - echo "PKGVER=$(python setup.py --version)" >> $GITHUB_ENV - echo "LLVM_PROFILE_FILE=pyxmlsec.profraw" >> $GITHUB_ENV - - name: Install test dependencies - run: | - export PKG_CONFIG_PATH="$(brew --prefix)/opt/libxml2/lib/pkgconfig" - pip install coverage --upgrade --no-binary=lxml -r requirements-test.txt - pip install xmlsec --only-binary=xmlsec --no-index --find-links=dist/ - echo "PYXMLSEC_LIBFILE=$(python -c 'import xmlsec; print(xmlsec.__file__)')" >> $GITHUB_ENV - - name: Run tests - run: | - coverage run -m pytest -v --color=yes - - name: Report coverage to codecov - run: | - /Library/Developer/CommandLineTools/usr/bin/llvm-profdata merge -sparse ${{ env.LLVM_PROFILE_FILE }} -output pyxmlsec.profdata - /Library/Developer/CommandLineTools/usr/bin/llvm-cov show ${{ env.PYXMLSEC_LIBFILE }} --arch=$(uname -m) --instr-profile=pyxmlsec.profdata src > coverage.txt - bash <(curl -s https://codecov.io/bash) -f coverage.txt - if: matrix.static_deps != 'static' +# name: MacOS +# on: [push, pull_request] +# jobs: +# macosx: +# runs-on: macos-latest +# strategy: +# matrix: +# python: ["3.9", "3.10", "3.11", "3.12", "3.13"] +# static_deps: ["static", ""] +# steps: +# - uses: actions/checkout@v3 +# - name: Setup Python +# uses: actions/setup-python@v4 +# with: +# python-version: ${{ matrix.python }} +# - name: Install build dependencies +# run: | +# pip install --upgrade pip setuptools wheel build +# brew install libxml2 libxmlsec1 pkg-config +# - name: Build macosx_x86_64 wheel +# env: +# CC: clang +# CFLAGS: "-fprofile-instr-generate -fcoverage-mapping" +# LDFLAGS: "-fprofile-instr-generate -fcoverage-mapping" +# PYXMLSEC_STATIC_DEPS: ${{ matrix.static_deps }} +# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# run: | +# export PKG_CONFIG_PATH="$(brew --prefix)/opt/libxml2/lib/pkgconfig" +# python -m build +# rm -rf build/ +# - name: Set environment variables +# shell: bash +# run: | +# echo "PKGVER=$(python setup.py --version)" >> $GITHUB_ENV +# echo "LLVM_PROFILE_FILE=pyxmlsec.profraw" >> $GITHUB_ENV +# - name: Install test dependencies +# run: | +# export PKG_CONFIG_PATH="$(brew --prefix)/opt/libxml2/lib/pkgconfig" +# pip install coverage --upgrade --no-binary=lxml -r requirements-test.txt +# pip install xmlsec --only-binary=xmlsec --no-index --find-links=dist/ +# echo "PYXMLSEC_LIBFILE=$(python -c 'import xmlsec; print(xmlsec.__file__)')" >> $GITHUB_ENV +# - name: Run tests +# run: | +# coverage run -m pytest -v --color=yes +# - name: Report coverage to codecov +# run: | +# /Library/Developer/CommandLineTools/usr/bin/llvm-profdata merge -sparse ${{ env.LLVM_PROFILE_FILE }} -output pyxmlsec.profdata +# /Library/Developer/CommandLineTools/usr/bin/llvm-cov show ${{ env.PYXMLSEC_LIBFILE }} --arch=$(uname -m) --instr-profile=pyxmlsec.profdata src > coverage.txt +# bash <(curl -s https://codecov.io/bash) -f coverage.txt +# if: matrix.static_deps != 'static' diff --git a/.github/workflows/manylinux.yml b/.github/workflows/manylinux.yml index a44776b3..7b3240cc 100644 --- a/.github/workflows/manylinux.yml +++ b/.github/workflows/manylinux.yml @@ -1,48 +1,47 @@ -name: manylinux -on: [push, pull_request] -jobs: - manylinux: - runs-on: ubuntu-latest - strategy: - matrix: - python-abi: [cp36-cp36m, cp37-cp37m, cp38-cp38, cp39-cp39, cp310-cp310, cp311-cp311] - image: - - manylinux2014_x86_64 - - manylinux_2_28_x86_64 - - musllinux_1_1_x86_64 - container: quay.io/pypa/${{ matrix.image }} - steps: - - uses: actions/checkout@v1 - - name: Install python build dependencies - run: | - # https://github.com/actions/runner/issues/2033 - chown -R $(id -u):$(id -g) $PWD - /opt/python/${{ matrix.python-abi }}/bin/pip install --upgrade pip setuptools wheel build - - name: Install system build dependencies (manylinux) - run: | - yum install -y perl-core - if: contains(matrix.image, 'manylinux') - - name: Set environment variables - shell: bash - run: | - echo "PKGVER=$(/opt/python/${{ matrix.python-abi }}/bin/python setup.py --version)" >> $GITHUB_ENV - - name: Build linux_x86_64 wheel - env: - PYXMLSEC_STATIC_DEPS: true - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - /opt/python/${{ matrix.python-abi }}/bin/python -m build - - name: Label manylinux wheel - run: | - ls -la dist/ - auditwheel show dist/xmlsec-${{ env.PKGVER }}-${{ matrix.python-abi }}-linux_x86_64.whl - auditwheel repair dist/xmlsec-${{ env.PKGVER }}-${{ matrix.python-abi }}-linux_x86_64.whl - ls -la wheelhouse/ - auditwheel show wheelhouse/xmlsec-${{ env.PKGVER }}-${{ matrix.python-abi }}-*${{ matrix.image }}*.whl - - name: Install test dependencies - run: | - /opt/python/${{ matrix.python-abi }}/bin/pip install --upgrade -r requirements-test.txt - /opt/python/${{ matrix.python-abi }}/bin/pip install xmlsec --only-binary=xmlsec --no-index --find-links=wheelhouse/ - - name: Run tests - run: | - /opt/python/${{ matrix.python-abi }}/bin/pytest -v --color=yes +# name: manylinux +# on: [push, pull_request] +# jobs: +# manylinux: +# runs-on: ubuntu-latest +# strategy: +# matrix: +# python-abi: [cp39-cp39, cp310-cp310, cp311-cp311, cp312-cp312, cp313-cp313] +# image: +# - manylinux_2_28_x86_64 +# - musllinux_1_1_x86_64 +# container: quay.io/pypa/${{ matrix.image }} +# steps: +# - uses: actions/checkout@v1 +# - name: Install python build dependencies +# run: | +# # https://github.com/actions/runner/issues/2033 +# chown -R $(id -u):$(id -g) $PWD +# /opt/python/${{ matrix.python-abi }}/bin/pip install --upgrade pip setuptools wheel build packaging +# - name: Install system build dependencies (manylinux) +# run: | +# yum install -y perl-core +# if: contains(matrix.image, 'manylinux') +# - name: Set environment variables +# shell: bash +# run: | +# echo "PKGVER=$(/opt/python/${{ matrix.python-abi }}/bin/python setup.py --version)" >> $GITHUB_ENV +# - name: Build linux_x86_64 wheel +# env: +# PYXMLSEC_STATIC_DEPS: true +# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# run: | +# /opt/python/${{ matrix.python-abi }}/bin/python -m build +# - name: Label manylinux wheel +# run: | +# ls -la dist/ +# auditwheel show dist/xmlsec-${{ env.PKGVER }}-${{ matrix.python-abi }}-linux_x86_64.whl +# auditwheel repair dist/xmlsec-${{ env.PKGVER }}-${{ matrix.python-abi }}-linux_x86_64.whl +# ls -la wheelhouse/ +# auditwheel show wheelhouse/xmlsec-${{ env.PKGVER }}-${{ matrix.python-abi }}-*${{ matrix.image }}*.whl +# - name: Install test dependencies +# run: | +# /opt/python/${{ matrix.python-abi }}/bin/pip install --upgrade -r requirements-test.txt +# /opt/python/${{ matrix.python-abi }}/bin/pip install xmlsec --only-binary=xmlsec --no-index --find-links=wheelhouse/ +# - name: Run tests +# run: | +# /opt/python/${{ matrix.python-abi }}/bin/pytest -v --color=yes diff --git a/.github/workflows/sdist.yml b/.github/workflows/sdist.yml index e987cdce..87392940 100644 --- a/.github/workflows/sdist.yml +++ b/.github/workflows/sdist.yml @@ -1,29 +1,29 @@ -name: sdist -on: [push, pull_request] -jobs: - sdist: - runs-on: ubuntu-latest - strategy: - matrix: - python: ["3.9", "3.10", "3.11", "3.12", "3.13"] - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python }} - - name: Install build dependencies - run: | - pip install --upgrade pip setuptools wheel - - name: Package source dist - run: | - python setup.py sdist - - name: Install test dependencies - run: | - sudo apt-get update - sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl opensc softhsm2 libengine-pkcs11-openssl - pip install --upgrade -r requirements-test.txt --no-binary lxml - pip install dist/xmlsec-$(python setup.py --version).tar.gz - - name: Run tests - run: | - pytest -v --color=yes +# name: sdist +# on: [push, pull_request] +# jobs: +# sdist: +# runs-on: ubuntu-latest +# strategy: +# matrix: +# python: ["3.9", "3.10", "3.11", "3.12", "3.13"] +# steps: +# - uses: actions/checkout@v3 +# - name: Set up Python +# uses: actions/setup-python@v4 +# with: +# python-version: ${{ matrix.python }} +# - name: Install build dependencies +# run: | +# pip install --upgrade pip setuptools wheel +# - name: Package source dist +# run: | +# python setup.py sdist +# - name: Install test dependencies +# run: | +# sudo apt-get update +# sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl opensc softhsm2 libengine-pkcs11-openssl +# pip install --upgrade -r requirements-test.txt --no-binary lxml +# pip install dist/xmlsec-$(python setup.py --version).tar.gz +# - name: Run tests +# run: | +# pytest -v --color=yes diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index af3fb57d..c32b0832 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -15,7 +15,9 @@ on: pull_request: workflow_dispatch: -permissions: {} +permissions: + contents: write + id-token: write jobs: sdist: @@ -69,7 +71,7 @@ jobs: - uses: actions/checkout@v4 - name: Install cibuildwheel # Nb. keep cibuildwheel version pin consistent with job below - run: pipx install cibuildwheel==2.21.3 + run: pipx install cibuildwheel==2.23.3 - id: set-matrix # Once we have the windows build figured out, it can be added here # by updating the matrix to include windows builds as well. @@ -79,11 +81,13 @@ jobs: MATRIX=$( { cibuildwheel --print-build-identifiers --platform linux \ + | grep -E 'manylinux_(x86_64|aarch64)' \ + | grep -E 'cp3(12|13)-' \ | jq -nRc '{"only": inputs, "os": "ubuntu-latest"}' \ && cibuildwheel --print-build-identifiers --platform macos \ - | jq -nRc '{"only": inputs, "os": "macos-latest"}' \ - && cibuildwheel --print-build-identifiers --platform windows \ - | jq -nRc '{"only": inputs, "os": "windows-2019"}' + | grep -E 'cp3(12|13)-' \ + | grep -E 'arm64' \ + | jq -nRc '{"only": inputs, "os": "macos-latest"}' } | jq -sc ) echo "include=$MATRIX" @@ -100,8 +104,10 @@ 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.13.8 + PYXMLSEC_LIBXSLT_VERSION: 1.1.43 + PYXMLSEC_XMLSEC1_VERSION: 1.3.7 + PYXMLSEC_OPENSSL_VERSION: 3.5.0 steps: - name: Check out the repo @@ -115,6 +121,12 @@ jobs: with: platforms: all + - name: Set Homebrew paths for macOS + if: runner.os == 'macOS' + run: | + echo "CPPFLAGS=-I/opt/homebrew/include" >> $GITHUB_ENV + echo "LDFLAGS=-L/opt/homebrew/lib" >> $GITHUB_ENV + - name: Build wheels uses: pypa/cibuildwheel@v2.21.3 with: @@ -126,3 +138,24 @@ jobs: with: path: ./wheelhouse/*.whl name: xmlsec-wheel-${{ matrix.only }} + + upload_release_assets: + needs: build_wheels + runs-on: ubuntu-latest + if: github.event_name == 'release' + steps: + - name: Download all wheel artifacts + uses: actions/download-artifact@v4 + with: + path: all_wheels + + - name: Install gh CLI + run: sudo apt-get update && sudo apt-get install -y gh + + - name: Upload wheels to release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + for wheel in all_wheels/**/*.whl; do + gh release upload "${GITHUB_REF##*/}" "$wheel" --repo "$GITHUB_REPOSITORY" --clobber + done diff --git a/pyproject.toml b/pyproject.toml index 8c03f910..4673bc38 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,23 +44,29 @@ known_first_party = ['xmlsec'] known_third_party = ['lxml', 'pytest', '_pytest', 'hypothesis'] [build-system] -requires = ['setuptools>=42', 'wheel', 'setuptools_scm[toml]>=3.4', "pkgconfig>=1.5.1", "lxml>=3.8, !=4.7.0"] +requires = [ + 'setuptools>=42', + 'wheel', + 'setuptools_scm[toml]>=3.4', + "pkgconfig>=1.5.1", + "lxml>=3.8, !=4.7.0", +] [tool.cibuildwheel] build-verbosity = 1 build-frontend = "build" skip = [ - "pp*", - "*-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*", - "cp38-macosx*", + "pp*", + "*-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*", + "cp38-macosx*", ] test-command = "pytest -v --color=yes {package}/tests" before-test = "pip install -r requirements-test.txt" @@ -72,10 +78,12 @@ PYXMLSEC_STATIC_DEPS = "true" [tool.cibuildwheel.linux] archs = ["x86_64", "aarch64", "i686"] environment-pass = [ - "PYXMLSEC_LIBXML2_VERSION", - "PYXMLSEC_LIBXSLT_VERSION", - "PYXMLSEC_STATIC_DEPS", - "GH_TOKEN" + "PYXMLSEC_LIBXML2_VERSION", + "PYXMLSEC_LIBXSLT_VERSION", + "PYXMLSEC_XMLSEC1_VERSION", + "PYXMLSEC_OPENSSL_VERSION", + "PYXMLSEC_STATIC_DEPS", + "GH_TOKEN", ] [tool.cibuildwheel.macos] 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 diff --git a/setup.py b/setup.py index 92588ebc..48ea8b20 100644 --- a/setup.py +++ b/setup.py @@ -26,19 +26,19 @@ def __init__(self, *args, **kwargs): self.hrefs = [] def handle_starttag(self, tag, attrs): - if tag == 'a': + if tag == "a": for name, value in attrs: - if name == 'href': + if name == "href": self.hrefs.append(value) def make_request(url, github_token=None, json_response=False): - headers = {'User-Agent': 'https://github.com/xmlsec/python-xmlsec'} + headers = {"User-Agent": "https://github.com/xmlsec/python-xmlsec"} if github_token: - headers['authorization'] = "Bearer " + github_token + headers["authorization"] = "Bearer " + github_token request = Request(url, headers=headers) with contextlib.closing(urlopen(request)) as r: - charset = r.headers.get_content_charset() or 'utf-8' + charset = r.headers.get_content_charset() or "utf-8" content = r.read().decode(charset) if json_response: return json.loads(content) @@ -54,58 +54,71 @@ def latest_release_from_html(url, matcher): def comp(text): try: - return Version(matcher.match(text).groupdict()['version']) + return Version(matcher.match(text).groupdict()["version"]) except (AttributeError, ValueError): - return Version('0.0') + return Version("0.0") latest = max(hrefs, key=comp) - return '{}/{}'.format(url, latest) + return "{}/{}".format(url, latest) def latest_release_from_gnome_org_cache(url, lib_name): - cache_url = '{}/cache.json'.format(url) + cache_url = "{}/cache.json".format(url) cache = make_request(cache_url, json_response=True) latest_version = cache[2][lib_name][-1] - latest_source = cache[1][lib_name][latest_version]['tar.xz'] - return '{}/{}'.format(url, latest_source) + latest_source = cache[1][lib_name][latest_version]["tar.xz"] + return "{}/{}".format(url, latest_source) def latest_release_from_github_api(repo): - api_url = 'https://api.github.com/repos/{}/releases'.format(repo) + api_url = "https://api.github.com/repos/{}/releases".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] + 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)) + raise DistutilsError("No release found for {}".format(repo)) return releases[0] def latest_openssl_release(): - return latest_release_from_github_api('openssl/openssl') + return latest_release_from_github_api("openssl/openssl") def latest_zlib_release(): - return latest_release_from_html('https://zlib.net/fossils', re.compile('zlib-(?P.*).tar.gz')) + return latest_release_from_html( + "https://zlib.net/fossils", re.compile("zlib-(?P.*).tar.gz") + ) def latest_libiconv_release(): - return latest_release_from_html('https://ftp.gnu.org/pub/gnu/libiconv', re.compile('libiconv-(?P.*).tar.gz')) + return latest_release_from_html( + "https://ftp.gnu.org/pub/gnu/libiconv", + re.compile("libiconv-(?P.*).tar.gz"), + ) def latest_libxml2_release(): - return latest_release_from_gnome_org_cache('https://download.gnome.org/sources/libxml2', 'libxml2') + return latest_release_from_gnome_org_cache( + "https://download.gnome.org/sources/libxml2", "libxml2" + ) def latest_libxslt_release(): - return latest_release_from_gnome_org_cache('https://download.gnome.org/sources/libxslt', 'libxslt') + return latest_release_from_gnome_org_cache( + "https://download.gnome.org/sources/libxslt", "libxslt" + ) def latest_xmlsec_release(): - return latest_release_from_html('https://www.aleksey.com/xmlsec/download/', re.compile('xmlsec1-(?P.*).tar.gz')) + return latest_release_from_github_api("lsh123/xmlsec") class CrossCompileInfo: @@ -124,108 +137,115 @@ def info(self, message): self.announce(message, level=log.INFO) def run(self): - ext = self.ext_map['xmlsec'] - self.debug = os.environ.get('PYXMLSEC_ENABLE_DEBUG', False) - self.static = os.environ.get('PYXMLSEC_STATIC_DEPS', False) - self.size_opt = os.environ.get('PYXMLSEC_OPTIMIZE_SIZE', True) + ext = self.ext_map["xmlsec"] + self.debug = os.environ.get("PYXMLSEC_ENABLE_DEBUG", False) + self.static = os.environ.get("PYXMLSEC_STATIC_DEPS", False) + self.size_opt = os.environ.get("PYXMLSEC_OPTIMIZE_SIZE", True) - if self.static or sys.platform == 'win32': - self.info('starting static build on {}'.format(sys.platform)) - buildroot = Path('build', 'tmp') + if self.static or sys.platform == "win32": + self.info("starting static build on {}".format(sys.platform)) + buildroot = Path("build", "tmp") - self.prefix_dir = buildroot / 'prefix' + self.prefix_dir = buildroot / "prefix" self.prefix_dir.mkdir(parents=True, exist_ok=True) self.prefix_dir = self.prefix_dir.absolute() - self.build_libs_dir = buildroot / 'libs' + self.build_libs_dir = buildroot / "libs" self.build_libs_dir.mkdir(exist_ok=True) - self.libs_dir = Path(os.environ.get('PYXMLSEC_LIBS_DIR', 'libs')) + self.libs_dir = Path(os.environ.get("PYXMLSEC_LIBS_DIR", "libs")) self.libs_dir.mkdir(exist_ok=True) - self.info('{:20} {}'.format('Lib sources in:', self.libs_dir.absolute())) + self.info("{:20} {}".format("Lib sources in:", self.libs_dir.absolute())) - if sys.platform == 'win32': + if sys.platform == "win32": self.prepare_static_build_win() - elif 'linux' in sys.platform: + elif "linux" in sys.platform: self.prepare_static_build(sys.platform) - elif 'darwin' in sys.platform: + elif "darwin" in sys.platform: self.prepare_static_build(sys.platform) else: import pkgconfig try: - config = pkgconfig.parse('xmlsec1') + config = pkgconfig.parse("xmlsec1") except EnvironmentError: - raise DistutilsError('Unable to invoke pkg-config.') + raise DistutilsError("Unable to invoke pkg-config.") except pkgconfig.PackageNotFoundError: - raise DistutilsError('xmlsec1 is not installed or not in path.') + raise DistutilsError("xmlsec1 is not installed or not in path.") - if config is None or not config.get('libraries'): - raise DistutilsError('Bad or incomplete result returned from pkg-config.') + if config is None or not config.get("libraries"): + raise DistutilsError( + "Bad or incomplete result returned from pkg-config." + ) - ext.define_macros.extend(config['define_macros']) - ext.include_dirs.extend(config['include_dirs']) - ext.library_dirs.extend(config['library_dirs']) - ext.libraries.extend(config['libraries']) + ext.define_macros.extend(config["define_macros"]) + ext.include_dirs.extend(config["include_dirs"]) + ext.library_dirs.extend(config["library_dirs"]) + ext.libraries.extend(config["libraries"]) import lxml ext.include_dirs.extend(lxml.get_include()) ext.define_macros.extend( - [('MODULE_NAME', self.distribution.metadata.name), ('MODULE_VERSION', self.distribution.metadata.version)] + [ + ("MODULE_NAME", self.distribution.metadata.name), + ("MODULE_VERSION", self.distribution.metadata.version), + ] ) # escape the XMLSEC_CRYPTO macro value, see mehcode/python-xmlsec#141 for key, value in ext.define_macros: - if key == 'XMLSEC_CRYPTO' and not (value.startswith('"') and value.endswith('"')): + if key == "XMLSEC_CRYPTO" and not ( + value.startswith('"') and value.endswith('"') + ): ext.define_macros.remove((key, value)) ext.define_macros.append((key, '"{0}"'.format(value))) break - if sys.platform == 'win32': - ext.extra_compile_args.append('/Zi') + if sys.platform == "win32": + ext.extra_compile_args.append("/Zi") else: ext.extra_compile_args.extend( [ - '-g', - '-std=c99', - '-fPIC', - '-fno-strict-aliasing', - '-Wno-error=declaration-after-statement', - '-Werror=implicit-function-declaration', + "-g", + "-std=c99", + "-fPIC", + "-fno-strict-aliasing", + "-Wno-error=declaration-after-statement", + "-Werror=implicit-function-declaration", ] ) if self.debug: - ext.define_macros.append(('PYXMLSEC_ENABLE_DEBUG', '1')) - if sys.platform == 'win32': - ext.extra_compile_args.append('/Od') + ext.define_macros.append(("PYXMLSEC_ENABLE_DEBUG", "1")) + if sys.platform == "win32": + ext.extra_compile_args.append("/Od") else: - ext.extra_compile_args.append('-Wall') - ext.extra_compile_args.append('-O0') + ext.extra_compile_args.append("-Wall") + ext.extra_compile_args.append("-O0") else: if self.size_opt: - if sys.platform == 'win32': - ext.extra_compile_args.append('/Os') + if sys.platform == "win32": + ext.extra_compile_args.append("/Os") else: - ext.extra_compile_args.append('-Os') + ext.extra_compile_args.append("-Os") super(build_ext, self).run() def prepare_static_build_win(self): - release_url = 'https://github.com/mxamin/python-xmlsec-win-binaries/releases/download/2024.04.17/' + release_url = "https://github.com/mxamin/python-xmlsec-win-binaries/releases/download/2024.04.17/" if sys.maxsize > 2147483647: # 2.0 GiB - suffix = 'win64' + suffix = "win64" else: - suffix = 'win32' + suffix = "win32" libs = [ - 'libxml2-2.11.7.{}.zip'.format(suffix), - 'libxslt-1.1.37.{}.zip'.format(suffix), - 'zlib-1.2.12.{}.zip'.format(suffix), - 'iconv-1.16-1.{}.zip'.format(suffix), - 'openssl-3.0.8.{}.zip'.format(suffix), - 'xmlsec-1.3.4.{}.zip'.format(suffix), + "libxml2-2.11.7.{}.zip".format(suffix), + "libxslt-1.1.37.{}.zip".format(suffix), + "zlib-1.2.12.{}.zip".format(suffix), + "iconv-1.16-1.{}.zip".format(suffix), + "openssl-3.0.8.{}.zip".format(suffix), + "xmlsec-1.3.4.{}.zip".format(suffix), ] for libfile in libs: @@ -238,404 +258,540 @@ def prepare_static_build_win(self): urlcleanup() # work around FTP bug 27973 in Py2.7.12+ urlretrieve(url, str(destfile)) - for p in self.libs_dir.glob('*.zip'): + for p in self.libs_dir.glob("*.zip"): with zipfile.ZipFile(str(p)) as f: destdir = self.build_libs_dir f.extractall(path=str(destdir)) - ext = self.ext_map['xmlsec'] + ext = self.ext_map["xmlsec"] ext.define_macros = [ - ('XMLSEC_CRYPTO', '\\"openssl\\"'), - ('__XMLSEC_FUNCTION__', '__FUNCTION__'), - ('XMLSEC_NO_GOST', '1'), - ('XMLSEC_NO_XKMS', '1'), - ('XMLSEC_NO_CRYPTO_DYNAMIC_LOADING', '1'), - ('XMLSEC_CRYPTO_OPENSSL', '1'), - ('UNICODE', '1'), - ('_UNICODE', '1'), - ('LIBXML_ICONV_ENABLED', 1), - ('LIBXML_STATIC', '1'), - ('LIBXSLT_STATIC', '1'), - ('XMLSEC_STATIC', '1'), - ('inline', '__inline'), + ("XMLSEC_CRYPTO", '\\"openssl\\"'), + ("__XMLSEC_FUNCTION__", "__FUNCTION__"), + ("XMLSEC_NO_GOST", "1"), + ("XMLSEC_NO_XKMS", "1"), + ("XMLSEC_NO_CRYPTO_DYNAMIC_LOADING", "1"), + ("XMLSEC_CRYPTO_OPENSSL", "1"), + ("UNICODE", "1"), + ("_UNICODE", "1"), + ("LIBXML_ICONV_ENABLED", 1), + ("LIBXML_STATIC", "1"), + ("LIBXSLT_STATIC", "1"), + ("XMLSEC_STATIC", "1"), + ("inline", "__inline"), ] ext.libraries = [ - 'libxmlsec_a', - 'libxmlsec-openssl_a', - 'libcrypto', - 'iconv_a', - 'libxslt_a', - 'libexslt_a', - 'libxml2_a', - 'zlib', - 'WS2_32', - 'Advapi32', - 'User32', - 'Gdi32', - 'Crypt32', + "libxmlsec_a", + "libxmlsec-openssl_a", + "libcrypto", + "iconv_a", + "libxslt_a", + "libexslt_a", + "libxml2_a", + "zlib", + "WS2_32", + "Advapi32", + "User32", + "Gdi32", + "Crypt32", ] - ext.library_dirs = [str(p.absolute()) for p in self.build_libs_dir.rglob('lib')] + ext.library_dirs = [str(p.absolute()) for p in self.build_libs_dir.rglob("lib")] - includes = [p for p in self.build_libs_dir.rglob('include') if p.is_dir()] - includes.append(next(p / 'xmlsec' for p in includes if (p / 'xmlsec').is_dir())) + includes = [p for p in self.build_libs_dir.rglob("include") if p.is_dir()] + includes.append(next(p / "xmlsec" for p in includes if (p / "xmlsec").is_dir())) ext.include_dirs = [str(p.absolute()) for p in includes] def prepare_static_build(self, build_platform): - self.openssl_version = os.environ.get('PYXMLSEC_OPENSSL_VERSION') - self.libiconv_version = os.environ.get('PYXMLSEC_LIBICONV_VERSION') - self.libxml2_version = os.environ.get('PYXMLSEC_LIBXML2_VERSION') - self.libxslt_version = os.environ.get('PYXMLSEC_LIBXSLT_VERSION') - self.zlib_version = os.environ.get('PYXMLSEC_ZLIB_VERSION') - self.xmlsec1_version = os.environ.get('PYXMLSEC_XMLSEC1_VERSION') + self.openssl_version = os.environ.get("PYXMLSEC_OPENSSL_VERSION") + self.libiconv_version = os.environ.get("PYXMLSEC_LIBICONV_VERSION") + self.libxml2_version = os.environ.get("PYXMLSEC_LIBXML2_VERSION") + self.libxslt_version = os.environ.get("PYXMLSEC_LIBXSLT_VERSION") + self.zlib_version = os.environ.get("PYXMLSEC_ZLIB_VERSION") + self.xmlsec1_version = os.environ.get("PYXMLSEC_XMLSEC1_VERSION") # fetch openssl - openssl_tar = next(self.libs_dir.glob('openssl*.tar.gz'), None) + openssl_tar = next(self.libs_dir.glob("openssl*.tar.gz"), None) if openssl_tar is None: - self.info('{:10}: {}'.format('OpenSSL', 'source tar not found, downloading ...')) - openssl_tar = self.libs_dir / 'openssl.tar.gz' + self.info( + "{:10}: {}".format("OpenSSL", "source tar not found, downloading ...") + ) + openssl_tar = self.libs_dir / "openssl.tar.gz" if self.openssl_version is None: url = latest_openssl_release() - self.info('{:10}: {}'.format('OpenSSL', 'PYXMLSEC_OPENSSL_VERSION unset, downloading latest from {}'.format(url))) + self.info( + "{:10}: {}".format( + "OpenSSL", + "PYXMLSEC_OPENSSL_VERSION unset, downloading latest from {}".format( + url + ), + ) + ) else: - url = 'https://api.github.com/repos/openssl/openssl/tarball/openssl-{}'.format(self.openssl_version) - self.info('{:10}: {} {}'.format('OpenSSL', 'version', self.openssl_version)) + url = "https://api.github.com/repos/openssl/openssl/tarball/openssl-{}".format( + self.openssl_version + ) + self.info( + "{:10}: {} {}".format("OpenSSL", "version", self.openssl_version) + ) urlretrieve(url, str(openssl_tar)) # fetch zlib - zlib_tar = next(self.libs_dir.glob('zlib*.tar.gz'), None) + zlib_tar = next(self.libs_dir.glob("zlib*.tar.gz"), None) if zlib_tar is None: - self.info('{:10}: {}'.format('zlib', 'source not found, downloading ...')) - zlib_tar = self.libs_dir / 'zlib.tar.gz' + self.info("{:10}: {}".format("zlib", "source not found, downloading ...")) + zlib_tar = self.libs_dir / "zlib.tar.gz" if self.zlib_version is None: url = latest_zlib_release() - self.info('{:10}: {}'.format('zlib', 'PYXMLSEC_ZLIB_VERSION unset, downloading latest from {}'.format(url))) + self.info( + "{:10}: {}".format( + "zlib", + "PYXMLSEC_ZLIB_VERSION unset, downloading latest from {}".format( + url + ), + ) + ) else: - url = 'https://zlib.net/fossils/zlib-{}.tar.gz'.format(self.zlib_version) + url = "https://zlib.net/fossils/zlib-{}.tar.gz".format( + self.zlib_version + ) self.info( - '{:10}: {}'.format('zlib', 'PYXMLSEC_ZLIB_VERSION={}, downloading from {}'.format(self.zlib_version, url)) + "{:10}: {}".format( + "zlib", + "PYXMLSEC_ZLIB_VERSION={}, downloading from {}".format( + self.zlib_version, url + ), + ) ) urlretrieve(url, str(zlib_tar)) # fetch libiconv - libiconv_tar = next(self.libs_dir.glob('libiconv*.tar.gz'), None) + libiconv_tar = next(self.libs_dir.glob("libiconv*.tar.gz"), None) if libiconv_tar is None: - self.info('{:10}: {}'.format('libiconv', 'source not found, downloading ...')) - libiconv_tar = self.libs_dir / 'libiconv.tar.gz' + self.info( + "{:10}: {}".format("libiconv", "source not found, downloading ...") + ) + libiconv_tar = self.libs_dir / "libiconv.tar.gz" if self.libiconv_version is None: url = latest_libiconv_release() - self.info('{:10}: {}'.format('zlib', 'PYXMLSEC_LIBICONV_VERSION unset, downloading latest from {}'.format(url))) + self.info( + "{:10}: {}".format( + "zlib", + "PYXMLSEC_LIBICONV_VERSION unset, downloading latest from {}".format( + url + ), + ) + ) else: - url = 'https://ftp.gnu.org/pub/gnu/libiconv/libiconv-{}.tar.gz'.format(self.libiconv_version) + url = "https://ftp.gnu.org/pub/gnu/libiconv/libiconv-{}.tar.gz".format( + self.libiconv_version + ) self.info( - '{:10}: {}'.format( - 'zlib', 'PYXMLSEC_LIBICONV_VERSION={}, downloading from {}'.format(self.libiconv_version, url) + "{:10}: {}".format( + "zlib", + "PYXMLSEC_LIBICONV_VERSION={}, downloading from {}".format( + self.libiconv_version, url + ), ) ) urlretrieve(url, str(libiconv_tar)) # fetch libxml2 - libxml2_tar = next(self.libs_dir.glob('libxml2*.tar.xz'), None) + libxml2_tar = next(self.libs_dir.glob("libxml2*.tar.xz"), None) if libxml2_tar is None: - self.info('{:10}: {}'.format('libxml2', 'source tar not found, downloading ...')) + self.info( + "{:10}: {}".format("libxml2", "source tar not found, downloading ...") + ) if self.libxml2_version is None: url = latest_libxml2_release() - self.info('{:10}: {}'.format('libxml2', 'PYXMLSEC_LIBXML2_VERSION unset, downloading latest from {}'.format(url))) + self.info( + "{:10}: {}".format( + "libxml2", + "PYXMLSEC_LIBXML2_VERSION unset, downloading latest from {}".format( + url + ), + ) + ) else: - version_prefix, _ = self.libxml2_version.rsplit('.', 1) - url = 'https://download.gnome.org/sources/libxml2/{}/libxml2-{}.tar.xz'.format( + version_prefix, _ = self.libxml2_version.rsplit(".", 1) + url = "https://download.gnome.org/sources/libxml2/{}/libxml2-{}.tar.xz".format( version_prefix, self.libxml2_version ) self.info( - '{:10}: {}'.format( - 'libxml2', 'PYXMLSEC_LIBXML2_VERSION={}, downloading from {}'.format(self.libxml2_version, url) + "{:10}: {}".format( + "libxml2", + "PYXMLSEC_LIBXML2_VERSION={}, downloading from {}".format( + self.libxml2_version, url + ), ) ) - libxml2_tar = self.libs_dir / 'libxml2.tar.xz' + libxml2_tar = self.libs_dir / "libxml2.tar.xz" urlretrieve(url, str(libxml2_tar)) # fetch libxslt - libxslt_tar = next(self.libs_dir.glob('libxslt*.tar.gz'), None) + libxslt_tar = next(self.libs_dir.glob("libxslt*.tar.gz"), None) if libxslt_tar is None: - self.info('{:10}: {}'.format('libxslt', 'source tar not found, downloading ...')) + self.info( + "{:10}: {}".format("libxslt", "source tar not found, downloading ...") + ) if self.libxslt_version is None: url = latest_libxslt_release() - self.info('{:10}: {}'.format('libxslt', 'PYXMLSEC_LIBXSLT_VERSION unset, downloading latest from {}'.format(url))) + self.info( + "{:10}: {}".format( + "libxslt", + "PYXMLSEC_LIBXSLT_VERSION unset, downloading latest from {}".format( + url + ), + ) + ) else: - version_prefix, _ = self.libxslt_version.rsplit('.', 1) - url = 'https://download.gnome.org/sources/libxslt/{}/libxslt-{}.tar.xz'.format( + version_prefix, _ = self.libxslt_version.rsplit(".", 1) + url = "https://download.gnome.org/sources/libxslt/{}/libxslt-{}.tar.xz".format( version_prefix, self.libxslt_version ) self.info( - '{:10}: {}'.format( - 'libxslt', 'PYXMLSEC_LIBXSLT_VERSION={}, downloading from {}'.format(self.libxslt_version, url) + "{:10}: {}".format( + "libxslt", + "PYXMLSEC_LIBXSLT_VERSION={}, downloading from {}".format( + self.libxslt_version, url + ), ) ) - libxslt_tar = self.libs_dir / 'libxslt.tar.gz' + libxslt_tar = self.libs_dir / "libxslt.tar.gz" urlretrieve(url, str(libxslt_tar)) # fetch xmlsec1 - xmlsec1_tar = next(self.libs_dir.glob('xmlsec1*.tar.gz'), None) + xmlsec1_tar = next(self.libs_dir.glob("xmlsec1*.tar.gz"), None) if xmlsec1_tar is None: - self.info('{:10}: {}'.format('xmlsec1', 'source tar not found, downloading ...')) + self.info( + "{:10}: {}".format("xmlsec1", "source tar not found, downloading ...") + ) if self.xmlsec1_version is None: url = latest_xmlsec_release() - self.info('{:10}: {}'.format('xmlsec1', 'PYXMLSEC_XMLSEC1_VERSION unset, downloading latest from {}'.format(url))) + 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/{}/xmlsec1-{}.tar.gz".format( + self.xmlsec1_version, self.xmlsec1_version + ) + self.info( - '{:10}: {}'.format( - 'xmlsec1', 'PYXMLSEC_XMLSEC1_VERSION={}, downloading from {}'.format(self.xmlsec1_version, url) + "{:10}: {}".format( + "xmlsec1", + "PYXMLSEC_XMLSEC1_VERSION={}, downloading from {}".format( + self.xmlsec1_version, url + ), ) ) - xmlsec1_tar = self.libs_dir / 'xmlsec1.tar.gz' + xmlsec1_tar = self.libs_dir / "xmlsec1.tar.gz" urlretrieve(url, str(xmlsec1_tar)) - for file in (openssl_tar, zlib_tar, libiconv_tar, libxml2_tar, libxslt_tar, xmlsec1_tar): - self.info('Unpacking {}'.format(file.name)) + for file in ( + openssl_tar, + zlib_tar, + libiconv_tar, + libxml2_tar, + libxslt_tar, + xmlsec1_tar, + ): + self.info("Unpacking {}".format(file.name)) try: with tarfile.open(str(file)) as tar: tar.extractall(path=str(self.build_libs_dir)) except EOFError: - raise DistutilsError('Bad {} downloaded; remove it and try again.'.format(file.name)) + raise DistutilsError( + "Bad {} downloaded; remove it and try again.".format(file.name) + ) - prefix_arg = '--prefix={}'.format(self.prefix_dir) + prefix_arg = "--prefix={}".format(self.prefix_dir) env = os.environ.copy() cflags = [] - if env.get('CFLAGS'): - cflags.append(env['CFLAGS']) - cflags.append('-fPIC') + if env.get("CFLAGS"): + cflags.append(env["CFLAGS"]) + cflags.append("-fPIC") ldflags = [] - if env.get('LDFLAGS'): - ldflags.append(env['LDFLAGS']) + if env.get("LDFLAGS"): + ldflags.append(env["LDFLAGS"]) cross_compiling = False - if build_platform == 'darwin': + if build_platform == "darwin": import platform - arch = self.plat_name.rsplit('-', 1)[1] - if arch != platform.machine() and arch in ('x86_64', 'arm64'): - self.info('Cross-compiling for {}'.format(arch)) - cflags.append('-arch {}'.format(arch)) - ldflags.append('-arch {}'.format(arch)) - cross_compiling = CrossCompileInfo('darwin64', arch, 'cc') - major_version, minor_version = tuple(map(int, platform.mac_ver()[0].split('.')[:2])) + arch = self.plat_name.rsplit("-", 1)[1] + if arch != platform.machine() and arch in ("x86_64", "arm64"): + self.info("Cross-compiling for {}".format(arch)) + cflags.append("-arch {}".format(arch)) + ldflags.append("-arch {}".format(arch)) + cross_compiling = CrossCompileInfo("darwin64", arch, "cc") + major_version, minor_version = tuple( + map(int, platform.mac_ver()[0].split(".")[:2]) + ) if major_version >= 11: - if 'MACOSX_DEPLOYMENT_TARGET' not in env: - env['MACOSX_DEPLOYMENT_TARGET'] = "11.0" + if "MACOSX_DEPLOYMENT_TARGET" not in env: + env["MACOSX_DEPLOYMENT_TARGET"] = "11.0" - env['CFLAGS'] = ' '.join(cflags) - env['LDFLAGS'] = ' '.join(ldflags) + env["CFLAGS"] = " ".join(cflags) + env["LDFLAGS"] = " ".join(ldflags) - self.info('Building OpenSSL') - openssl_dir = next(self.build_libs_dir.glob('openssl-*')) - openssl_config_cmd = [prefix_arg, 'no-shared', '-fPIC', '--libdir=lib'] + self.info("Building OpenSSL") + openssl_dir = next(self.build_libs_dir.glob("openssl-*")) + openssl_config_cmd = [prefix_arg, "no-shared", "-fPIC", "--libdir=lib"] if cross_compiling: - openssl_config_cmd.insert(0, './Configure') + openssl_config_cmd.insert(0, "./Configure") openssl_config_cmd.append(cross_compiling.triplet) else: - openssl_config_cmd.insert(0, './config') + 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( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install_sw'], cwd=str(openssl_dir), env=env + ["make", "-j{}".format(multiprocessing.cpu_count() + 1)], + cwd=str(openssl_dir), + env=env, + ) + subprocess.check_output( + ["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) + 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, + ) 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-*')) + self.info("Building libiconv") + libiconv_dir = next(self.build_libs_dir.glob("libiconv-*")) subprocess.check_output( [ - './configure', + "./configure", prefix_arg, - '--disable-dependency-tracking', - '--disable-shared', + "--disable-dependency-tracking", + "--disable-shared", host_arg, ], 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( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libiconv_dir), env=env + ["make", "-j{}".format(multiprocessing.cpu_count() + 1)], + cwd=str(libiconv_dir), + env=env, + ) + subprocess.check_output( + ["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-*')) + self.info("Building LibXML2") + libxml2_dir = next(self.build_libs_dir.glob("libxml2-*")) subprocess.check_output( [ - './configure', + "./configure", prefix_arg, - '--disable-dependency-tracking', - '--disable-shared', - '--without-lzma', - '--without-python', - '--with-iconv={}'.format(self.prefix_dir), - '--with-zlib={}'.format(self.prefix_dir), + "--disable-dependency-tracking", + "--disable-shared", + "--without-lzma", + "--without-python", + "--with-iconv={}".format(self.prefix_dir), + "--with-zlib={}".format(self.prefix_dir), host_arg, ], 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( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libxml2_dir), env=env + ["make", "-j{}".format(multiprocessing.cpu_count() + 1)], + cwd=str(libxml2_dir), + env=env, + ) + subprocess.check_output( + ["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-*')) + self.info("Building libxslt") + libxslt_dir = next(self.build_libs_dir.glob("libxslt-*")) subprocess.check_output( [ - './configure', + "./configure", prefix_arg, - '--disable-dependency-tracking', - '--disable-shared', - '--without-python', - '--without-crypto', - '--with-libxml-prefix={}'.format(self.prefix_dir), + "--disable-dependency-tracking", + "--disable-shared", + "--without-python", + "--without-crypto", + "--with-libxml-prefix={}".format(self.prefix_dir), host_arg, ], 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( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(libxslt_dir), env=env + ["make", "-j{}".format(multiprocessing.cpu_count() + 1)], + cwd=str(libxslt_dir), + env=env, + ) + subprocess.check_output( + ["make", "-j{}".format(multiprocessing.cpu_count() + 1), "install"], + cwd=str(libxslt_dir), + env=env, ) - self.info('Building xmlsec1') - ldflags.append('-lpthread') - env['LDFLAGS'] = ' '.join(ldflags) - xmlsec1_dir = next(self.build_libs_dir.glob('xmlsec1-*')) + self.info("Building xmlsec1") + ldflags.append("-lpthread") + env["LDFLAGS"] = " ".join(ldflags) + xmlsec1_dir = next(self.build_libs_dir.glob("xmlsec1-*")) subprocess.check_output( [ - './configure', + "./configure", prefix_arg, - '--disable-shared', - '--disable-gost', - '--enable-md5', - '--disable-crypto-dl', - '--enable-static=yes', - '--enable-shared=no', - '--enable-static-linking=yes', - '--with-default-crypto=openssl', - '--with-openssl={}'.format(self.prefix_dir), - '--with-libxml={}'.format(self.prefix_dir), - '--with-libxslt={}'.format(self.prefix_dir), + "--disable-shared", + "--disable-gost", + "--enable-md5", + "--enable-ripemd160", + "--disable-crypto-dl", + "--enable-static=yes", + "--enable-shared=no", + "--enable-static-linking=yes", + "--with-default-crypto=openssl", + "--with-openssl={}".format(self.prefix_dir), + "--with-libxml={}".format(self.prefix_dir), + "--with-libxslt={}".format(self.prefix_dir), host_arg, ], cwd=str(xmlsec1_dir), env=env, ) subprocess.check_output( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1)] - + ['-I{}'.format(str(self.prefix_dir / 'include')), '-I{}'.format(str(self.prefix_dir / 'include' / 'libxml'))], + ["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( - ['make', '-j{}'.format(multiprocessing.cpu_count() + 1), 'install'], cwd=str(xmlsec1_dir), env=env + ["make", "-j{}".format(multiprocessing.cpu_count() + 1), "install"], + cwd=str(xmlsec1_dir), + env=env, ) - ext = self.ext_map['xmlsec'] + ext = self.ext_map["xmlsec"] ext.define_macros = [ - ('__XMLSEC_FUNCTION__', '__func__'), - ('XMLSEC_NO_SIZE_T', None), - ('XMLSEC_NO_GOST', '1'), - ('XMLSEC_NO_GOST2012', '1'), - ('XMLSEC_NO_XKMS', '1'), - ('XMLSEC_CRYPTO', '\\"openssl\\"'), - ('XMLSEC_NO_CRYPTO_DYNAMIC_LOADING', '1'), - ('XMLSEC_CRYPTO_OPENSSL', '1'), - ('LIBXML_ICONV_ENABLED', 1), - ('LIBXML_STATIC', '1'), - ('LIBXSLT_STATIC', '1'), - ('XMLSEC_STATIC', '1'), - ('inline', '__inline'), - ('UNICODE', '1'), - ('_UNICODE', '1'), + ("__XMLSEC_FUNCTION__", "__func__"), + ("XMLSEC_NO_SIZE_T", None), + ("XMLSEC_NO_GOST", "1"), + ("XMLSEC_NO_GOST2012", "1"), + ("XMLSEC_NO_XKMS", "1"), + ("XMLSEC_CRYPTO", '\\"openssl\\"'), + ("XMLSEC_NO_CRYPTO_DYNAMIC_LOADING", "1"), + ("XMLSEC_CRYPTO_OPENSSL", "1"), + ("LIBXML_ICONV_ENABLED", 1), + ("LIBXML_STATIC", "1"), + ("LIBXSLT_STATIC", "1"), + ("XMLSEC_STATIC", "1"), + ("inline", "__inline"), + ("UNICODE", "1"), + ("_UNICODE", "1"), ] - ext.include_dirs.append(str(self.prefix_dir / 'include')) - ext.include_dirs.extend([str(p.absolute()) for p in (self.prefix_dir / 'include').iterdir() if p.is_dir()]) + ext.include_dirs.append(str(self.prefix_dir / "include")) + ext.include_dirs.extend( + [ + str(p.absolute()) + for p in (self.prefix_dir / "include").iterdir() + if p.is_dir() + ] + ) ext.library_dirs = [] - if build_platform == 'linux': - ext.libraries = ['m', 'rt'] + if build_platform == "linux": + ext.libraries = ["m", "rt"] extra_objects = [ - 'libxmlsec1.a', - 'libxslt.a', - 'libxml2.a', - 'libz.a', - 'libxmlsec1-openssl.a', - 'libcrypto.a', - 'libiconv.a', - 'libxmlsec1.a', + "libxmlsec1.a", + "libxslt.a", + "libxml2.a", + "libz.a", + "libxmlsec1-openssl.a", + "libcrypto.a", + "libiconv.a", + "libxmlsec1.a", ] - ext.extra_objects = [str(self.prefix_dir / 'lib' / o) for o in extra_objects] + ext.extra_objects = [str(self.prefix_dir / "lib" / o) for o in extra_objects] -src_root = Path(__file__).parent / 'src' -sources = [str(p.absolute()) for p in src_root.rglob('*.c')] -pyxmlsec = Extension('xmlsec', sources=sources) -setup_reqs = ['setuptools_scm[toml]>=3.4', 'pkgconfig>=1.5.1', 'lxml>=3.8'] +src_root = Path(__file__).parent / "src" +sources = [str(p.absolute()) for p in src_root.rglob("*.c")] +pyxmlsec = Extension("xmlsec", sources=sources) +setup_reqs = ["setuptools_scm[toml]>=3.4", "pkgconfig>=1.5.1", "lxml>=3.8"] -with io.open('README.rst', encoding='utf-8') as f: +with io.open("README.rst", encoding="utf-8") as f: long_desc = f.read() setup( - name='xmlsec', - use_scm_version=True, - description='Python bindings for the XML Security Library', + name="xmlsec", + # use_scm_version=True, + version="1.3.15", # <- manual + description="Python bindings for the XML Security Library", long_description=long_desc, - long_description_content_type='text/markdown', + long_description_content_type="text/markdown", ext_modules=[pyxmlsec], - cmdclass={'build_ext': build_ext}, - python_requires='>=3.5', + cmdclass={"build_ext": build_ext}, + python_requires=">=3.5", setup_requires=setup_reqs, - install_requires=['lxml>=3.8'], + install_requires=["lxml>=3.8"], author="Bulat Gaifullin", - author_email='support@mehcode.com', - maintainer='Oleg Hoefling', - maintainer_email='oleg.hoefling@gmail.com', - url='https://github.com/mehcode/python-xmlsec', + author_email="support@mehcode.com", + maintainer="Oleg Hoefling", + maintainer_email="oleg.hoefling@gmail.com", + url="https://github.com/mehcode/python-xmlsec", project_urls={ - 'Documentation': 'https://xmlsec.readthedocs.io', - 'Source': 'https://github.com/mehcode/python-xmlsec', - 'Changelog': 'https://github.com/mehcode/python-xmlsec/releases', + "Documentation": "https://xmlsec.readthedocs.io", + "Source": "https://github.com/mehcode/python-xmlsec", + "Changelog": "https://github.com/mehcode/python-xmlsec/releases", }, - license='MIT', - keywords=['xmlsec'], + license="MIT", + keywords=["xmlsec"], classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: C', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.11', - 'Topic :: Text Processing :: Markup :: XML', - 'Typing :: Typed', + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: C", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.11", + "Topic :: Text Processing :: Markup :: XML", + "Typing :: Typed", ], zip_safe=False, - packages=['xmlsec'], - package_dir={'': 'src'}, - package_data={'xmlsec': ['py.typed', '*.pyi']}, + packages=["xmlsec"], + package_dir={"": "src"}, + package_data={"xmlsec": ["py.typed", "*.pyi"]}, ) diff --git a/tests/test_pkcs11.py b/tests/test_pkcs11.py index accd29ae..d6bafd79 100644 --- a/tests/test_pkcs11.py +++ b/tests/test_pkcs11.py @@ -1,3 +1,5 @@ +import pytest + import xmlsec from tests import base from xmlsec import constants as consts @@ -33,14 +35,15 @@ def test_sign_bad_args(self): ctx = xmlsec.SignatureContext() ctx.key = xmlsec.Key.from_engine(KEY_URL) with self.assertRaises(TypeError): - ctx.sign('') + ctx.sign("") def test_sign_fail(self): ctx = xmlsec.SignatureContext() ctx.key = xmlsec.Key.from_engine(KEY_URL) - with self.assertRaisesRegex(xmlsec.Error, 'failed to sign'): - ctx.sign(self.load_xml('sign1-in.xml')) + with self.assertRaisesRegex(xmlsec.Error, "failed to sign"): + ctx.sign(self.load_xml("sign1-in.xml")) + @pytest.mark.skip(reason="no key configured") def test_sign_case1(self): """Should sign a pre-constructed template file using a key from a pkcs11 engine.""" root = self.load_xml("sign1-in.xml") @@ -50,7 +53,7 @@ def test_sign_case1(self): ctx = xmlsec.SignatureContext() ctx.key = xmlsec.Key.from_engine(KEY_URL) self.assertIsNotNone(ctx.key) - ctx.key.name = 'rsakey.pem' + ctx.key.name = "rsakey.pem" self.assertEqual("rsakey.pem", ctx.key.name) ctx.sign(sign)