Skip to content

Commit

Permalink
Merge from 3.1.x: PR #4263
Browse files Browse the repository at this point in the history
Fixes: #4141
  • Loading branch information
ccordoba12 committed Mar 21, 2017
2 parents 260735e + c0f5423 commit 669b6b4
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 17 deletions.
6 changes: 5 additions & 1 deletion spyder/plugins/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ def __init__(self, parent, ignore_last_opened_files=False):
self.toolbar_list = None
self.menu_list = None

self.introspector = IntrospectionManager()
self.introspector = IntrospectionManager(
extra_path=self.main.get_spyder_pythonpath())

# Setup new windows:
self.main.all_actions_defined.connect(self.setup_other_windows)
Expand Down Expand Up @@ -1473,6 +1474,9 @@ def set_current_filename(self, filename, editorwindow=None):
def set_path(self):
for finfo in self.editorstacks[0].data:
finfo.path = self.main.get_spyder_pythonpath()
if self.introspector:
self.introspector.change_extra_path(
self.main.get_spyder_pythonpath())

#------ Refresh methods
def refresh_file_dependent_actions(self):
Expand Down
27 changes: 21 additions & 6 deletions spyder/utils/introspection/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ class PluginManager(QObject):

introspection_complete = Signal(object)

def __init__(self, executable):
def __init__(self, executable, extra_path=None):

super(PluginManager, self).__init__()
plugins = OrderedDict()
for name in PLUGINS:
try:
plugin = PluginClient(name, executable)
plugin = PluginClient(name, executable, extra_path=extra_path)
plugin.run()
except Exception as e:
debug_print('Introspection Plugin Failed: %s' % name)
Expand Down Expand Up @@ -129,7 +130,9 @@ def handle_response(self, response):
self.pending = response

def close(self):
[plugin.close() for plugin in self.plugins]
for name, plugin in self.plugins.items():
plugin.close()
debug_print("Introspection Plugin Closed: {}".format(name))

def _finalize(self, response):
self.waiting = False
Expand Down Expand Up @@ -160,17 +163,29 @@ class IntrospectionManager(QObject):
send_to_help = Signal(str, str, str, str, bool)
edit_goto = Signal(str, int, str)

def __init__(self, executable=None):
def __init__(self, executable=None, extra_path=None):
super(IntrospectionManager, self).__init__()
self.editor_widget = None
self.pending = None
self.plugin_manager = PluginManager(executable)
self.extra_path = extra_path
self.executable = executable
self.plugin_manager = PluginManager(executable, extra_path)
self.plugin_manager.introspection_complete.connect(
self._introspection_complete)

def change_executable(self, executable):
self.executable = executable
self._restart_plugin()

def change_extra_path(self, extra_path):
if extra_path != self.extra_path:
self.extra_path = extra_path
self._restart_plugin()

def _restart_plugin(self):
self.plugin_manager.close()
self.plugin_manager = PluginManager(executable)
self.plugin_manager = PluginManager(self.executable,
extra_path=self.extra_path)
self.plugin_manager.introspection_complete.connect(
self._introspection_complete)

Expand Down
38 changes: 28 additions & 10 deletions spyder/utils/introspection/plugin_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import zmq

# Local imports
from spyder.config.base import debug_print, DEV, get_module_path
from spyder.config.base import debug_print, get_module_path


# Heartbeat timer in milliseconds
Expand All @@ -41,7 +41,8 @@ class AsyncClient(QObject):
received = Signal(object)

def __init__(self, target, executable=None, name=None,
extra_args=None, libs=None, cwd=None, env=None):
extra_args=None, libs=None, cwd=None, env=None,
extra_path=None):
super(AsyncClient, self).__init__()
self.executable = executable or sys.executable
self.extra_args = extra_args
Expand All @@ -50,8 +51,11 @@ def __init__(self, target, executable=None, name=None,
self.libs = libs
self.cwd = cwd
self.env = env
self.extra_path = extra_path
self.is_initialized = False
self.closing = False
self.notifier = None
self.process = None
self.context = zmq.Context()
QApplication.instance().aboutToQuit.connect(self.close)

Expand All @@ -77,7 +81,7 @@ def run(self):
# Set up environment variables.
processEnvironment = QProcessEnvironment()
env = self.process.systemEnvironment()
if (self.env and 'PYTHONPATH' not in self.env) or DEV:
if (self.env and 'PYTHONPATH' not in self.env) or self.env is None:
python_path = osp.dirname(get_module_path('spyder'))
# Add the libs to the python path.
for lib in self.libs:
Expand All @@ -86,6 +90,13 @@ def run(self):
python_path = osp.pathsep.join([python_path, path])
except ImportError:
pass
if self.extra_path:
try:
python_path = osp.pathsep.join([python_path] +
self.extra_path)
except Exception as e:
debug_print("Error when adding extra_path to plugin env")
debug_print(e)
env.append("PYTHONPATH=%s" % python_path)
if self.env:
env.update(self.env)
Expand Down Expand Up @@ -129,12 +140,17 @@ def close(self):
self.closing = True
self.is_initialized = False
self.timer.stop()
self.notifier.activated.disconnect(self._on_msg_received)
self.notifier.setEnabled(False)
del self.notifier

if self.notifier is not None:
self.notifier.activated.disconnect(self._on_msg_received)
self.notifier.setEnabled(False)
self.notifier = None

self.request('server_quit')
self.process.waitForFinished(1000)
self.process.close()

if self.process is not None:
self.process.waitForFinished(1000)
self.process.close()
self.context.destroy()

def _on_finished(self):
Expand Down Expand Up @@ -192,11 +208,13 @@ def _send(self, obj):

class PluginClient(AsyncClient):

def __init__(self, plugin_name, executable=None, env=None):
def __init__(self, plugin_name, executable=None, env=None,
extra_path=None):
cwd = os.path.dirname(__file__)
super(PluginClient, self).__init__('plugin_server.py',
executable=executable, cwd=cwd, env=env,
extra_args=[plugin_name], libs=[plugin_name])
extra_args=[plugin_name], libs=[plugin_name],
extra_path=extra_path)
self.name = plugin_name


Expand Down
42 changes: 42 additions & 0 deletions spyder/utils/introspection/tests/test_plugin_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
#
"""Tests for plugin_client.py."""

# Standard library imports
import os.path as osp

# Test library imports
import pytest

# Local imports
from spyder.utils.introspection.plugin_client import PluginClient
from spyder.utils.introspection.manager import PLUGINS


@pytest.mark.parametrize("plugin_name", PLUGINS)
def test_plugin_client(qtbot, plugin_name):
"""Test creation of the diferent plugin clients."""
plugin = PluginClient(plugin_name=plugin_name)

assert plugin


@pytest.mark.parametrize("plugin_name", PLUGINS)
def test_plugin_client_extra_path(qtbot, plugin_name):
"""Test adding of extra path.
Extra path is used for adding spyder_path to plugin clients.
"""
extra_path = '/some/dummy/path'

plugin = PluginClient(plugin_name=plugin_name, extra_path=[extra_path])
plugin.run()
python_path = plugin.process.processEnvironment().value('PYTHONPATH')
assert extra_path in python_path.split(osp.pathsep)


if __name__ == "__main__":
pytest.main()

0 comments on commit 669b6b4

Please sign in to comment.