1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
import os
import sys
import time
import pytest
from jupyter_client.blocking.client import BlockingKernelClient
from .test_eventloop import qt_guis_avail
from .utils import assemble_output
# these tests don't seem to work with xvfb yet
# these tests seem to be a problem on CI in general
pytestmark = pytest.mark.skipif(
bool(os.getenv("CI")),
reason="tests not working yet reliably on CI",
)
guis = []
if not sys.platform.startswith("tk"):
guis.append("tk")
if qt_guis_avail:
guis.append("qt")
if sys.platform == "darwin":
guis.append("osx")
backends = {
"tk": "tkagg",
"qt": "qtagg",
"osx": "macosx",
}
def execute(
kc: BlockingKernelClient,
code: str,
timeout=120,
):
msg_id = kc.execute(code)
stdout, stderr = assemble_output(kc.get_iopub_msg, timeout=timeout, parent_msg_id=msg_id)
assert not stderr.strip()
return stdout.strip(), stderr.strip()
@pytest.mark.parametrize("gui", guis)
@pytest.mark.timeout(300)
def test_matplotlib_gui(kc, gui):
"""Make sure matplotlib activates and its eventloop runs while the kernel is also responsive"""
pytest.importorskip("matplotlib", reason="this test requires matplotlib")
stdout, stderr = execute(kc, f"%matplotlib {gui}")
assert not stderr
# debug: show output from invoking the matplotlib magic
print(stdout)
execute(
kc,
"""
from concurrent.futures import Future
import matplotlib as mpl
import matplotlib.pyplot as plt
""",
)
stdout, _ = execute(kc, "print(mpl.get_backend())")
assert stdout == backends[gui]
execute(
kc,
"""
fig, ax = plt.subplots()
timer = fig.canvas.new_timer(interval=10)
f = Future()
call_count = 0
def add_call():
global call_count
call_count += 1
if not f.done():
f.set_result(None)
timer.add_callback(add_call)
timer.start()
""",
)
# wait for the first call (up to 60 seconds)
deadline = time.monotonic() + 60
done = False
while time.monotonic() <= deadline:
stdout, _ = execute(kc, "print(f.done())")
if stdout.strip() == "True":
done = True
break
if stdout == "False":
time.sleep(0.1)
else:
pytest.fail(f"Unexpected output {stdout}")
if not done:
pytest.fail("future never finished...")
time.sleep(0.25)
stdout, _ = execute(kc, "print(call_count)")
call_count = int(stdout)
assert call_count > 0
time.sleep(0.25)
stdout, _ = execute(kc, "timer.stop()\nprint(call_count)")
call_count_2 = int(stdout)
assert call_count_2 > call_count
stdout, _ = execute(kc, "print(call_count)")
call_count_3 = int(stdout)
assert call_count_3 <= call_count_2 + 5
|