class RequestHandler(QObject):
    """Handle introspection request.
    """

    introspection_complete = Signal()

    def __init__(self, code_info, plugins):
        super(RequestHandler, self).__init__()
        self.info = code_info
        self.timer = QTimer()
        self.timer.singleShot(LEAD_TIME_SEC * 1000, self._handle_timeout)
        self.waiting = True
        self.pending = {}
        self.result = None
        self.plugins = plugins
        self._start_time = time.time()
        self._threads = {}
        for plugin in plugins:
            self._make_async_call(plugin, code_info)

    def _handle_timeout(self):
        debug_print('got timeout: %s' % self.plugins)
        if self.pending:
            for plugin in self.plugins:
                if plugin.name in self.pending:
                    self._finalize(plugin.name, self.pending[plugin.name])
                    return
        self.waiting = False

    def _handle_incoming(self, name):
        # coerce to a str in case it is a QString
        name = str(name)
        self._threads[name].wait()
        if self.result:
            return
        result = self._threads[name].result
        if name == self.plugins[0].name or not self.waiting:
            if result:
                self._finalize(name, result)
            else:
                debug_print('No valid responses acquired')
                self.introspection_complete.emit()
        else:
            self.pending[name] = result

    def _make_async_call(self, plugin, info):
        """Trigger an introspection job in a thread"""
        self._threads[str(plugin.name)] = thread = IntrospectionThread(
            plugin, info)
        thread.request_handled.connect(self._handle_incoming)
        thread.start()

    def _finalize(self, name, result):
        self.result = result
        self.waiting = False
        self.pending = None
        delta = time.time() - self._start_time
        debug_print('%s request from %s finished: "%s" in %.1f sec' %
                    (self.info.name, name, str(result)[:100], delta))
        self.introspection_complete.emit()
class RequestHandler(QObject):

    """Handle introspection request.
    """

    introspection_complete = Signal()

    def __init__(self, code_info, plugins):
        super(RequestHandler, self).__init__()
        self.info = code_info
        self.timer = QTimer()
        self.timer.singleShot(LEAD_TIME_SEC * 1000, self._handle_timeout)
        self.waiting = True
        self.pending = {}
        self.result = None
        self.plugins = plugins
        self._start_time = time.time()
        self._threads = {}
        for plugin in plugins:
            self._make_async_call(plugin, code_info)

    def _handle_timeout(self):
        debug_print('got timeout: %s' % self.plugins)
        if self.pending:
            for plugin in self.plugins:
                if plugin.name in self.pending:
                    self._finalize(plugin.name, self.pending[plugin.name])
                    return
        self.waiting = False

    def _handle_incoming(self, name):
        # coerce to a str in case it is a QString
        name = str(name)
        self._threads[name].wait()
        if self.result:
            return
        result = self._threads[name].result
        if name == self.plugins[0].name or not self.waiting:
            if result:
                self._finalize(name, result)
            else:
                debug_print('No valid responses acquired')
                self.introspection_complete.emit()
        else:
            self.pending[name] = result

    def _make_async_call(self, plugin, info):
        """Trigger an introspection job in a thread"""
        self._threads[str(plugin.name)] = thread = IntrospectionThread(plugin, info)
        thread.request_handled.connect(self._handle_incoming)
        thread.start()

    def _finalize(self, name, result):
        self.result = result
        self.waiting = False
        self.pending = None
        delta = time.time() - self._start_time
        debug_print('%s request from %s finished: "%s" in %.1f sec'
            % (self.info.name, name, str(result)[:100], delta))
        self.introspection_complete.emit()
Exemple #3
0
    def focusOutEvent(self, event):
        """Handle focus out event restoring the last valid selected path."""
        # Calling asynchronously the 'add_current_text' to avoid crash
        # https://groups.google.com/group/spyderlib/browse_thread/thread/2257abf530e210bd
        lineedit = self.lineEdit()
        QTimer.singleShot(50, lambda: lineedit.setText(self.selected_text))

        hide_status = getattr(self.lineEdit(), 'hide_status_icon', None)
        if hide_status:
            hide_status()
        QComboBox.focusOutEvent(self, event)
Exemple #4
0
 def follow_directories_loaded(self, fname):
     """Follow directories loaded during startup"""
     if self._to_be_loaded is None:
         return
     path = osp.normpath(to_text_string(fname))
     if path in self._to_be_loaded:
         self._to_be_loaded.remove(path)
     if self._to_be_loaded is not None and len(self._to_be_loaded) == 0 and not is_pyqt46:
         self.fsmodel.directoryLoaded.disconnect(self.follow_directories_loaded)
         if self._scrollbar_positions is not None:
             # The tree view need some time to render branches:
             QTimer.singleShot(50, self.restore_scrollbar_positions)
Exemple #5
0
 def follow_directories_loaded(self, fname):
     """Follow directories loaded during startup"""
     if self._to_be_loaded is None:
         return
     path = osp.normpath(to_text_string(fname))
     if path in self._to_be_loaded:
         self._to_be_loaded.remove(path)
     if self._to_be_loaded is not None and len(self._to_be_loaded) == 0:
         self.disconnect(self.fsmodel, SIGNAL('directoryLoaded(QString)'),
                         self.follow_directories_loaded)
         if self._scrollbar_positions is not None:
             # The tree view need some time to render branches:
             QTimer.singleShot(50, self.restore_scrollbar_positions)
Exemple #6
0
 def follow_directories_loaded(self, fname):
     """Follow directories loaded during startup"""
     if self._to_be_loaded is None:
         return
     path = osp.normpath(unicode(fname))
     if path in self._to_be_loaded:
         self._to_be_loaded.pop(self._to_be_loaded.index(path))
     if self._to_be_loaded is not None and len(self._to_be_loaded) == 0:
         self.disconnect(self.fsmodel, SIGNAL('directoryLoaded(QString)'),
                         self.follow_directories_loaded)
         if self._scrollbar_positions is not None:
             # The tree view need some time to render branches:
             QTimer.singleShot(50, self.restore_scrollbar_positions)
Exemple #7
0
    def event(self, event):
        """Qt Override.

        Filter tab keys and process double tab keys.
        """
        if (event.type() == QEvent.KeyPress) and (event.key() == Qt.Key_Tab):
            self.sig_tab_pressed.emit(True)
            self.numpress += 1
            if self.numpress == 1:
                self.presstimer = QTimer.singleShot(400, self.handle_keypress)
            return True
        return QComboBox.event(self, event)
Exemple #8
0
 def focusOutEvent(self, event):
     """Handle focus out event"""
     # Calling asynchronously the 'add_current_text' to avoid crash
     # https://groups.google.com/group/spyderlib/browse_thread/thread/2257abf530e210bd
     QTimer.singleShot(50, self.add_current_text_if_valid)
     QComboBox.focusOutEvent(self, event)
Exemple #9
0
class PluginManager(QObject):

    introspection_complete = Signal(object)

    def __init__(self, executable):
        super(PluginManager, self).__init__()
        plugins = OrderedDict()
        for name in PLUGINS:
            try:
                plugin = PluginClient(name, executable)
                plugin.run()
            except Exception as e:
                debug_print('Introspection Plugin Failed: %s' % name)
                debug_print(str(e))
                continue
            debug_print('Introspection Plugin Loaded: %s' % name)
            plugins[name] = plugin
            plugin.received.connect(self.handle_response)
        self.plugins = plugins
        self.timer = QTimer()
        self.desired = []
        self.ids = dict()
        self.info = None
        self.request = None
        self.pending = None
        self.pending_request = None
        self.waiting = False

    def send_request(self, info):
        """Handle an incoming request from the user."""
        if self.waiting:
            if info.serialize() != self.info.serialize():
                self.pending_request = info
            else:
                debug_print('skipping duplicate request')
            return
        debug_print('%s request' % info.name)
        desired = None
        self.info = info
        editor = info.editor
        if (info.name == 'completion' and 'jedi' not in self.plugins
                and info.line.lstrip().startswith(('import ', 'from '))):
            desired = 'fallback'

        if ((not editor.is_python_like()) or sourcecode.is_keyword(info.obj)
                or (editor.in_comment_or_string() and info.name != 'info')):
            desired = 'fallback'

        plugins = self.plugins.values()
        if desired:
            plugins = [self.plugins[desired]]
            self.desired = [desired]
        elif (info.name == 'definition' and not info.editor.is_python()
              or info.name == 'info'):
            self.desired = list(self.plugins.keys())
        else:
            # Use all but the fallback
            plugins = list(self.plugins.values())[:-1]
            self.desired = list(self.plugins.keys())[:-1]

        self._start_time = time.time()
        self.waiting = True
        method = 'get_%s' % info.name
        value = info.serialize()
        self.ids = dict()
        for plugin in plugins:
            request_id = plugin.request(method, value)
            self.ids[request_id] = plugin.name
        self.timer.stop()
        self.timer.singleShot(LEAD_TIME_SEC * 1000, self._handle_timeout)

    def validate(self):
        for plugin in self.plugins.values():
            plugin.request('validate')

    def handle_response(self, response):
        name = self.ids.get(response['request_id'], None)
        if not name:
            return
        if response.get('error', None):
            debug_print('Response error:', response['error'])
            return
        if name == self.desired[0] or not self.waiting:
            if response.get('result', None):
                self._finalize(response)
        else:
            self.pending = response

    def close(self):
        [plugin.close() for plugin in self.plugins]

    def _finalize(self, response):
        self.waiting = False
        self.pending = None
        if self.info:
            delta = time.time() - self._start_time
            debug_print('%s request from %s finished: "%s" in %.1f sec' %
                        (self.info.name, response['name'],
                         str(response['result'])[:100], delta))
            response['info'] = self.info
            self.introspection_complete.emit(response)
            self.info = None
        if self.pending_request:
            info = self.pending_request
            self.pending_request = None
            self.send_request(info)

    def _handle_timeout(self):
        self.waiting = False
        if self.pending:
            self._finalize(self.pending)
        else:
            debug_print('No valid responses acquired')
Exemple #10
0
 def focusOutEvent(self, event):
     """Handle focus out event"""
     # Calling asynchronously the 'add_current_text' to avoid crash
     # https://groups.google.com/group/spyderlib/browse_thread/thread/2257abf530e210bd
     QTimer.singleShot(50, self.add_current_text_if_valid)
     QComboBox.focusOutEvent(self, event)
Exemple #11
0
class PluginManager(QObject):

    introspection_complete = Signal(object)

    def __init__(self, executable):
        super(PluginManager, self).__init__()
        plugins = OrderedDict()
        for name in PLUGINS:
            try:
                plugin = PluginClient(name, executable)
            except Exception as e:
                debug_print('Introspection Plugin Failed: %s' % name)
                debug_print(str(e))
                continue
            debug_print('Introspection Plugin Loaded: %s' % name)
            plugins[name] = plugin
            plugin.request_handled.connect(self.handle_response)
        self.plugins = plugins
        self.timer = QTimer()
        self.desired = []
        self.info = None
        self.request = None
        self.pending = None
        self.pending_request = None
        self.waiting = False

    def send_request(self, info):
        """Handle an incoming request from the user."""
        if self.waiting:
            if info.serialize() != self.info.serialize():
                self.pending_request = info
            else:
                debug_print('skipping duplicate request')
            return
        debug_print('%s request' % info.name)
        desired = None
        self.info = info
        editor = info.editor
        if (info.name == 'completion' and 'jedi' not in self.plugins and
                info.line.lstrip().startswith(('import ', 'from '))):
            desired = 'fallback'

        if ((not editor.is_python_like()) or
                sourcecode.is_keyword(info.obj) or
                (editor.in_comment_or_string() and info.name != 'info')):
            desired = 'fallback'

        plugins = self.plugins.values()
        if desired:
            plugins = [self.plugins[desired]]
            self.desired = [desired]
        elif (info.name == 'definition' and not info.editor.is_python() or
              info.name == 'info'):
            self.desired = list(self.plugins.keys())
        else:
            # Use all but the fallback
            plugins = list(self.plugins.values())[:-1]
            self.desired = list(self.plugins.keys())[:-1]

        self._start_time = time.time()
        self.waiting = True
        request = dict(method='get_%s' % info.name,
                       args=[info.serialize()],
                       request_id=id(info))
        for plugin in plugins:
            plugin.send(request)
            debug_print('sending %s' % (plugin.plugin_name))
        self.timer.stop()
        self.timer.singleShot(LEAD_TIME_SEC * 1000, self._handle_timeout)
        self.request = request

    def validate(self):
        message = dict(method='validate')
        for plugin in self.plugins.values():
            plugin.send(message)

    def handle_response(self, response):
        if (self.request is None):
            return
        if (response.get('request_id', None) != id(self.info)):
            return
        name = response['plugin_name']
        response['info'] = self.info
        if response.get('error', None):
            debug_print('Response error:', response['error'])
            return
        if name == self.desired[0] or not self.waiting:
            if response.get('result', None):
                self._finalize(response)
        else:
            self.pending = response

    def close(self):
        [plugin.close() for plugin in self.plugins]

    def _finalize(self, response):
        self.waiting = False
        self.pending = None
        delta = time.time() - self._start_time
        debug_print(str(response.keys()))
        debug_print('%s request from %s finished: "%s" in %.1f sec'
            % (self.info.name, response['plugin_name'],
               str(response['result'])[:100], delta))
        self.introspection_complete.emit(response)
        self.info = None
        if self.pending_request:
            info = self.pending_request
            self.pending_request = None
            self.send_request(info)

    def _handle_timeout(self):
        self.waiting = False
        if self.pending:
            self._finalize(self.pending)
        else:
            debug_print('No valid responses acquired', self.request['method'])
Exemple #12
0
 def refresh_plugin(self):
     """Refresh widget"""
     if self._starting_up:
         self._starting_up = False
         QTimer.singleShot(5000, self.refresh_plugin)
     self.set_object_text(None, force_refresh=False)