Skip to content

Commit 6c7cf65

Browse files
committed
Clarify logic for repl displayhook.
_IP_REGISTERED and _INSTALL_FIG_OBSERVER effectively encode a 3-state, so just store that as a single _REPL_DISPLAYHOOK variable. Also make post_execute a globally available (private) function, so that it doesn't need to be smuggled via _IP_REGISTERED to uninstall_repl_displayhook.
1 parent aeb0692 commit 6c7cf65

File tree

1 file changed

+22
-23
lines changed

1 file changed

+22
-23
lines changed

lib/matplotlib/pyplot.py

+22-23
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
implicit and explicit interfaces.
3636
"""
3737

38+
from enum import Enum
3839
import functools
3940
import importlib
4041
import inspect
@@ -108,8 +109,15 @@ def _copy_docstring_and_deprecators(method, func=None):
108109

109110
## Global ##
110111

111-
_IP_REGISTERED = None
112-
_INSTALL_FIG_OBSERVER = False
112+
113+
# The state controlled by {,un}install_repl_displayhook().
114+
_ReplDisplayHook = Enum("_ReplDisplayHook", ["NONE", "PLAIN", "IPYTHON"])
115+
_REPL_DISPLAYHOOK = _ReplDisplayHook.NONE
116+
117+
118+
def _draw_all_if_interactive():
119+
if matplotlib.is_interactive():
120+
draw_all()
113121

114122

115123
def install_repl_displayhook():
@@ -119,30 +127,25 @@ def install_repl_displayhook():
119127
120128
This works both with IPython and with vanilla python shells.
121129
"""
122-
global _IP_REGISTERED
123-
global _INSTALL_FIG_OBSERVER
130+
global _REPL_DISPLAYHOOK
124131

125-
if _IP_REGISTERED:
132+
if _REPL_DISPLAYHOOK is _ReplDisplayHook.IPYTHON:
126133
return
134+
127135
# See if we have IPython hooks around, if so use them.
128136
# Use ``sys.modules.get(name)`` rather than ``name in sys.modules`` as
129137
# entries can also have been explicitly set to None.
130138
mod_ipython = sys.modules.get("IPython")
131139
if not mod_ipython:
132-
_INSTALL_FIG_OBSERVER = True
140+
_REPL_DISPLAYHOOK = _ReplDisplayHook.PLAIN
133141
return
134142
ip = mod_ipython.get_ipython()
135143
if not ip:
136-
_INSTALL_FIG_OBSERVER = True
144+
_REPL_DISPLAYHOOK = _ReplDisplayHook.PLAIN
137145
return
138146

139-
def post_execute():
140-
if matplotlib.is_interactive():
141-
draw_all()
142-
143-
ip.events.register("post_execute", post_execute)
144-
_IP_REGISTERED = post_execute
145-
_INSTALL_FIG_OBSERVER = False
147+
ip.events.register("post_execute", _draw_all_if_interactive)
148+
_REPL_DISPLAYHOOK = _ReplDisplayHook.IPYTHON
146149

147150
from IPython.core.pylabtools import backend2gui
148151
# trigger IPython's eventloop integration, if available
@@ -161,16 +164,12 @@ def uninstall_repl_displayhook():
161164
this will reset `sys.displayhook` to what ever function was there when
162165
Matplotlib installed its displayhook, possibly discarding your changes.
163166
"""
164-
global _IP_REGISTERED
165-
global _INSTALL_FIG_OBSERVER
166-
if _IP_REGISTERED:
167+
global _REPL_DISPLAYHOOK
168+
if _REPL_DISPLAYHOOK is _ReplDisplayHook.IPYTHON:
167169
from IPython import get_ipython
168170
ip = get_ipython()
169-
ip.events.unregister('post_execute', _IP_REGISTERED)
170-
_IP_REGISTERED = None
171-
172-
if _INSTALL_FIG_OBSERVER:
173-
_INSTALL_FIG_OBSERVER = False
171+
ip.events.unregister("post_execute", _draw_all_if_interactive)
172+
_REPL_DISPLAYHOOK = _ReplDisplayHook.NONE
174173

175174

176175
draw_all = _pylab_helpers.Gcf.draw_all
@@ -810,7 +809,7 @@ def figure(num=None, # autoincrement if None, else integer from 1-N
810809
# FigureManager base class.
811810
draw_if_interactive()
812811

813-
if _INSTALL_FIG_OBSERVER:
812+
if _REPL_DISPLAYHOOK is _ReplDisplayHook.PLAIN:
814813
fig.stale_callback = _auto_draw_if_interactive
815814

816815
if clear:

0 commit comments

Comments
 (0)