8000 Convert matplotlib gui name in enable_gui (#14451) · ipython/ipython@4136241 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4136241

Browse files
authored
Convert matplotlib gui name in enable_gui (#14451)
This is a bug that I discovered whilst dealing with matplotlib/matplotlib#28332. The change here is in `TerminalInteractiveShell.enable_gui` which needs to convert a gui of `macosx` from Matplotlib into `osx` in IPython. It reuses the converter function created in #14420. I've added a test that uses `enable_gui` and raises an exception before this PR but passes with it. The remainder of the changes are formatting changes from `pre-commit`.
2 parents c098f4c + 78e081b commit 4136241

File tree

3 files changed

+79
-51
lines changed

3 files changed

+79
-51
lines changed

IPython/core/tests/test_interactiveshell.py

Lines changed: 67 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727
from IPython.core import interactiveshell
2828
from IPython.core.oinspect import OInfo
2929
from IPython.testing.decorators import (
30-
skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
30+
skipif,
31+
skip_win32,
32+
onlyif_unicode_paths,
33+
onlyif_cmds_exist,
34+
skip_if_not_osx,
3135
)
3236
from IPython.testing import tools as tt
3337
from IPython.utils.process import find_cmd
@@ -124,16 +128,16 @@ def test_In_variable(self):
124128
newlen = len(ip.user_ns['In'])
125129
self.assertEqual(oldlen+1, newlen)
126130
self.assertEqual(ip.user_ns['In'][-1],'1;')
127-
131+
128132
def test_magic_names_in_string(self):
129133
ip.run_cell('a = """\n%exit\n"""')
130134
self.assertEqual(ip.user_ns['a'], '\n%exit\n')
131-
135+
132136
def test_trailing_newline(self):
133137
"""test that running !(command) does not raise a SyntaxError"""
134138
ip.run_cell('!(true)\n', False)
135139
ip.run_cell('!(true)\n\n\n', False)
136-
140+
137141
def test_gh_597(self):
138142
"""Pretty-printing lists of objects with non-ascii reprs may cause
139143
problems."""
@@ -142,8 +146,7 @@ def __repr__(self):
142146
return "\xe9"*50
143147
import IPython.core.formatters
144148
f = IPython.core.formatters.PlainTextFormatter()
145-
f([Spam(),Spam()])
146-
149+
f([Spam(), Spam()])
147150

148151
def test_future_flags(self):
149152
"""Check that future flags are used for parsing code (gh-777)"""
@@ -163,9 +166,9 @@ def test_can_pickle(self):
163166
" def __init__(self,x=[]):\n"
164167
" list.__init__(self,x)"))
165168
ip.run_cell("w=Mylist([1,2,3])")
166-
169+
167170
from pickle import dumps
168-
171+
169172
# We need to swap in our main module - this is only necessary
170173
# inside the test framework, because IPython puts the interactive module
171174
# in place (but the test framework undoes this).
@@ -176,7 +179,7 @@ def test_can_pickle(self):
176179
finally:
177180
sys.modules['__main__'] = _main
178181
self.assertTrue(isinstance(res, bytes))
179-
182+
180183
def test_global_ns(self):
181184
"Code in functions must be able to access variables outside them."
182185
ip = get_ipython()
@@ -222,13 +225,13 @@ def test_var_expand(self):
222225
self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
223226
self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
224227
self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
225-
228+
226229
self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
227230

228231
ip.user_ns['f'] = b'Ca\xc3\xb1o'
229232
# This should not raise any exception:
230233
ip.var_expand(u'echo $f')
231-
234+
232235
def test_var_expand_local(self):
233236
"""Test local variable expansion in !system and %magic calls"""
234237
# !system
@@ -253,7 +256,7 @@ def test_var_expand_local(self):
253256

254257
def test_var_expand_self(self):
255258
"""Test variable expansion with the name 'self', which was failing.
256-
259+
257260
See htt F438 ps://github.com/ipython/ipython/issues/1878#issuecomment-7698218
258261
"""
259262
ip.run_cell(
@@ -273,20 +276,20 @@ def test_bad_var_expand(self):
273276
self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
274277
# ZeroDivisionError
275278
self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
276-
279+
277280
def test_silent_postexec(self):
278281
"""run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
279282
pre_explicit = mock.Mock()
280283
pre_always = mock.Mock()
281284
post_explicit = mock.Mock()
282285
post_always = mock.Mock()
283286
all_mocks = [pre_explicit, pre_always, post_explicit, post_always]
284-
287+
285288
ip.events.register('pre_run_cell', pre_explicit)
286289
ip.events.register('pre_execute', pre_always)
287290
ip.events.register('post_run_cell', post_explicit)
288291
ip.events.register('post_execute', post_always)
289-
292+
290293
try:
291294
ip.run_cell("1", silent=True)
292295
assert pre_always.called
@@ -317,29 +320,29 @@ def test_silent_postexec(self):
317320
ip.events.unregister('pre_execute', pre_always)
318321
ip.events.unregister('post_run_cell', post_explicit)
319322
ip.events.unregister('post_execute', post_always)
320-
323+
321324
def test_silent_noadvance(self):
322325
"""run_cell(silent=True) doesn't advance execution_count"""
323326
ec = ip.execution_count
324327
# silent should force store_history=False
325328
ip.run_cell("1", store_history=True, silent=True)
326-
329+
327330
self.assertEqual(ec, ip.execution_count)
328331
# double-check that non-silent exec did what we expected
329332
# silent to avoid
330333
ip.run_cell("1", store_history=True)
331334
self.assertEqual(ec+1, ip.execution_count)
332-
335+
333336
def test_silent_nodisplayhook(self):
334337
"""run_cell(silent=True) doesn't trigger displayhook"""
335338
d = dict(called=False)
336-
339+
337340
trap = ip.display_trap
338341
save_hook = trap.hook
339-
342+
340343
def failing_hook(*args, **kwargs):
341344
d['called'] = True
342-
345+
343346
try:
344347
trap.hook = failing_hook
345348
res = ip.run_cell("1", silent=True)
@@ -354,7 +357,7 @@ def failing_hook(*args, **kwargs):
354357

355358
def test_ofind_line_magic(self):
356359
from IPython.core.magic import register_line_magic
357-
360+
358361
@register_line_magic
359362
def lmagic(line):
360363
"A line magic"
@@ -370,10 +373,10 @@ def lmagic(line):
370373
parent=None,
371374
)
372375
self.assertEqual(lfind, info)
373-
376+
374377
def test_ofind_cell_magic(self):
375378
from IPython.core.magic import register_cell_magic
376-
379+
377380
@register_cell_magic
378381
def cmagic(line, cell):
379382
"A cell magic"
@@ -490,7 +493,7 @@ def test_custom_exception(self):
490493
def my_handler(shell, etype, value, tb, tb_offset=None):
491494
called.append(etype)
492495
shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
493-
496+
494497
ip.set_custom_exc((ValueError,), my_handler)
495498
try:
496499
res = ip.run_cell("raise ValueError('test')")
@@ -501,7 +504,7 @@ def my_handler(shell, etype, value, tb, tb_offset=None):
501504
finally:
502505
# Reset the custom exception hook
503506
ip.set_custom_exc((), None)
504-
507+
505508
@mock.patch("builtins.print")
506509
def test_showtraceback_with_surrogates(self, mocked_print):
507510
values = []
@@ -618,15 +621,15 @@ def test_exit_code_ok(self):
618621
def test_exit_code_error(self):
619622
self.system('exit 1')
620623
self.assertEqual(ip.user_ns['_exit_code'], 1)
621-
624+
622625
@skipif(not hasattr(signal, 'SIGALRM'))
623626
def test_exit_code_signal(self):
624627
self.mktmp("import signal, time\n"
625628
"signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
626629
"time.sleep(1)\n")
627630
self.system("%s %s" % (sys.executable, self.fname))
628631
self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
629-
632+
630633
@onlyif_cmds_exist("csh")
631634
def test_exit_code_signal_csh(self): # pragma: no cover
632635
SHELL = os.environ.get("SHELL", None)
@@ -730,7 +733,7 @@ class TestAstTransform(unittest.TestCase):
730733
def setUp(self):
731734
self.negator = Negator()
732735
ip.ast_transformers.append(self.negator)
733-
736+
734737
def tearDown(self):
735738
ip.ast_transformers.remove(self.negator)
736739

@@ -752,7 +755,7 @@ def test_timeit(self):
752755
def f(x):
753756
called.add(x)
754757
ip.push({'f':f})
755-
758+
756759
with tt.AssertPrints("std. dev. of"):
757760
ip.run_lin F438 e_magic("timeit", "-n1 f(1)")
758761
self.assertEqual(called, {-1})
@@ -761,29 +764,29 @@ def f(x):
761764
with tt.AssertPrints("std. dev. of"):
762765
ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
763766
self.assertEqual(called, {-2, -3})
764-
767+
765768
def test_time(self):
766769
called = []
767770
def f(x):
768771
called.append(x)
769772
ip.push({'f':f})
770-
773+
771774
# Test with an expression
772775
with tt.AssertPrints("Wall time: "):
773776
ip.run_line_magic("time", "f(5+9)")
774777
self.assertEqual(called, [-14])
775778
called[:] = []
776-
779+
777780
# Test with a statement (different code path)
778781
with tt.AssertPrints("Wall time: "):
779782
ip.run_line_magic("time", "a = f(-3 + -2)")
780783
self.assertEqual(called, [5])
781-
784+
782785
def test_macro(self):
783786
ip.push({'a':10})
784787
# The AST transformation makes this do a+=-1
785788
ip.define_macro("amacro", "a+=1\nprint(a)")
786-
789+
787790
with tt.AssertPrints("9"):
788791
ip.run_cell("amacro")
789792
with tt.AssertPrints("8"):
@@ -836,21 +839,21 @@ class TestAstTransform2(unittest.TestCase):
836839
def setUp(self):
837840
self.intwrapper = IntegerWrapper()
838841
ip.ast_transformers.append(self.intwrapper)
839-
842+
840843
self.calls = []
841844
def Integer(*args):
842845
self.calls.append(args)
843846
return args
844847
ip.push({"Integer": Integer})
845-
848+
846849
def tearDown(self):
847850
ip.ast_transformers.remove(self.intwrapper)
848851
del ip.user_ns['Integer']
849-
852+
850853
def test_run_cell(self):
851854
ip.run_cell("n = 2")
852855
self.assertEqual(self.calls, [(2,)])
853-
856+
854857
# This shouldn't throw an error
855858
ip.run_cell("o = 2.0")
856859
self.assertEqual(ip.user_ns['o'], 2.0)
@@ -887,10 +890,10 @@ class TestAstTransformError(unittest.TestCase):
887890
def test_unregistering(self):
888891
err_transformer = ErrorTransformer()
889892
ip.ast_transformers.append(err_transformer)
890-
893+
891894
with self.assertWarnsRegex(UserWarning, "It will be unregistered"):
892895
ip.run_cell("1 + 2")
893-
896+
894897
# This should have been removed.
895898
self.assertNotIn(err_transformer, ip.ast_transformers)
896899

@@ -901,7 +904,7 @@ class StringRejector(ast.NodeTransformer):
901904
Used to verify that NodeTransformers can signal that a piece of code should
902905
not be executed by throwing an InputRejected.
903906
"""
904-
907+
905908
def visit_Constant(self, node):
906909
if isinstance(node.value, str):
907910
raise InputRejected("test")
@@ -941,18 +944,18 @@ def test__IPYTHON__():
941944
class DummyRepr(object):
942945
def __repr__(self):
943946
return "DummyRepr"
944-
947+
945948
def _repr_html_(self):
946949
return "<b>dummy</b>"
947-
950+
948951
def _repr_javascript_(self):
949952
return "console.log('hi');", {'key': 'value'}
950-
953+
951954

952955
def test_user_variables():
953956
# enable all formatters
954957
ip.display_formatter.active_types = ip.display_formatter.format_types
955-
958+
956959
ip.user_ns['dummy'] = d = DummyRepr()
957960
keys = {'dummy', 'doesnotexist'}
958961
r = ip.user_expressions({ key:key for key in keys})
@@ -974,7 +977,7 @@ def test_user_variables():
974977

975978
# back to text only
976979
ip.display_formatter.active_types = ['text/plain']
977-
980+
978981
def test_user_expression():
979982
# enable all formatters
980983
ip.display_formatter.active_types = ip.display_formatter.format_types
@@ -1199,3 +1202,20 @@ def test_set_show_tracebacks_noop(self):
11991202
assert result.result is None
12001203
assert isinstance(result.error_in_exec, AssertionError)
12011204
assert str(result.error_in_exec) == "This should not raise an exception"
1205+
1206+
1207+
@skip_if_not_osx
1208+
def test_enable_gui_osx():
1209+
simple_prompt = ip.simple_prompt
1210+
ip.simple_prompt = False
1211+
1212+
ip.enable_gui("osx")
1213+
assert ip.active_eventloop == "osx"
1214+
ip.enable_gui()
1215+
1216+
# The following line fails for IPython <= 8.25.0
1217+
ip.enable_gui("macosx")
1218+
assert ip.active_eventloop == "osx"
1219+
ip.enable_gui()
1220+
1221+
ip.simple_prompt = simple_prompt

IPython/terminal/interactiveshell.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,11 @@ def inputhook(self, context):
943943
active_eventloop: Optional[str] = None
944944

945945
def enable_gui(self, gui: Optional[str] = None) -> None:
946+
if gui:
947+
from ..core.pylabtools import _convert_gui_from_matplotlib
948+
949+
gui = _convert_gui_from_matplotlib(gui)
950+
946951
if self.simple_prompt is True and gui is not None:
947952
print(
948953
f'Cannot install event loop hook for "{gui}" when running with `--simple-prompt`.'

IPython/testing/decorators.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,13 @@ def module_not_available(module):
147147

148148

149149
# Decorators to skip tests if not on specific platforms.
150-
skip_if_not_win32 = skipif(sys.platform != 'win32',
151-
"This test only runs under Windows")
152-
skip_if_not_linux = skipif(not sys.platform.startswith('linux'),
153-
"This test only runs under Linux")
150+
skip_if_not_win32 = skipif(sys.platform != "win32", "This test only runs under Windows")
151+
skip_if_not_linux = skipif(
152+
not sys.platform.startswith("linux"), "This test only runs under Linux"
153+
)
154+
skip_if_not_osx = skipif(
155+
not sys.platform.startswith("darwin"), "This test only runs under macOS"
156+
)
154157

155158
_x11_skip_cond = (sys.platform not in ('darwin', 'win32') and
156159
os.environ.get('DISPLAY', '') == '')

0 commit comments

Comments
 (0)
0