Skip to content
Merged
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
16 changes: 11 additions & 5 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Set up dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools build cython pytest pytest-skip-slow wheel lxml numpy scipy
pip install setuptools build cython pytest pytest-skip-slow wheel lxml numpy scipy nbformat nbclient ipykernel
- name: Build source distribution
run:
python -m build
Expand All @@ -38,7 +38,13 @@ jobs:
cd dist
pip install -v pygambit*.tar.gz
- name: Run tests
run: pytest
run: |
if [ "${{ matrix.python-version }}" = "3.9" ]; then
# Python 3.9 on linux skips the notebook execution test (notebooks may require newer kernels/deps)
pytest -q -k 'not test_execute_notebook'
else
pytest
fi

macos-13:
runs-on: macos-13
Expand All @@ -56,7 +62,7 @@ jobs:
- name: Set up dependencies
run: |
python -m pip install --upgrade pip
pip install cython pytest pytest-skip-slow wheel lxml numpy scipy
pip install cython pytest pytest-skip-slow wheel lxml numpy scipy nbformat nbclient ipykernel
- name: Build extension
run: |
python -m pip install -v .
Expand All @@ -79,7 +85,7 @@ jobs:
- name: Set up dependencies
run: |
python -m pip install --upgrade pip
pip install cython pytest pytest-skip-slow wheel lxml numpy scipy
pip install cython pytest pytest-skip-slow wheel lxml numpy scipy nbformat nbclient ipykernel
- name: Build extension
run: |
python -m pip install -v .
Expand All @@ -102,7 +108,7 @@ jobs:
- name: Set up dependencies
run: |
python -m pip install --upgrade pip
pip install cython pytest pytest-skip-slow wheel lxml numpy scipy
pip install cython pytest pytest-skip-slow wheel lxml numpy scipy nbformat nbclient ipykernel
- name: Build extension
run: |
python -m pip install -v .
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorials/running_locally.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ How to run PyGambit tutorials on your computer
==============================================

The PyGambit tutorials are available as Jupyter notebooks and can be run interactively using any program that supports Jupyter notebooks, such as JupyterLab or VSCode.
You will need a working installation of Python 3 (tested with 3.9 and later) on your machine.
You will need a working installation of Python 3.9+ on your machine to run PyGambit (however the tutorials contain some syntax that may not be compatible with earlier versions of Python than 3.13).

1. To download the tutorials, open your OS's command prompt and clone the Gambit repository from GitHub, then navigate to the tutorials directory: ::

Expand Down
55 changes: 55 additions & 0 deletions tests/test_tutorials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import contextlib
from pathlib import Path

import nbformat
import pytest
from nbclient import NotebookClient
from nbclient.exceptions import CellExecutionError


def _find_tutorial_notebooks():
"""Return a sorted list of notebook Paths under doc/tutorials.

Skips the entire module if the tutorials directory does not exist.
"""
root = Path(__file__).resolve().parents[1] / "doc" / "tutorials"
if not root.exists():
pytest.skip(f"Tutorials folder not found: {root}")
notebooks = sorted(root.rglob("*.ipynb"))
if not notebooks:
pytest.skip(f"No tutorial notebooks found in: {root}")
return notebooks


# Discover notebooks at import time so pytest can parametrize them.
_NOTEBOOKS = _find_tutorial_notebooks()


@pytest.mark.parametrize("nb_path", _NOTEBOOKS, ids=[p.name for p in _NOTEBOOKS])
def test_execute_notebook(nb_path):
"""Execute a single Jupyter notebook and fail if any cell errors occur.

This uses nbclient.NotebookClient to run the notebook in its parent directory
so relative paths within the notebook resolve correctly.
"""
nb = nbformat.read(str(nb_path), as_version=4)

# Prefer the notebook's kernelspec if provided, otherwise let nbclient pick the default.
kernel_name = nb.metadata.get("kernelspec", {}).get("name")

client = NotebookClient(
nb,
timeout=600,
kernel_name=kernel_name,
resources={"metadata": {"path": str(nb_path.parent)}},
)

try:
client.execute()
except CellExecutionError as exc:
# Re-raise with more context so pytest shows which notebook failed.
raise AssertionError(f"Error while executing notebook {nb_path}: {exc}") from exc
finally:
# Ensure kernel is shut down.
with contextlib.suppress(Exception):
client.shutdown_kernel()
38 changes: 0 additions & 38 deletions tests/test_userguide.py

This file was deleted.

Loading