ci: run checks for all platforms on PR

This commit is contained in:
David Hewitt 2022-12-24 19:17:25 +00:00
parent b2906cf678
commit 710c895d01
6 changed files with 188 additions and 60 deletions

View file

@ -35,50 +35,82 @@ jobs:
run: nox -s fmt-rust run: nox -s fmt-rust
clippy: clippy:
if: github.ref != 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- run: pip install nox
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- run: nox -s clippy
check-target:
needs: [fmt] needs: [fmt]
runs-on: ubuntu-latest runs-on: ${{ matrix.platform.os }}
if: ${{ github.event_name != 'pull_request' && github.ref != 'refs/heads/main' }} if: github.ref != 'refs/heads/main'
strategy: strategy:
# If one platform fails, allow the rest to keep testing if `CI-no-fail-fast` label is present # If one platform fails, allow the rest to keep testing if `CI-no-fail-fast` label is present
fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }} fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }}
matrix: matrix:
target: [powerpc64le-unknown-linux-gnu, s390x-unknown-linux-gnu, wasm32-wasi] rust: [stable]
name: check-${{ matrix.target }} platform: [
{
os: "macos-latest",
python-architecture: "x64",
rust-target: "x86_64-apple-darwin",
},
{
os: "ubuntu-latest",
python-architecture: "x64",
rust-target: "x86_64-unknown-linux-gnu",
},
{
os: "ubuntu-latest",
python-architecture: "x64",
rust-target: "powerpc64le-unknown-linux-gnu",
},
{
os: "ubuntu-latest",
python-architecture: "x64",
rust-target: "s390x-unknown-linux-gnu",
},
{
os: "ubuntu-latest",
python-architecture: "x64",
rust-target: "wasm32-wasi",
},
{
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:
- rust: 1.48.0
python-version: "3.11"
platform:
{
os: "ubuntu-latest",
python-architecture: "x64",
rust-target: "x86_64-unknown-linux-gnu",
}
msrv: "MSRV"
name: clippy/${{ matrix.platform.rust-target }}/${{ matrix.rust }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install Rust toolchain - uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@stable
with: with:
targets: ${{ matrix.target }} toolchain: ${{ matrix.rust }}
- name: Run cargo checks targets: ${{ matrix.rust-target }}
run: | components: clippy
set -x - uses: actions/setup-python@v4
VERSIONS=("3.7" "3.8" "3.9" "3.10" "3.11") with:
for VERSION in ${VERSIONS[@]}; do architecture: ${{ matrix.platform.python-architecture }}
echo "version=$VERSION" > config.txt - run: python -m pip install nox
echo "suppress_build_script_link_lines=true" >> config.txt - if: matrix.msrv == 'MSRV'
PYO3_BUILD_CONFIG=$(pwd)/config.txt cargo check --all-targets --no-default-features name: Prepare minimal package versions (MSRV only)
PYO3_BUILD_CONFIG=$(pwd)/config.txt cargo check --all-targets --no-default-features --features "abi3" run: nox -s set-minimal-package-versions
PYO3_BUILD_CONFIG=$(pwd)/config.txt cargo check --all-targets --features "full multiple-pymethods" - run: nox -s clippy-all
PYO3_BUILD_CONFIG=$(pwd)/config.txt cargo check --all-targets --features "abi3 full multiple-pymethods"
done
build-pr: build-pr:
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} rust-${{ matrix.rust }} name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} rust-${{ matrix.rust }}
needs: [fmt] # don't wait for clippy as fails rarely and takes longer needs: [fmt]
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
with: with:
os: ${{ matrix.platform.os }} os: ${{ matrix.platform.os }}
@ -114,12 +146,16 @@ jobs:
python-architecture: "x64", python-architecture: "x64",
rust-target: "x86_64-pc-windows-msvc", rust-target: "x86_64-pc-windows-msvc",
}, },
{
os: "windows-latest",
python-architecture: "x86",
rust-target: "i686-pc-windows-msvc",
}
] ]
build-full: build-full:
if: ${{ github.event_name != 'pull_request' && github.ref != 'refs/heads/main' }} if: ${{ github.event_name != 'pull_request' && github.ref != 'refs/heads/main' }}
name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} rust-${{ matrix.rust }} name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} rust-${{ matrix.rust }}
needs: [fmt] # don't wait for clippy as fails rarely and takes longer needs: [fmt]
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
with: with:
os: ${{ matrix.platform.os }} os: ${{ matrix.platform.os }}
@ -317,7 +353,6 @@ jobs:
needs: needs:
- fmt - fmt
- clippy - clippy
- check-target
- build-pr - build-pr
- build-full - build-full
- valgrind - valgrind

View file

@ -2,11 +2,9 @@ use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::{intern, prepare_freethreaded_python}; use pyo3::intern;
fn getattr_direct(b: &mut Bencher<'_>) { fn getattr_direct(b: &mut Bencher<'_>) {
prepare_freethreaded_python();
Python::with_gil(|py| { Python::with_gil(|py| {
let sys = py.import("sys").unwrap(); let sys = py.import("sys").unwrap();
@ -15,8 +13,6 @@ fn getattr_direct(b: &mut Bencher<'_>) {
} }
fn getattr_intern(b: &mut Bencher<'_>) { fn getattr_intern(b: &mut Bencher<'_>) {
prepare_freethreaded_python();
Python::with_gil(|py| { Python::with_gil(|py| {
let sys = py.import("sys").unwrap(); let sys = py.import("sys").unwrap();

View file

@ -37,7 +37,7 @@ fn tuple_get_item(b: &mut Bencher<'_>) {
}); });
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(any(Py_LIMITED_API, PyPy)))]
fn tuple_get_item_unchecked(b: &mut Bencher<'_>) { fn tuple_get_item_unchecked(b: &mut Bencher<'_>) {
Python::with_gil(|py| { Python::with_gil(|py| {
const LEN: usize = 50_000; const LEN: usize = 50_000;
@ -57,7 +57,7 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("iter_tuple", iter_tuple); c.bench_function("iter_tuple", iter_tuple);
c.bench_function("tuple_new", tuple_new); c.bench_function("tuple_new", tuple_new);
c.bench_function("tuple_get_item", tuple_get_item); c.bench_function("tuple_get_item", tuple_get_item);
#[cfg(not(Py_LIMITED_API))] #[cfg(not(any(Py_LIMITED_API, PyPy)))]
c.bench_function("tuple_get_item_unchecked", tuple_get_item_unchecked); c.bench_function("tuple_get_item_unchecked", tuple_get_item_unchecked);
} }

View file

@ -0,0 +1 @@
Add `PyList::get_item_unchecked` for PyPy.

View file

@ -5,9 +5,10 @@ import subprocess
import sys import sys
import tempfile import tempfile
import time import time
from functools import lru_cache
from glob import glob from glob import glob
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional, Tuple
import nox import nox
@ -15,6 +16,8 @@ nox.options.sessions = ["test", "clippy", "fmt"]
PYO3_DIR = Path(__file__).parent PYO3_DIR = Path(__file__).parent
PY_VERSIONS = ("3.7", "3.8", "3.9", "3.10", "3.11")
PYPY_VERSIONS = ("3.7", "3.8", "3.9")
@nox.session(venv_backend="none") @nox.session(venv_backend="none")
@ -83,20 +86,71 @@ def fmt_py(session: nox.Session):
_run(session, "black", ".", "--check") _run(session, "black", ".", "--check")
@nox.session(venv_backend="none") @nox.session(name="clippy", venv_backend="none")
def clippy(session: nox.Session) -> None: def clippy(session: nox.Session) -> bool:
for feature_set in ["full", "abi3 full"]: if not _clippy(session):
session.error("one or more jobs failed")
def _clippy(session: nox.Session, *, env: Dict[str, str] = None) -> bool:
success = True
env = env or os.environ
for feature_set in _get_feature_sets():
command = "clippy"
extra = ("--", "--deny=warnings")
if _get_rust_version()[:2] == (1, 48):
# 1.48 crashes during clippy because of lints requested
# in .cargo/config
command = "check"
extra = ()
try:
_run( _run(
session, session,
"cargo", "cargo",
"clippy", command,
f"--features={feature_set}", *feature_set,
"--all-targets", "--all-targets",
"--workspace", "--workspace",
"--", *extra,
"--deny=warnings",
external=True, external=True,
env=env,
) )
except Exception:
success = False
return success
@nox.session(name="clippy-all", venv_backend="none")
def clippy_all(session: nox.Session) -> None:
success = True
with tempfile.NamedTemporaryFile("r+") as config:
env = os.environ.copy()
env["PYO3_CONFIG_FILE"] = config.name
env["PYO3_CI"] = "1"
def _clippy_with_config(implementation, version) -> bool:
config.seek(0)
config.truncate(0)
config.write(
f"""\
implementation={implementation}
version={version}
suppress_build_script_link_lines=true
"""
)
config.flush()
session.log(f"{implementation} {version}")
return _clippy(session, env=env)
for version in PY_VERSIONS:
success &= _clippy_with_config("CPython", version)
for version in PYPY_VERSIONS:
success &= _clippy_with_config("PyPy", version)
if not success:
session.error("one or more jobs failed")
@nox.session(venv_backend="none") @nox.session(venv_backend="none")
@ -396,14 +450,56 @@ def set_minimal_package_versions(session: nox.Session):
_run(session, "cargo", "metadata", silent=True, external=True) _run(session, "cargo", "metadata", silent=True, external=True)
def _get_rust_target() -> str: @lru_cache()
def _get_rust_info() -> Tuple[str, ...]:
output = _get_output("rustc", "-vV") output = _get_output("rustc", "-vV")
for line in output.splitlines(): return tuple(output.splitlines())
def _get_rust_version() -> Tuple[int, int, int, List[str]]:
for line in _get_rust_info():
if line.startswith(_RELEASE_LINE_START):
version = line[len(_RELEASE_LINE_START) :].strip()
# e.g. 1.67.0-beta.2
(version_number, *extra) = version.split("-", maxsplit=1)
return (*map(int, version_number.split(".")), extra)
def _get_rust_target() -> str:
for line in _get_rust_info():
if line.startswith(_HOST_LINE_START): if line.startswith(_HOST_LINE_START):
return line[len(_HOST_LINE_START) :].strip() return line[len(_HOST_LINE_START) :].strip()
@lru_cache()
def _get_feature_sets() -> Tuple[Tuple[str, ...], ...]:
"""Returns feature sets to use for clippy job"""
rust_version = _get_rust_version()
if rust_version[:2] >= (1, 62):
# multiple-pymethods feature not supported before 1.62
return (
("--no-default-features",),
(
"--no-default-features",
"--features=abi3",
),
("--features=full multiple-pymethods",),
("--features=abi3 full multiple-pymethods",),
)
else:
return (
("--no-default-features",),
(
"--no-default-features",
"--features=abi3",
),
("--features=full",),
("--features=abi3 full",),
)
_RELEASE_LINE_START = "release: "
_HOST_LINE_START = "host: " _HOST_LINE_START = "host: "

View file

@ -142,7 +142,7 @@ impl PyList {
/// # Safety /// # Safety
/// ///
/// Caller must verify that the index is within the bounds of the list. /// Caller must verify that the index is within the bounds of the list.
#[cfg(not(any(Py_LIMITED_API, PyPy)))] #[cfg(not(Py_LIMITED_API))]
pub unsafe fn get_item_unchecked(&self, index: usize) -> &PyAny { pub unsafe fn get_item_unchecked(&self, index: usize) -> &PyAny {
let item = ffi::PyList_GET_ITEM(self.as_ptr(), index as Py_ssize_t); let item = ffi::PyList_GET_ITEM(self.as_ptr(), index as Py_ssize_t);
// PyList_GET_ITEM return borrowed ptr; must make owned for safety (see #890). // PyList_GET_ITEM return borrowed ptr; must make owned for safety (see #890).