Support matplotlib interactive mode if it was imported inside script. Also support it for debugger without using consoles. (PY-15520)

This commit is contained in:
Elizaveta Shashkova
2015-04-20 15:29:13 +03:00
parent afd35dec27
commit 5fbaba36be
+45 -21
View File
@@ -378,7 +378,10 @@ class PyDB:
self.has_plugin_line_breaks = False
self.has_plugin_exception_breaks = False
self.use_hooks_in_debug_console = False
# matplotlib support in debugger and debug console
self.mpl_in_use = False
self.mpl_hooks_in_debug_console = False
self.mpl_modules_for_patching = {}
def get_plugin_lazy_init(self):
if self.plugin is None and SUPPORT_PLUGINS:
@@ -516,29 +519,33 @@ class PyDB:
def init_matplotlib_in_debug_console(self):
# import hook and patches for matplotlib support
class _DebugConsoleHelper:
# import hook and patches for matplotlib support in debug console
from pydev_import_hook import import_hook_manager
for module in DictKeys(self.mpl_modules_for_patching):
import_hook_manager.add_module_name(module, DictPop(self.mpl_modules_for_patching, module))
def init_matplotlib_support(self):
# prepare debugger for integration with matplotlib GUI event loop
from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot, do_enable_gui
# enable_gui_function in activate_matplotlib should be called in main thread. Unlike integrated console,
# in the debug console we have no interpreter instance with exec_queue, but we run this code in the main
# thread and can call it directly.
class _MatplotlibHelper:
_return_control_osc = False
def return_control():
# Some of the input hooks (e.g. Qt4Agg) check return control without doing
# a single operation, so we don't return True on every
# call when the debug hook is in place to allow the GUI to run
_DebugConsoleHelper._return_control_osc = not _DebugConsoleHelper._return_control_osc
return _DebugConsoleHelper._return_control_osc
_MatplotlibHelper._return_control_osc = not _MatplotlibHelper._return_control_osc
return _MatplotlibHelper._return_control_osc
from pydev_ipython.inputhook import set_return_control_callback
set_return_control_callback(return_control)
from pydev_import_hook import import_hook_manager
from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot, do_enable_gui
import_hook_manager.add_module_name("matplotlib", lambda: activate_matplotlib(do_enable_gui))
# enable_gui_function in activate_matplotlib should be called in main thread. Unlike integrated console,
# in the debug console we have no interpreter instance with exec_queue, but we run this code in the main
# thread and can call it directly.
import_hook_manager.add_module_name("pylab", activate_pylab)
import_hook_manager.add_module_name("pyplot", activate_pyplot)
self.use_hooks_in_debug_console = True
self.mpl_modules_for_patching = {"matplotlib": lambda: activate_matplotlib(do_enable_gui),
"matplotlib.pyplot": activate_pyplot,
"pylab": activate_pylab }
def processInternalCommands(self):
@@ -582,13 +589,15 @@ class PyDB:
while True:
int_cmd = queue.get(False)
if not self.use_hooks_in_debug_console and isinstance(int_cmd, InternalConsoleExec):
# patch matplotlib if only debug console was started
if not self.mpl_hooks_in_debug_console and isinstance(int_cmd, InternalConsoleExec):
# add import hooks for matplotlib patches if only debug console was started
try:
self.init_matplotlib_in_debug_console()
self.mpl_hooks_in_debug_console = True
self.mpl_in_use = True
except:
sys.stderr.write("Matplotlib support in debug console failed\n")
pydev_log.error("Error in matplotlib init %s\n" % sys.exc_info()[0])
pydev_log.error("Matplotlib support in debug console failed\n")
traceback.print_exc()
if int_cmd.canBeExecutedBy(curr_thread_id):
PydevdLog(2, "processing internal command ", str(int_cmd))
@@ -1429,9 +1438,19 @@ class PyDB:
imported = False
info = thread.additionalInfo
if info.pydev_state == STATE_SUSPEND and not self._finishDebuggingSession:
# before every stop check if matplotlib modules were imported inside script code
if len(self.mpl_modules_for_patching) > 0:
for module in DictKeys(self.mpl_modules_for_patching):
if module in sys.modules:
activate_function = DictPop(self.mpl_modules_for_patching, module)
activate_function()
self.mpl_in_use = True
while info.pydev_state == STATE_SUSPEND and not self._finishDebuggingSession:
if self.use_hooks_in_debug_console:
# import and call input hooks if only debug console was started
if self.mpl_in_use:
# call input hooks if only matplotlib is in use
try:
if not imported:
from pydev_ipython.inputhook import get_inputhook
@@ -1440,7 +1459,7 @@ class PyDB:
if inputhook:
inputhook()
except:
pydev_log.error("Error while calling matplotlib input hooks in debug console %s\n" % sys.exc_info()[0])
pass
self.processInternalCommands()
time.sleep(0.01)
@@ -1752,6 +1771,11 @@ class PyDB:
while not self.readyToRun:
time.sleep(0.1) # busy wait until we receive run command
try:
self.init_matplotlib_support()
except:
sys.stderr.write("Matplotlib support in debugger failed\n")
traceback.print_exc()
pydev_imports.execfile(file, globals, locals) # execute the script