feat: add built-in frozendict support for Python 3.15+
#2824
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build | |
| on: | |
| push: | |
| branches: | |
| - main # allow to trigger the workflow with tag push event | |
| pull_request: | |
| types: | |
| - labeled | |
| - unlabeled | |
| - opened | |
| - synchronize | |
| - reopened | |
| - ready_for_review | |
| paths: | |
| - setup.py | |
| - setup.cfg | |
| - pyproject.toml | |
| - MANIFEST.in | |
| - CMakeLists.txt | |
| - include/** | |
| - src/** | |
| - optree/version.py | |
| - .github/workflows/build.yml | |
| release: | |
| types: | |
| - published | |
| # Allow to trigger the workflow manually | |
| workflow_dispatch: | |
| inputs: | |
| task: | |
| description: "Task type" | |
| type: choice | |
| options: | |
| - build-only | |
| - build-and-publish | |
| required: true | |
| nightly-pybind11: | |
| description: "Use nightly pybind11" | |
| type: boolean | |
| required: false | |
| default: false | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: "${{ github.workflow }}-${{ github.ref }}" | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| env: | |
| OPTREE_CXX_WERROR: "OFF" | |
| _GLIBCXX_USE_CXX11_ABI: "1" | |
| PYTHONUNBUFFERED: "1" | |
| PYTHON_TAG: "py3" # to be updated | |
| PYTHON_VERSION: "3" # to be updated | |
| COLUMNS: "100" | |
| FORCE_COLOR: "1" | |
| CLICOLOR_FORCE: "1" | |
| ALLOW_PRERELEASES: "false" | |
| jobs: | |
| build-sdist: | |
| name: Build sdist | |
| if: | | |
| github.repository_owner == 'metaopt' && | |
| (github.event_name != 'push' || startsWith(github.ref, 'refs/tags/')) && | |
| (github.event_name != 'pull_request' || !github.event.pull_request.draft) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.9 - 3.15" | |
| update-environment: true | |
| - name: Upgrade pip | |
| run: python -m pip install --upgrade pip setuptools | |
| - name: Set __release__ | |
| if: | | |
| startsWith(github.ref, 'refs/tags/') || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.task == 'build-and-publish') | |
| run: python .github/workflows/set_release.py | |
| - name: Print version | |
| run: python setup.py --version | |
| - name: Use nightly pybind11 | |
| shell: bash | |
| if: | | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.nightly-pybind11 == 'true') || | |
| ( | |
| github.event_name == 'pull_request' && | |
| contains(github.event.pull_request.labels.*.name, 'test-with-nightly-pybind11') | |
| ) | |
| run: | | |
| python -m pip install --force-reinstall "$(python .github/workflows/set_setup_requires.py)" | |
| echo "::group::pyproject.toml" | |
| cat pyproject.toml | |
| echo "::endgroup::" | |
| - name: Install dependencies | |
| run: python -m pip install --upgrade pip setuptools wheel build | |
| - name: Build sdist | |
| run: python -m build --sdist | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: sdist | |
| path: dist/*.tar.gz | |
| if-no-files-found: error | |
| build-wheels: | |
| name: >- | |
| Build wheels for | |
| ${{ startsWith(matrix.python-version, 'pypy') && 'PyPy' || 'CPython' }} ${{ matrix.python-version }} | |
| on ${{ matrix.target.runner }} (${{ matrix.target.platform }} / ${{ matrix.target.archs }}) | |
| if: | | |
| github.repository_owner == 'metaopt' && | |
| (github.event_name != 'push' || startsWith(github.ref, 'refs/tags/')) && | |
| (github.event_name != 'pull_request' || !github.event.pull_request.draft) | |
| # https://docs.github.com/en/actions/reference/runners/github-hosted-runners | |
| runs-on: ${{ matrix.target.runner }} | |
| strategy: | |
| matrix: | |
| # Reference: https://cibuildwheel.pypa.io | |
| target: | |
| - { runner: ubuntu-latest, platform: linux, archs: "auto64" } | |
| - { runner: ubuntu-latest, platform: linux, archs: "auto32" } | |
| - { runner: ubuntu-24.04-arm, platform: linux, archs: "aarch64" } | |
| - { runner: ubuntu-latest, platform: linux, archs: "ppc64le" } | |
| - { runner: ubuntu-latest, platform: linux, archs: "s390x" } | |
| - { runner: ubuntu-latest, platform: linux, archs: "riscv64" } | |
| - { runner: macos-latest, platform: macos, archs: "auto64" } | |
| - { runner: macos-latest, platform: macos, archs: "x86_64" } | |
| - { runner: windows-latest, platform: windows, archs: "auto64" } | |
| - { runner: windows-latest, platform: windows, archs: "auto32" } | |
| - { runner: windows-11-arm, platform: windows, archs: "ARM64" } | |
| python-version: | |
| - "3.9" | |
| - "3.10" | |
| - "3.11" | |
| - "3.12" | |
| - "3.13" | |
| - "3.13t" | |
| - "3.14" | |
| - "3.14t" | |
| # - "3.15" | |
| # - "3.15t" | |
| - "pypy-3.11" | |
| exclude: | |
| # Exclude unsupported Python versions | |
| - python-version: "3.9" | |
| target: { archs: "ARM64" } | |
| - python-version: "3.10" | |
| target: { archs: "ARM64" } | |
| - python-version: "pypy-3.11" | |
| target: { archs: "auto32" } | |
| - python-version: "pypy-3.11" | |
| target: { archs: "ppc64le" } | |
| - python-version: "pypy-3.11" | |
| target: { archs: "s390x" } | |
| - python-version: "pypy-3.11" | |
| target: { archs: "riscv64" } | |
| - python-version: "pypy-3.11" | |
| target: { archs: "ARM64" } | |
| include: | |
| # iOS | |
| - python-version: "3.13" | |
| target: | |
| runner: macos-latest | |
| platform: ios | |
| archs: "arm64_iphoneos" | |
| - python-version: "3.14" | |
| target: | |
| runner: macos-latest | |
| platform: ios | |
| archs: "arm64_iphoneos" | |
| # - python-version: "3.15" | |
| # target: | |
| # runner: macos-latest | |
| # platform: ios | |
| # archs: "arm64_iphoneos" | |
| # iOS Simulator | |
| - python-version: "3.13" | |
| target: | |
| runner: macos-latest | |
| platform: ios | |
| archs: "arm64_iphonesimulator" | |
| - python-version: "3.14" | |
| target: | |
| runner: macos-latest | |
| platform: ios | |
| archs: "arm64_iphonesimulator" | |
| # - python-version: "3.15" | |
| # target: | |
| # runner: macos-latest | |
| # platform: ios | |
| # archs: "arm64_iphonesimulator" | |
| # Android | |
| - python-version: "3.13" | |
| target: | |
| runner: ubuntu-latest | |
| platform: android | |
| archs: "arm64_v8a" | |
| - python-version: "3.14" | |
| target: | |
| runner: ubuntu-latest | |
| platform: android | |
| archs: "arm64_v8a" | |
| # - python-version: "3.15" | |
| # target: | |
| # runner: ubuntu-latest | |
| # platform: android | |
| # archs: "arm64_v8a" | |
| # Pyodide | |
| - python-version: "3.12" | |
| target: | |
| runner: ubuntu-latest | |
| platform: pyodide | |
| archs: "wasm32" | |
| - python-version: "3.13" | |
| target: | |
| runner: ubuntu-latest | |
| platform: pyodide | |
| archs: "wasm32" | |
| fail-fast: false | |
| timeout-minutes: 180 | |
| steps: | |
| - name: Sanity check for variables | |
| shell: bash | |
| run: | | |
| if [[ '${{ env.ALLOW_PRERELEASES }}' != 'true' && | |
| '${{ env.ALLOW_PRERELEASES }}' != 'false' ]]; then | |
| echo '::error::Expect ALLOW_PRERELEASES ("${{ env.ALLOW_PRERELEASES }}") to be "true" or "false"' >&2 | |
| exit 1 | |
| fi | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Determine Python version | |
| shell: bash | |
| run: | | |
| PYTHON_VERSION="${{ matrix.python-version }}" | |
| PYTHON_VERSION="${PYTHON_VERSION%t}" | |
| echo "Using Python version: ${PYTHON_VERSION}" | |
| echo "PYTHON_VERSION=${PYTHON_VERSION}" | tee -a "${GITHUB_ENV}" | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| update-environment: true | |
| allow-prereleases: true | |
| - name: Set up Environment | |
| shell: bash | |
| run: | | |
| python -m pip install --upgrade pip setuptools | |
| if [[ "${{ runner.os }}" == 'macOS' ]]; then | |
| brew update --quiet --force | |
| brew list --formula cmake >/dev/null && brew uninstall --formula cmake || true | |
| brew install --formula cmake | |
| fi | |
| - name: Set __release__ | |
| if: | | |
| startsWith(github.ref, 'refs/tags/') || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.task == 'build-and-publish') | |
| run: python .github/workflows/set_release.py | |
| - name: Print version | |
| run: python setup.py --version | |
| - name: Use nightly pybind11 | |
| shell: bash | |
| if: | | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.nightly-pybind11 == 'true') || | |
| ( | |
| github.event_name == 'pull_request' && | |
| contains(github.event.pull_request.labels.*.name, 'test-with-nightly-pybind11') | |
| ) | |
| run: | | |
| python -m pip install --force-reinstall "$(python .github/workflows/set_setup_requires.py)" | |
| echo "::group::pyproject.toml" | |
| cat pyproject.toml | |
| echo "::endgroup::" | |
| - name: Set CIBW_BUILD | |
| shell: bash | |
| run: | | |
| set -x | |
| PYTHON_TAG="$( | |
| echo 'import sys; print( | |
| "{0.name[0]}p{1.major}{1.minor}".format( | |
| sys.implementation, | |
| sys.version_info, | |
| ).lower(), | |
| )' | python - | |
| )" | |
| if [[ "${{ matrix.python-version }}" == *"t" ]]; then | |
| PYTHON_TAG="${PYTHON_TAG}t" | |
| fi | |
| echo "PYTHON_TAG=${PYTHON_TAG}" | tee -a "${GITHUB_ENV}" | |
| echo "CIBW_BUILD=${PYTHON_TAG}-*" | tee -a "${GITHUB_ENV}" | |
| if [[ "${{ matrix.target.platform }}" == 'ios' && | |
| "${{ matrix.target.archs }}" == *simulator* ]]; then | |
| xcrun simctl shutdown all || true | |
| xcrun simctl delete unavailable || true | |
| xcrun simctl list devices >/dev/null || true | |
| xcodebuild -downloadPlatform iOS || true | |
| xcrun simctl list devices available || true | |
| fi | |
| - name: Set up QEMU | |
| if: runner.os == 'Linux' | |
| uses: docker/setup-qemu-action@v4 | |
| with: | |
| platforms: all | |
| - name: Build wheels | |
| uses: pypa/cibuildwheel@v3.4 | |
| env: | |
| CIBW_BUILD: ${{ env.CIBW_BUILD }} | |
| CIBW_PLATFORM: ${{ matrix.target.platform }} | |
| CIBW_ARCHS: ${{ matrix.target.archs }} | |
| CIBW_ENABLE: pypy cpython-freethreading${{ env.ALLOW_PRERELEASES == 'true' && ' cpython-prerelease' || '' }} | |
| CIBW_ALLOW_EMPTY: ${{ env.ALLOW_PRERELEASES == 'true' }} | |
| with: | |
| package-dir: . | |
| output-dir: wheelhouse | |
| config-file: "{package}/pyproject.toml" | |
| - name: Upload wheels | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: wheels-${{ env.PYTHON_TAG }}-${{ matrix.target.platform }}-${{ matrix.target.archs }} | |
| path: wheelhouse/*.whl | |
| if-no-files-found: ${{ env.ALLOW_PRERELEASES == 'true' && 'warn' || 'error' }} | |
| list-artifacts: | |
| name: List artifacts | |
| runs-on: ubuntu-latest | |
| needs: [build-sdist, build-wheels] | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Download built sdist | |
| uses: actions/download-artifact@v8 | |
| with: | |
| # unpacks default artifact into dist/ | |
| # if `name: artifact` is omitted, the action will create extra parent dir | |
| name: sdist | |
| path: dist | |
| - name: Download built wheels | |
| uses: actions/download-artifact@v8 | |
| with: | |
| pattern: wheels-* | |
| path: dist | |
| merge-multiple: true | |
| - name: List distributions | |
| run: ls -lh dist/* | |
| - name: Remove PyPI unsupported files | |
| run: rm -f dist/*wasm*.whl | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: artifacts | |
| path: dist/* | |
| if-no-files-found: error | |
| publish: | |
| name: Publish to PyPI | |
| runs-on: ubuntu-latest | |
| needs: [list-artifacts] | |
| if: | | |
| github.repository_owner == 'metaopt' && | |
| github.event_name != 'pull_request' && | |
| (github.event_name != 'workflow_dispatch' || github.event.inputs.task == 'build-and-publish') && | |
| (github.event_name != 'push' || startsWith(github.ref, 'refs/tags/')) | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.9 - 3.15" | |
| update-environment: true | |
| - name: Upgrade pip | |
| run: python -m pip install --upgrade pip setuptools | |
| - name: Set __release__ | |
| if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' | |
| run: python .github/workflows/set_release.py | |
| - name: Print version | |
| run: python setup.py --version | |
| - name: Check consistency between the package version and release tag | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: | | |
| PACKAGE_VER="v$(python setup.py --version)" | |
| RELEASE_TAG="${GITHUB_REF#refs/*/}" | |
| if [[ "${PACKAGE_VER}" != "${RELEASE_TAG}" ]]; then | |
| echo "::error::package ver. (${PACKAGE_VER}) != release tag. (${RELEASE_TAG})" >&2 | |
| exit 1 | |
| fi | |
| - name: Download built artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| # unpacks default artifact into dist/ | |
| # if `name: artifact` is omitted, the action will create extra parent dir | |
| name: artifacts | |
| path: dist | |
| - name: List distributions | |
| run: ls -lh dist/* | |
| - name: Publish to TestPyPI | |
| if: | | |
| (startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch') && | |
| env.ALLOW_PRERELEASES == 'false' | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| user: __token__ | |
| password: ${{ secrets.TESTPYPI_UPLOAD_TOKEN }} | |
| repository-url: https://test.pypi.org/legacy/ | |
| verbose: true | |
| print-hash: true | |
| skip-existing: true | |
| - name: Publish to PyPI | |
| if: | | |
| (startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch') && | |
| env.ALLOW_PRERELEASES == 'false' | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| user: __token__ | |
| password: ${{ secrets.PYPI_UPLOAD_TOKEN }} | |
| verbose: true | |
| print-hash: true | |
| skip-existing: true |