refactoring in matplotlib support
authorElizaveta Shashkova <Elizaveta.Shashkova@jetbrains.com>
Tue, 10 Feb 2015 12:55:10 +0000 (15:55 +0300)
committerElizaveta Shashkova <Elizaveta.Shashkova@jetbrains.com>
Tue, 10 Feb 2015 12:55:10 +0000 (15:55 +0300)
python/helpers/pydev/pydev_ipython/matplotlibtools.py
python/helpers/pydev/pydevconsole.py
python/helpers/pydev/pydevd.py

index 664f6ab06b33b37473267e1a1218b2c69ed59260..234a93710d60bfbe7289445a5ee62970c838db7a 100644 (file)
@@ -61,16 +61,13 @@ def is_interactive_backend(backend):
         return matplotlib.is_interactive()
 
 
-def patch_use(interpreter=None):
+def patch_use(enable_gui_function):
     """ Patch matplotlib function 'use' """
     matplotlib = sys.modules['matplotlib']
     def patched_use(*args, **kwargs):
         matplotlib.real_use(*args, **kwargs)
         gui, backend = find_gui_and_backend()
-        if interpreter:
-            interpreter.enableGui(gui)
-        else:
-            do_enable_gui(gui)
+        enable_gui_function(gui)
 
     setattr(matplotlib, "real_use", getattr(matplotlib, "use"))
     setattr(matplotlib, "use", patched_use)
@@ -86,27 +83,24 @@ def patch_is_interactive():
     setattr(matplotlib, "is_interactive", patched_is_interactive)
 
 
-def activate_matplotlib(interpreter=None):
-    """Set interactive to True for interactive backends."""
-    def activate_matplotlib_inner():
-        matplotlib = sys.modules['matplotlib']
-        gui, backend = find_gui_and_backend()
-        is_interactive = is_interactive_backend(backend)
-        if is_interactive:
-            if interpreter:
-                interpreter.enableGui(gui)
-            else:
-                do_enable_gui(gui)
-            if not matplotlib.is_interactive():
-                sys.stdout.write("Backend %s is interactive backend. Turning interactive mode on.\n" % backend)
-            matplotlib.interactive(True)
-        else:
-            if matplotlib.is_interactive():
-                sys.stdout.write("Backend %s is non-interactive backend. Turning interactive mode off.\n" % backend)
-            matplotlib.interactive(False)
-        patch_use(interpreter)
-        patch_is_interactive()
-    return activate_matplotlib_inner
+def activate_matplotlib(enable_gui_function):
+    """Set interactive to True for interactive backends.
+    enable_gui_function - Function which enables gui, should be run in the main thread.
+    """
+    matplotlib = sys.modules['matplotlib']
+    gui, backend = find_gui_and_backend()
+    is_interactive = is_interactive_backend(backend)
+    if is_interactive:
+        enable_gui_function(gui)
+        if not matplotlib.is_interactive():
+            sys.stdout.write("Backend %s is interactive backend. Turning interactive mode on.\n" % backend)
+        matplotlib.interactive(True)
+    else:
+        if matplotlib.is_interactive():
+            sys.stdout.write("Backend %s is non-interactive backend. Turning interactive mode off.\n" % backend)
+        matplotlib.interactive(False)
+    patch_use(enable_gui_function)
+    patch_is_interactive()
 
 
 def flag_calls(func):
index dfface32307c863ee6b9cd41a4ca98ac77904af9..ad6443df81e7d16681dcc68f5c44bbb913a32cb9 100644 (file)
@@ -176,7 +176,9 @@ def process_exec_queue(interpreter):
 
     from pydev_import_hook import import_hook_manager
     from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot
-    import_hook_manager.add_module_name("matplotlib", activate_matplotlib(interpreter))
+    import_hook_manager.add_module_name("matplotlib", lambda: activate_matplotlib(interpreter.enableGui))
+    # enable_gui_function in activate_matplotlib should be called in main thread. That's why we call
+    # interpreter.enableGui which put it into the interpreter's exec_queue and executes it in the main thread.
     import_hook_manager.add_module_name("pylab", activate_pylab)
     import_hook_manager.add_module_name("pyplot", activate_pyplot)
 
index 4d8f109e8ac7831b50447d4a9b27c36614e25a7d..6ab83b95679016534c02dfad21a87acc4a211ad1 100644 (file)
@@ -499,8 +499,11 @@ class PyDB:
         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
-        import_hook_manager.add_module_name("matplotlib", activate_matplotlib())
+        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
@@ -547,12 +550,6 @@ class PyDB:
                         try:
                             while True:
                                 int_cmd = queue.get(False)
-                                if int_cmd.canBeExecutedBy(curr_thread_id):
-                                    PydevdLog(2, "processing internal command ", str(int_cmd))
-                                    int_cmd.doIt(self)
-                                else:
-                                    PydevdLog(2, "NOT processing internal command ", str(int_cmd))
-                                    cmdsToReadd.append(int_cmd)
 
                                 if not self.use_hooks_in_debug_console and isinstance(int_cmd, InternalConsoleExec):
                                     # patch matplotlib if only debug console was started
@@ -562,6 +559,14 @@ class PyDB:
                                         sys.stderr.write("Matplotlib support in debug console failed\n")
                                         pydev_log.error("Error in matplotlib init %s\n" % sys.exc_info()[0])
 
+                                if int_cmd.canBeExecutedBy(curr_thread_id):
+                                    PydevdLog(2, "processing internal command ", str(int_cmd))
+                                    int_cmd.doIt(self)
+                                else:
+                                    PydevdLog(2, "NOT processing internal command ", str(int_cmd))
+                                    cmdsToReadd.append(int_cmd)
+
+
                         except _queue.Empty: #@UndefinedVariable
                             for int_cmd in cmdsToReadd:
                                 queue.put(int_cmd)