mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
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:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user