Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bcc570b

Browse files
committed
macOS: Check for display availability when looking for backends
1 parent 993f22d commit bcc570b

9 files changed

+54
-18
lines changed

lib/matplotlib/tests/test_backend_macosx.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@
33
import pytest
44

55
import matplotlib as mpl
6+
from matplotlib import _c_internal_utils
67
import matplotlib.pyplot as plt
78
try:
89
from matplotlib.backends import _macosx
910
except ImportError:
1011
pytest.skip("These are mac only tests", allow_module_level=True)
1112

1213

14+
pytestmark = [
15+
pytest.mark.skipif(not _c_internal_utils.display_is_valid(),
16+
reason="Display is unavailable")
17+
]
18+
19+
1320
@pytest.mark.backend('macosx')
1421
def test_cached_renderer():
1522
# Make sure that figures have an associated renderer after

lib/matplotlib/tests/test_backend_qt.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,8 @@ def _get_testable_qt_backends():
305305
]:
306306
reason = None
307307
missing = [dep for dep in deps if not importlib.util.find_spec(dep)]
308-
if (sys.platform == "linux" and
309-
not _c_internal_utils.display_is_valid()):
310-
reason = "$DISPLAY and $WAYLAND_DISPLAY are unset"
308+
if not _c_internal_utils.display_is_valid():
309+
reason = "Display is unavailable"
311310
elif missing:
312311
reason = "{} cannot be imported".format(", ".join(missing))
313312
elif env["MPLBACKEND"] == 'macosx' and os.environ.get('TF_BUILD'):

lib/matplotlib/tests/test_backend_tk.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ def _isolated_tk_test(success_count, func=None):
3535
reason="missing tkinter"
3636
)
3737
@pytest.mark.skipif(
38-
sys.platform == "linux" and not _c_internal_utils.display_is_valid(),
39-
reason="$DISPLAY and $WAYLAND_DISPLAY are unset"
38+
not _c_internal_utils.display_is_valid(),
39+
reason="Display is unavailable"
4040
)
4141
@pytest.mark.xfail( # https://github.com/actions/setup-python/issues/649
4242
('TF_BUILD' in os.environ or 'GITHUB_ACTION' in os.environ) and

lib/matplotlib/tests/test_backends_interactive.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ def wait_for(self, terminator):
5555

5656
@functools.lru_cache
5757
def _get_available_interactive_backends():
58-
_is_linux_and_display_invalid = (sys.platform == "linux" and
59-
not _c_internal_utils.display_is_valid())
58+
_is_display_invalid = not _c_internal_utils.display_is_valid()
6059
envs = []
6160
for deps, env in [
6261
*[([qt_api],
@@ -74,8 +73,8 @@ def _get_available_interactive_backends():
7473
]:
7574
reason = None
7675
missing = [dep for dep in deps if not importlib.util.find_spec(dep)]
77-
if _is_linux_and_display_invalid:
78-
reason = "$DISPLAY and $WAYLAND_DISPLAY are unset"
76+
if _is_display_invalid:
77+
reason = "Display is unavailable"
7978
elif missing:
8079
reason = "{} cannot be imported".format(", ".join(missing))
8180
elif env["MPLBACKEND"] == 'macosx' and os.environ.get('TF_BUILD'):

lib/matplotlib/tests/test_rcparams.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -534,9 +534,7 @@ def test_backend_fallback_headless(tmp_path):
534534
env=env, check=True, stderr=subprocess.DEVNULL)
535535

536536

537-
@pytest.mark.skipif(
538-
sys.platform == "linux" and not _c_internal_utils.display_is_valid(),
539-
reason="headless")
537+
@pytest.mark.skipif(not _c_internal_utils.display_is_valid(), reason="headless")
540538
def test_backend_fallback_headful(tmp_path):
541539
pytest.importorskip("tkinter")
542540
env = {**os.environ, "MPLBACKEND": "", "MPLCONFIGDIR": str(tmp_path)}

meson.build

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ project(
1717

1818
cc = meson.get_compiler('c')
1919
cpp = meson.get_compiler('cpp')
20+
# Objective C is needed for the _c_internal_utils and macosx extension.
21+
if host_machine.system() == 'darwin'
22+
add_languages('objc', native: false)
23+
endif
2024

2125
# https://mesonbuild.com/Python-module.html
2226
py_mod = import('python')

src/_c_internal_utils.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
#else
1919
#define UNUSED_ON_NON_WINDOWS Py_UNUSED
2020
#endif
21+
#ifdef __APPLE__
22+
// Defined in _objc_internal_utils.m.
23+
extern "C" {
24+
int _macos_display_is_valid(void);
25+
}
26+
#endif
2127

2228
namespace py = pybind11;
2329
using namespace pybind11::literals;
@@ -69,6 +75,8 @@ mpl_display_is_valid(void)
6975
}
7076
}
7177
return false;
78+
#elif defined(__APPLE__)
79+
return _macos_display_is_valid() == 1;
7280
#else
7381
return true;
7482
#endif
@@ -180,6 +188,8 @@ PYBIND11_MODULE(_c_internal_utils, m)
180188
succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)
181189
succeeds.
182190
191+
On macOS, returns True if NSScreen::mainScreen is not nil.
192+
183193
On other platforms, always returns True.)""");
184194
m.def(
185195
"Win32_GetCurrentProcessExplicitAppUserModelID",

src/_objc_internal_utils.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <Cocoa/Cocoa.h>
2+
3+
int
4+
_macos_display_is_valid(void)
5+
{
6+
NSApplicationLoad();
7+
NSScreen *main = [NSScreen mainScreen];
8+
if (main != nil) {
9+
return 1;
10+
} else {
11+
return 0;
12+
}
13+
}

src/meson.build

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ else
6969
user32 = []
7070
endif
7171

72+
if host_machine.system() == 'darwin'
73+
cocoa = dependency('appleframeworks', modules: 'Cocoa')
74+
else
75+
cocoa = []
76+
endif
77+
7278
extension_data = {
7379
'_backend_agg': {
7480
'subdir': 'matplotlib/backends',
@@ -81,10 +87,11 @@ extension_data = {
8187
},
8288
'_c_internal_utils': {
8389
'subdir': 'matplotlib',
84-
'sources': files(
85-
'_c_internal_utils.cpp',
86-
),
87-
'dependencies': [pybind11_dep, dl, ole32, shell32, user32],
90+
'sources': [
91+
files('_c_internal_utils.cpp'),
92+
(host_machine.system() == 'darwin') ? files('_objc_internal_utils.m') : [],
93+
],
94+
'dependencies': [pybind11_dep, dl, ole32, shell32, user32, cocoa],
8895
},
8996
'ft2font': {
9097
'subdir': 'matplotlib',
@@ -182,14 +189,13 @@ foreach ext, kwargs : extension_data
182189
endforeach
183190

184191
if get_option('macosx') and host_machine.system() == 'darwin'
185-
add_languages('objc', native: false)
186192
py3.extension_module(
187193
'_macosx',
188194
subdir: 'matplotlib/backends',
189195
sources: files(
190196
'_macosx.m',
191197
),
192-
dependencies: dependency('appleframeworks', modules: 'Cocoa'),
198+
dependencies: [cocoa],
193199
override_options: ['werror=true'],
194200
install: true,
195201
)

0 commit comments

Comments
 (0)