1
1
import functools
2
- import inspect
2
+ import importlib
3
3
import os
4
4
import platform
5
- import re
6
5
import subprocess
7
6
import sys
8
7
9
8
import pytest
10
9
10
+ from matplotlib .testing import subprocess_run_helper
11
+ from matplotlib import _c_internal_utils
12
+
11
13
_test_timeout = 60 # A reasonably safe value for slower architectures.
12
14
13
15
@@ -18,30 +20,32 @@ def _isolated_tk_test(success_count, func=None):
18
20
19
21
TkAgg tests seem to have interactions between tests, so isolate each test
20
22
in a subprocess. See GH#18261
21
-
22
- The decorated function must be fully self-contained, and thus perform
23
- all the imports it needs. Because its source is extracted and run by
24
- itself, coverage will consider it as not being run, so it should be marked
25
- with ``# pragma: no cover``
26
23
"""
27
24
28
25
if func is None :
29
26
return functools .partial (_isolated_tk_test , success_count )
30
27
31
- # Remove decorators.
32
- source = re .search (r"(?ms)^def .*" , inspect .getsource (func )).group (0 )
33
-
28
+ if "MPL_TEST_ESCAPE_HATCH" in os .environ :
29
+ return func
30
+
31
+ @pytest .mark .skipif (
32
+ importlib .util .find_spec ('tkinter' ),
33
+ reason = "missing tkinter"
34
+ )
35
+ @pytest .mark .skipif (
36
+ sys .platform == "linux" and not _c_internal_utils .display_is_valid (),
37
+ reason = "$DISPLAY and $WAYLAND_DISPLAY are unset"
38
+ )
34
39
@functools .wraps (func )
35
40
def test_func ():
41
+ # even if the package exists, may not actually be importable this can
42
+ # be the case on some CI systems.
43
+ pytest .importorskip ('tkinter' )
36
44
try :
37
- proc = subprocess .run (
38
- [sys .executable , "-c" , f"{ source } \n { func .__name__ } ()" ],
39
- env = {** os .environ , "MPLBACKEND" : "TkAgg" },
40
- timeout = _test_timeout ,
41
- stdout = subprocess .PIPE ,
42
- stderr = subprocess .PIPE ,
43
- check = True ,
44
- universal_newlines = True ,
45
+ proc = subprocess_run_helper (
46
+ func , timeout = _test_timeout ,
47
+ MPLBACKEND = "TkAgg" ,
48
+ MPL_TEST_ESCAPE_HATCH = "1"
45
49
)
46
50
except subprocess .TimeoutExpired :
47
51
pytest .fail ("Subprocess timed out" )
@@ -59,9 +63,8 @@ def test_func():
59
63
return test_func
60
64
61
65
62
- @pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
63
66
@_isolated_tk_test (success_count = 6 ) # len(bad_boxes)
64
- def test_blit (): # pragma: no cover
67
+ def test_blit ():
65
68
import matplotlib .pyplot as plt
66
69
import numpy as np
67
70
import matplotlib .backends .backend_tkagg # noqa
@@ -88,9 +91,8 @@ def test_blit(): # pragma: no cover
88
91
print ("success" )
89
92
90
93
91
- @pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
92
94
@_isolated_tk_test (success_count = 1 )
93
- def test_figuremanager_preserves_host_mainloop (): # pragma: no cover
95
+ def test_figuremanager_preserves_host_mainloop ():
94
96
import tkinter
95
97
import matplotlib .pyplot as plt
96
98
success = []
@@ -116,10 +118,9 @@ def legitimate_quit():
116
118
@pytest .mark .skipif (platform .python_implementation () != 'CPython' ,
117
119
reason = 'PyPy does not support Tkinter threading: '
118
120
'https://foss.heptapod.net/pypy/pypy/-/issues/1929' )
119
- @pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
120
121
@pytest .mark .flaky (reruns = 3 )
121
122
@_isolated_tk_test (success_count = 1 )
122
- def test_figuremanager_cleans_own_mainloop (): # pragma: no cover
123
+ def test_figuremanager_cleans_own_mainloop ():
123
124
import tkinter
124
125
import time
125
126
import matplotlib .pyplot as plt
@@ -144,10 +145,9 @@ def target():
144
145
thread .join ()
145
146
146
147
147
- @pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
148
148
@pytest .mark .flaky (reruns = 3 )
149
149
@_isolated_tk_test (success_count = 0 )
150
- def test_never_update (): # pragma: no cover
150
+ def test_never_update ():
151
151
import tkinter
152
152
del tkinter .Misc .update
153
153
del tkinter .Misc .update_idletasks
@@ -171,9 +171,8 @@ def test_never_update(): # pragma: no cover
171
171
# checks them.
172
172
173
173
174
- @pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
175
174
@_isolated_tk_test (success_count = 2 )
176
- def test_missing_back_button (): # pragma: no cover
175
+ def test_missing_back_button ():
177
176
import matplotlib .pyplot as plt
178
177
from matplotlib .backends .backend_tkagg import NavigationToolbar2Tk
179
178
0 commit comments