|
5 | 5 | import json |
6 | 6 | import os |
7 | 7 | import platform |
| 8 | +import re |
8 | 9 | import signal |
9 | 10 | import subprocess |
10 | 11 | import sys |
|
16 | 17 |
|
17 | 18 | import pytest |
18 | 19 |
|
19 | | -import matplotlib as mpl |
20 | 20 | from matplotlib import _c_internal_utils |
21 | 21 | from matplotlib.backend_tools import ToolToggleBase |
22 | 22 | from matplotlib.testing import subprocess_run_helper as _run_helper, is_ci_environment |
@@ -46,7 +46,7 @@ def wait_for(self, terminator): |
46 | 46 | f'Subprocess died before emitting expected {terminator!r}') |
47 | 47 | buf += c |
48 | 48 | if buf.endswith(terminator): |
49 | | - return |
| 49 | + return buf |
50 | 50 |
|
51 | 51 |
|
52 | 52 | # Minimal smoke-testing of the backends for which the dependencies are |
@@ -160,7 +160,6 @@ def _test_interactive_impl(): |
160 | 160 | from matplotlib.backend_bases import KeyEvent, FigureCanvasBase |
161 | 161 | mpl.rcParams.update({ |
162 | 162 | "webagg.open_in_browser": False, |
163 | | - "webagg.port_retries": 1, |
164 | 163 | }) |
165 | 164 |
|
166 | 165 | mpl.rcParams.update(json.loads(sys.argv[1])) |
@@ -484,32 +483,32 @@ def test_cross_Qt_imports(host, mpl): |
484 | 483 | @pytest.mark.skipif(sys.platform == "win32", reason="Cannot send SIGINT on Windows.") |
485 | 484 | def test_webagg(): |
486 | 485 | pytest.importorskip("tornado") |
487 | | - proc = subprocess.Popen( |
488 | | - [sys.executable, "-c", |
489 | | - inspect.getsource(_test_interactive_impl) |
490 | | - + "\n_test_interactive_impl()", "{}"], |
491 | | - env={**os.environ, "MPLBACKEND": "webagg", "SOURCE_DATE_EPOCH": "0"}) |
492 | | - url = f'http://{mpl.rcParams["webagg.address"]}:{mpl.rcParams["webagg.port"]}' |
493 | | - timeout = time.perf_counter() + _test_timeout |
494 | | - try: |
495 | | - while True: |
496 | | - try: |
497 | | - retcode = proc.poll() |
498 | | - # check that the subprocess for the server is not dead |
499 | | - assert retcode is None |
500 | | - conn = urllib.request.urlopen(url) |
501 | | - break |
502 | | - except urllib.error.URLError: |
503 | | - if time.perf_counter() > timeout: |
504 | | - pytest.fail("Failed to connect to the webagg server.") |
505 | | - else: |
506 | | - continue |
507 | | - conn.close() |
508 | | - proc.send_signal(signal.SIGINT) |
509 | | - assert proc.wait(timeout=_test_timeout) == 0 |
510 | | - finally: |
511 | | - if proc.poll() is None: |
512 | | - proc.kill() |
| 486 | + source = (inspect.getsource(_test_interactive_impl) + |
| 487 | + "\n_test_interactive_impl()") |
| 488 | + rc = '{"backend": "webagg"}' |
| 489 | + with _WaitForStringPopen([sys.executable, "-c", source, rc]) as proc: |
| 490 | + try: |
| 491 | + buf = proc.wait_for('Press Ctrl+C') |
| 492 | + url = re.search(r'visit (https?:\/\/\S+)', buf).group(1) |
| 493 | + timeout = time.perf_counter() + _test_timeout |
| 494 | + while True: |
| 495 | + try: |
| 496 | + retcode = proc.poll() |
| 497 | + # check that the subprocess for the server is not dead |
| 498 | + assert retcode is None |
| 499 | + with urllib.request.urlopen(url): |
| 500 | + # Do nothing; we've just confirmed that we can connect. |
| 501 | + break |
| 502 | + except urllib.error.URLError: |
| 503 | + if time.perf_counter() > timeout: |
| 504 | + pytest.fail("Failed to connect to the webagg server.") |
| 505 | + else: |
| 506 | + continue |
| 507 | + proc.send_signal(signal.SIGINT) |
| 508 | + assert proc.wait(timeout=_test_timeout) == 0 |
| 509 | + finally: |
| 510 | + if proc.poll() is None: |
| 511 | + proc.kill() |
513 | 512 |
|
514 | 513 |
|
515 | 514 | def _lazy_headless(): |
@@ -737,18 +736,17 @@ def test_sigint(env, target, kwargs): |
737 | 736 | backend = env.get("MPLBACKEND") |
738 | 737 | if not backend.startswith(("qt", "macosx")): |
739 | 738 | pytest.skip("SIGINT currently only tested on qt and macosx") |
740 | | - proc = _WaitForStringPopen( |
741 | | - [sys.executable, "-c", |
742 | | - inspect.getsource(_test_sigint_impl) + |
743 | | - f"\n_test_sigint_impl({backend!r}, {target!r}, {kwargs!r})"]) |
744 | | - try: |
745 | | - proc.wait_for('DRAW') |
746 | | - stdout, _ = proc.communicate(timeout=_test_timeout) |
747 | | - except Exception: |
748 | | - proc.kill() |
749 | | - stdout, _ = proc.communicate() |
750 | | - raise |
751 | | - assert 'SUCCESS' in stdout |
| 739 | + source = (inspect.getsource(_test_sigint_impl) + |
| 740 | + f"\n_test_sigint_impl({backend!r}, {target!r}, {kwargs!r})") |
| 741 | + with _WaitForStringPopen([sys.executable, "-c", source]) as proc: |
| 742 | + try: |
| 743 | + proc.wait_for('DRAW') |
| 744 | + stdout, _ = proc.communicate(timeout=_test_timeout) |
| 745 | + except Exception: |
| 746 | + proc.kill() |
| 747 | + stdout, _ = proc.communicate() |
| 748 | + raise |
| 749 | + assert 'SUCCESS' in stdout |
752 | 750 |
|
753 | 751 |
|
754 | 752 | def _test_other_signal_before_sigint_impl(backend, target_name, kwargs): |
@@ -796,20 +794,19 @@ def test_other_signal_before_sigint(env, target, kwargs, request): |
796 | 794 | # https://github.com/matplotlib/matplotlib/issues/27984 |
797 | 795 | request.node.add_marker( |
798 | 796 | pytest.mark.xfail(reason="Qt backend is buggy on macOS")) |
799 | | - proc = _WaitForStringPopen( |
800 | | - [sys.executable, "-c", |
801 | | - inspect.getsource(_test_other_signal_before_sigint_impl) + |
802 | | - "\n_test_other_signal_before_sigint_impl(" |
803 | | - f"{backend!r}, {target!r}, {kwargs!r})"]) |
804 | | - try: |
805 | | - proc.wait_for('DRAW') |
806 | | - os.kill(proc.pid, signal.SIGUSR1) |
807 | | - proc.wait_for('SIGUSR1') |
808 | | - os.kill(proc.pid, signal.SIGINT) |
809 | | - stdout, _ = proc.communicate(timeout=_test_timeout) |
810 | | - except Exception: |
811 | | - proc.kill() |
812 | | - stdout, _ = proc.communicate() |
813 | | - raise |
| 797 | + source = (inspect.getsource(_test_other_signal_before_sigint_impl) + |
| 798 | + "\n_test_other_signal_before_sigint_impl(" |
| 799 | + f"{backend!r}, {target!r}, {kwargs!r})") |
| 800 | + with _WaitForStringPopen([sys.executable, "-c", source]) as proc: |
| 801 | + try: |
| 802 | + proc.wait_for('DRAW') |
| 803 | + os.kill(proc.pid, signal.SIGUSR1) |
| 804 | + proc.wait_for('SIGUSR1') |
| 805 | + os.kill(proc.pid, signal.SIGINT) |
| 806 | + stdout, _ = proc.communicate(timeout=_test_timeout) |
| 807 | + except Exception: |
| 808 | + proc.kill() |
| 809 | + stdout, _ = proc.communicate() |
| 810 | + raise |
814 | 811 | print(stdout) |
815 | 812 | assert 'SUCCESS' in stdout |
0 commit comments