Skip to content

Commit a04d4e6

Browse files
add notebook_vars utility with example notebook and unit test depicting how it can be ised to construct a pytest fixture with the notebook state after execution (#39)
Co-authored-by: Sylwester Arabas <[email protected]>
1 parent 5a12ee2 commit a04d4e6

File tree

8 files changed

+94
-1
lines changed

8 files changed

+94
-1
lines changed

.github/workflows/pylint.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: Install dependencies
2121
run: |
2222
python -m pip install --upgrade pip setuptools
23-
pip install pylint
23+
pip install pylint pytest
2424
python setup.py egg_info
2525
pip install -r *.egg-info/requires.txt
2626
- name: Analysing the code with pylint

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ Utility routines used in Jupyter notebooks in [PySDM](https://github.com/open-at
1010
- [``show_anim()``](https://open-atmos.github.io/jupyter-utils/open_atmos_jupyter_utils/show_anim.html) - a replacement for matplotlib's FuncAnimate() that inline-displays animations in gif format (thus github renderer compatible) and offers a way to download the .gif file (on Colab the widget triggers Google Drive download)
1111
- [``TemporaryFile``](https://open-atmos.github.io/jupyter-utils/open_atmos_jupyter_utils/temporary_file.html) - a class equipped with ``make_link_widget()`` method returning a click-to-download Colab-compatible widget to be display()-ed in a Jupyter notebook
1212
- [``pip_install_on_colab('package_a', 'package_b', ...)``](https://open-atmos.github.io/jupyter-utils/open_atmos_jupyter_utils/pip_install_on_colab.html) - a function handling execution of ``pip`` (and ``ldconfig``) on Colab
13+
- [``notebook_vars``](https://open-atmos.github.io/jupyter-utils/open_atmos_jupyter_utils/notebook_vars) - a function that executes Jupyter notebook and returns a dictionary with all variables notebook variables (variable names as keys) - useful in setting up automated tests for notebooks without modifying the notebooks (e.g., using pytest fixtures)
1314

1415
public API docs are maintained at: https://open-atmos.github.io/jupyter-utils/

examples/__init__.py

Whitespace-only changes.

examples/notebook_vars_example.ipynb

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"id": "51913260-f89a-4237-bc7b-af5a0b1785f9",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"a = 44\n",
11+
"b = 666\n",
12+
"c = a + b"
13+
]
14+
}
15+
],
16+
"metadata": {
17+
"kernelspec": {
18+
"display_name": "Python 3 (ipykernel)",
19+
"language": "python",
20+
"name": "python3"
21+
},
22+
"language_info": {
23+
"codemirror_mode": {
24+
"name": "ipython",
25+
"version": 3
26+
},
27+
"file_extension": ".py",
28+
"mimetype": "text/x-python",
29+
"name": "python",
30+
"nbconvert_exporter": "python",
31+
"pygments_lexer": "ipython3",
32+
"version": "3.12.7"
33+
}
34+
},
35+
"nbformat": 4,
36+
"nbformat_minor": 5
37+
}

open_atmos_jupyter_utils/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
from open_atmos_jupyter_utils.temporary_file import TemporaryFile
66
from open_atmos_jupyter_utils.show_plot import show_plot, save_and_make_link
77
from open_atmos_jupyter_utils.show_anim import show_anim
8+
from open_atmos_jupyter_utils.notebook_vars import notebook_vars
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
""" helper routines for use in smoke tests """
2+
3+
from pathlib import Path
4+
5+
import nbformat
6+
7+
8+
def notebook_vars(file: Path, plot: bool):
9+
"""Executes the code from all cells of the Jupyter notebook `file` and
10+
returns a dictionary with the notebook variables. If the `plot` argument
11+
is set to `True`, any code line within the notebook starting with `show_plot(`
12+
(see [open_atmos_jupyter_utils docs](https://pypi.org/p/open_atmos_jupyter_utils))
13+
is replaced with `pyplot.show() #`, otherwise it is replaced with `pyplot.gca().clear() #`
14+
to match the smoke-test conventions."""
15+
notebook = nbformat.read(file, nbformat.NO_CONVERT)
16+
context = {}
17+
for cell in notebook.cells:
18+
if cell.cell_type != "markdown":
19+
lines = cell.source.splitlines()
20+
for i, line in enumerate(lines):
21+
if line.strip().startswith("!"):
22+
lines[i] = line.replace("!", "pass #")
23+
if line.strip().startswith("show_plot("):
24+
lines[i] = line.replace(
25+
"show_plot(",
26+
"from matplotlib import pyplot; "
27+
+ ("pyplot.show() #" if plot else "pyplot.gca().clear() #"),
28+
)
29+
30+
exec("\n".join(lines), context) # pylint: disable=exec-used
31+
return context

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dependencies = [
1818
"IPython",
1919
"matplotlib",
2020
"imageio",
21+
"nbformat"
2122
]
2223
[project.urls]
2324
"Homepage" = "https://github.com/open-atmos/jupyter-utils"

tests/test_notebook_vars.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""
2+
test checking notebook_vars function
3+
"""
4+
5+
from pathlib import Path
6+
import pytest
7+
8+
from open_atmos_jupyter_utils import notebook_vars
9+
import examples
10+
11+
@pytest.fixture(scope="session", name="notebook_variables")
12+
def notebook_variables_fixture():
13+
"""returns variables from the notebook """
14+
print(examples.__file__)
15+
return notebook_vars(
16+
file=Path(examples.__file__).parent / "notebook_vars_example.ipynb",
17+
plot=False,
18+
)
19+
20+
def test_notebook_vars(notebook_variables):
21+
""" checks for a value known only after notebook execution"""
22+
assert notebook_variables["c"] == notebook_variables["a"] + notebook_variables["b"]

0 commit comments

Comments
 (0)