Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a new Async Server approach based on pyzmq to get completions on the Editor #3049

Merged
merged 8 commits into from
Mar 13, 2016
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,18 @@ a Python version greater than 2.7 (Python 3.2 is not supported anymore).
* **Python** 2.7 or 3.3+
* **PyQt5** 5.2+ or **PyQt4** 4.6+: PyQt5 is recommended.
* **qtconsole**: Enhanced Python interpreter.
* **Rope** and **Jedi**: Editor code completion, calltips
* **Rope** and **Jedi**: Editor code completion, calltips.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to put a dot at the end here. Please notice that the text continues in the next line :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

and go-to-definition.
* **Pyflakes**: Real-time code analysis.
* **Sphinx**: Rich text mode for the Help pane
* **Sphinx**: Rich text mode for the Help pane.
* **Pygments**: Syntax highlighting for all file types it supports.
* **Pylint**: Static code analysis.
* **Pep8**: Style analysis.
* **Psutil**: CPU and memory usage on the status bar.
* **Nbconvert**: Manipulation of notebooks in the Editor.
* **Qtawesome**: To have an icon theme based on FontAwesome
* **Pickleshare**: Show import completions on the Python consoles
* **Qtawesome**: To have an icon theme based on FontAwesome.
* **Pickleshare**: Show import completions on the Python consoles.
* **PyZMQ**: Run introspection services asynchronously.

### Optional dependencies

Expand Down
1 change: 1 addition & 0 deletions conda.recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ requirements:
- psutil
- pylint
- qtawesome
- pyzmq
- python.app [osx]

about:
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ def run(self):
'pylint',
'psutil',
'qtawesome',
'pickleshare'
'pickleshare',
'pyzmq'
]

if 'setuptools' in sys.modules:
Expand Down
31 changes: 14 additions & 17 deletions spyderlib/utils/introspection/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,18 @@ def __init__(self, executable):
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.request_handled.connect(self.handle_response)
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
Expand Down Expand Up @@ -98,28 +100,23 @@ def send_request(self, info):

self._start_time = time.time()
self.waiting = True
request = dict(method='get_%s' % info.name,
args=[info.serialize()],
request_id=id(info))
method = 'get_%s' % info.name
value = info.serialize()
self.ids = dict()
for plugin in plugins:
plugin.send(request)
debug_print('sending %s' % (plugin.plugin_name))
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)
self.request = request

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

def handle_response(self, response):
if (self.request is None):
name = self.ids.get(response['request_id'], None)
if not name:
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
Expand All @@ -136,10 +133,10 @@ 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'],
% (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:
Expand All @@ -152,7 +149,7 @@ def _handle_timeout(self):
if self.pending:
self._finalize(self.pending)
else:
debug_print('No valid responses acquired', self.request['method'])
debug_print('No valid responses acquired')


class IntrospectionManager(QObject):
Expand Down
Loading