numpy 0.18.0

PyO3-based Rust bindings of the NumPy C-API
Documentation
name: CI

on:
  push:
    branches:
      - main
      - release-*
  pull_request:

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

jobs:

  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy
      - uses: Swatinem/rust-cache@v2
        continue-on-error: true
      - run: ./x.py check

  test:
    name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }}
    runs-on: ${{ matrix.platform.os }}
    needs: [lint, check-msrv, examples]
    strategy:
      fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }}
      matrix:
        python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
        platform: [
          { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu" },
          { os: "macOS-latest",   python-architecture: "x64", rust-target: "x86_64-apple-darwin" },
          { os: "windows-latest", python-architecture: "x64", rust-target: "x86_64-pc-windows-msvc" },
          { os: "windows-latest", python-architecture: "x86", rust-target: "i686-pc-windows-msvc" },
        ]
        include:
          # NumPy does not provide pre-built wheels for PyPy on macOS and Windows
          - python-version: pypy-3.7
            platform: { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu" }
          - python-version: pypy-3.8
            platform: { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu" }
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
          architecture: ${{ matrix.platform.python-architecture }}
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.platform.rust-target }}
      - name: Install toml
        run: pip install toml
      - name: Edit Cargo.toml and enable new resolver
        run: |
          import toml
          cargo_toml = toml.load("Cargo.toml")
          cargo_toml["package"]["resolver"] = "2"
          with open("Cargo.toml", "w") as f:
            toml.dump(cargo_toml, f)
        shell: python
      - name: Test
        run: |
            pip install numpy
            cargo test --all-features
        # Not on PyPy, because no embedding API
        if: ${{ !startsWith(matrix.python-version, 'pypy') }}
      - name: Test example
        run: |
          pip install nox
          nox -f examples/simple/noxfile.py
    env:
      CARGO_TERM_VERBOSE: true
      CARGO_BUILD_TARGET: ${{ matrix.platform.rust-target }}
      RUST_BACKTRACE: 1

  cross-build:
    runs-on: ubuntu-latest
    needs: [lint, check-msrv, examples]
    steps:
      - uses: actions/checkout@v3
      - uses: messense/maturin-action@v1
        with:
          target: aarch64
          manylinux: auto
          args: --manifest-path examples/simple/Cargo.toml

  valgrind:
    runs-on: ubuntu-22.04
    needs: [lint, check-msrv, examples]
    steps:
      - uses: actions/checkout@v3
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
        continue-on-error: true
      - uses: taiki-e/install-action@valgrind
      - run: |
            pip install numpy
            cargo test --all-features --release
        env:
          CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: valgrind --leak-check=no --error-exitcode=1

  careful:
    runs-on: ubuntu-latest
    needs: [lint, check-msrv, examples]
    steps:
      - uses: actions/checkout@v3
      - uses: dtolnay/rust-toolchain@nightly
      - uses: Swatinem/rust-cache@v2
        continue-on-error: true
      - run: |
            pip install numpy
            cargo install --locked cargo-careful
            cargo careful test --all-features

  check-msrv:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: 3.8
      - name: Install Rust
        uses: dtolnay/rust-toolchain@1.48.0
      - uses: Swatinem/rust-cache@v2
        with:
          workspaces: examples/simple
        continue-on-error: true
      - name: Install toml
        run: pip install toml
      - name: Edit Cargo.toml
        run: |
          import toml
          cargo_toml = toml.load("Cargo.toml")
          cargo_toml["dependencies"]["ndarray"] = "0.13.1"
          cargo_toml["dependencies"]["parking_lot"] = "0.11.2"
          cargo_toml["dependencies"]["num-complex"] = "0.2.4"
          cargo_toml["dependencies"]["once_cell"] = "1.14.0"
          with open("Cargo.toml", "w") as f:
            toml.dump(cargo_toml, f)
        working-directory: examples/simple
        shell: python
      - name: Generate lockfile
        run: cargo generate-lockfile
        working-directory: examples/simple
      - name: Unify dependencies to MSRV-compatible versions
        run: |
          import toml
          import subprocess
          cargo_lock = toml.load("Cargo.lock")
          for pkg in cargo_lock["package"]:
            pkg_id = pkg["name"] + ":" + pkg["version"]
            if pkg["name"] == "ndarray" and pkg["version"] != "0.13.1":
              subprocess.run(["cargo", "update", "--package", pkg_id, "--precise", "0.13.1"], check=True)
            elif pkg["name"] == "parking_lot" and pkg["version"] != "0.11.2":
              subprocess.run(["cargo", "update", "--package", pkg_id, "--precise", "0.11.2"], check=True)
            elif pkg["name"] == "once_cell" and pkg["version"] != "1.14.0":
              subprocess.run(["cargo", "update", "--package", pkg_id, "--precise", "1.14.0"], check=True)
        working-directory: examples/simple
        shell: python
      - name: Test example
        run: |
          pip install nox
          nox -f examples/simple/noxfile.py

  examples:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: 3.8
      - name: Install OpenBLAS
        run: sudo apt install --yes libopenblas-dev
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
        continue-on-error: true
      - name: Test examples
        run: |
          pip install nox
          nox -f examples/linalg/noxfile.py
          nox -f examples/parallel/noxfile.py

  coverage:
    runs-on: ubuntu-latest
    needs: [lint, check-msrv, examples]
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: 3.9
          architecture: x64
      - name: Install numpy
        run: pip install numpy
      - uses: Swatinem/rust-cache@v2
        continue-on-error: true
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: llvm-tools-preview
      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@cargo-llvm-cov
      - name: Generate code coverage
        run: cargo llvm-cov --all-features --lcov --output-path coverage.lcov
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v2
        with:
          file: coverage.lcov
          fail_ci_if_error: true