Skip to content

[WIP] Integrate testing to the Python wheels workflow #19600

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/cibuildwheel-impl/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,22 @@ inputs:
runs:
using: "composite"
steps:
- name: Install system dependencies
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y \
binutils cmake dpkg-dev g++ gcc libssl-dev git libx11-dev \
libxext-dev libxft-dev libxpm-dev python3 libtbb-dev libvdt-dev libgif-dev

- name: Build wheel
uses: pypa/[email protected]
env:
PIP_NO_CACHE_DIR: "1"
CIBW_BUILD: ${{ inputs.build-tag }}
CIBW_TEST_REQUIRES: "-r test_tutorials/requirements.txt"
CIBW_TEST_SOURCES: "test_tutorials"
CIBW_TEST_COMMAND: "pytest -v"

- name: Upload wheel
uses: actions/upload-artifact@v4
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/python_wheel_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
schedule:
- cron: '01 1 * * *'
pull_request:
types: [labeled]
types: [opened, synchronize, reopened, labeled]

jobs:
build-wheels:
Expand All @@ -21,6 +21,7 @@ jobs:
contains(github.event.pull_request.labels.*.name, 'build-python-wheels')
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: [cp38-manylinux_x86_64, cp39-manylinux_x86_64, cp310-manylinux_x86_64, cp311-manylinux_x86_64, cp312-manylinux_x86_64, cp313-manylinux_x86_64]
name: ${{ matrix.target }}
Expand Down
47 changes: 47 additions & 0 deletions test_tutorials/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ROOT requirements for third-party Python packages

# PyROOT: Interoperability with numpy arrays
numpy
pandas

# TMVA: SOFIE
# dm-sonnet # used for GNNs
# graph_nets
# onnx

# TMVA: PyMVA interfaces
# scikit-learn
# tensorflow ; python_version < "3.13" # TensorFlow doesn't support Python 3.13 yet
# torch
# xgboost

# PyROOT: ROOT.Numba.Declare decorator
numba>=0.48
cffi>=1.9.1

# Notebooks: ROOT C++ kernel
# IPython
# jupyter
# metakernel>=0.20.0
# notebook>=4.4.1

# Distributed RDataFrame
pyspark>=2.4 # Spark backend
dask>=2022.08.1 # Dask backend
distributed>=2022.08.1 # Dask backend

# JsMVA: Jupyter notebook magic for TMVA
# ipywidgets

# Unified Histogram Interface (UHI)
uhi
matplotlib
mplhep

# For testing
# nbconvert>=7.4.0
pytest
# setuptools

# Look for CPU-only versions of PyTorch to avoid pulling CUDA in the CI docker images.
# -f https://download.pytorch.org/whl/cpu/torch_stable.html
34 changes: 34 additions & 0 deletions test_tutorials/test_tutorials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import subprocess
import sys
import pathlib
import ROOT
import os
import pytest

Check failure on line 6 in test_tutorials/test_tutorials.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

test_tutorials/test_tutorials.py:1:1: I001 Import block is un-sorted or un-formatted

ROOT.gROOT.SetBatch(True)

tutorial_dir = pathlib.Path(str(ROOT.gROOT.GetTutorialDir()))
tutorials = list(tutorial_dir.rglob("*.py"))


def test_tutorials_are_detected():
assert len(tutorials) > 0

@pytest.mark.parametrize("tutorial", tutorials, ids=lambda p: p.name)
def test_tutorial(tutorial):
env = dict(**os.environ)
# force matplotlib to use a non-GUI backend
env["MPLBACKEND"] = "Agg"
try:
subprocess.run(
[sys.executable, str(tutorial)],
check=True,
env=env,
capture_output=True,
text=True
)
except subprocess.CalledProcessError as e:
# read stderr to see if EOFError occurred
if "EOFError" in e.stderr:
pytest.skip("Skipping tutorial that requires user input")
raise
Loading