Sublime Forum

Python Completion and GotoDefinition plugin using Rope

#1

Hello everyone,

I started porting my TextMate bundle RopeMate to ST2. It integrates the python refactoring/completion library Rope (http://rope.sourceforge.net/) into ST2 to enable python auto-completion and Goto-Definition. Testers welcome!

github.com/JulianEberius/SublimeRope

Just unzip/git clone the folder SublimeRope into the Packages directory. Single-file completion works instantly, for project-wide completion you need minimal configuration (see README for details).

I’m looking forward to feedback!

p.s.: Don’t despair if the first completion on a new project takes long, just wait a moment. Rope indexes the project and stores the information, so subsequent completions should be fast.

Edit:
The package has been updated. Apart from various fixes to completion and GotoDefinition it also has new features:

  • “Rope: New Project” command added to the command palette to help with project setup
  • “Rope: Show Documentation” command, which shows the docstring of the word under the cursor
  • “Rope Refactor: Rename” command now works quite well (project-wide renaming)
0 Likes

#2

Hi, it’s great idea!

I used Rope when I used emacs.

Keep it up!

0 Likes

#3

This sounds great. However, when I have SublimeRope in my packages directory, pressing ctrl+spacebar makes Sublime hang. Endless spinning beachball.

I may be doing something unexpected, in that I use Sublime to open individual files from the command line, not projects. I assumed the point of the .ropeproject was so that it could find the project root anyway. Does whether I’m in a project affect anything?

0 Likes

#4

Good luck. Looking forward to next release.

0 Likes

#5

Any plans on doing something with pysmell?

I think that it works better than rope in terms of autocompletion (using django).

Maybe I could help developing a plugin for pysmell based on yours.

Great work anyway! :smiley:

Cheers

0 Likes

#6

@ggayan:
I played around with it, but I still like Rope better (don’t have to update tags, refactoring options etc.)
I attach my version of “SublimeSmell” :wink: so you can improve it if you want. I’ll stick with Rope.
Concerning Django: for me it works with Django. Remember that Sublime Text 2 may not use the same Python version as you (e.g. on OSX, it uses the system 2.6), so you may have to add your Django installation to the python_path in .ropeproject/config.py.
As written in the documentation, in my case I add

prefs.add('python_path', '/usr/local/Cellar/python/2.7.1/lib/python2.7/site-packages')

So that ST2 picks up my 2.7 packages.
Then I add the parent dir of my project dir, because the imports in Django include the root package of the project (they don’t use relative imports).
Basically, just make sure that everything you want to see completed is on the python path using config.py.

E.g.

prefs.add('python_path', '/Users/ebi/my_django_projects')

Then Rope completes everything for me, both Django and my Django code.

@rspeer
I think its a performance problem with Rope. If there are a lot of packages Rope will have to index them all, which takes a long time. I also had the same problem when working with “from X import *” on big modules, e.g., PyObjc. Every completion would take ~12 seconds, as Rope would always index the complete Objective-C/Cocoa API and not cache anything (for some reason). In the current version I disabled star imports in Rope, so it works for me.
In your case, try to use it in some project dir, not in your package dir and see if the problem persists.

edit: I have updated the documentation on GitHub to explain the issues with Rope and the Python path.
SublimeSmell.zip (69.1 KB)

0 Likes

#7

great, thanks!

probably i didn’t made the right configuration with rope; I’ll give it another change.

I’ll be glad to contribute if you need to, my github user is ggayan

Keep up the good work!

0 Likes

#8

The package has been updated. Apart from various fixes to completion and GotoDefinition it also has new features:

  • “Rope: New Project” command added to the command palette to help with project setup
  • “Rope: Show Documentation” command, which shows the docstring of the word under the cursor
  • “Rope Refactor: Rename” command now works quite well (project-wide renaming)

With ShowDocumentation, GoToDefinition and Rename (+completions) Sublime Text almost becomes a Python IDE :wink:

0 Likes

#9

Great, many thanks, with rope power, sublime becomes really useful for me.

0 Likes

#10

Hey! I am new to ST2. I just installed this plugin and it seems very useful so far.

Question: why is it that this plugin works when I place it in my ‘Packages’ directory (relative to the ST2 directory), but not when I put it in ‘Packages/User’ ? I suspect that this question applies more generally to ST2 rather than just this plugin; in saying that, I’ve otherwise been fine installing packages to ‘Packages/User’. Mac OS X Lion.

Thanks.

0 Likes

#11

This a fantastic plugin. Thanks!

0 Likes

#12

How does this compare to SublimeCodeIntel? Or are they compatible together?

0 Likes

#13

Really though, is this compatible with SublimeCodeIntel? Can someone confirm this? Or just give me an overview of this vs SublimeCodeIntel?

0 Likes

#14

Hi there,

I’ve been using SublimeRope pretty much since I first discovered ST2 a couple of weeks ago, and many thanks to Julian Eberius for such an amazing contribution—(I hope you can buy a beer with €5)

Is it possible to get relative paths to work in .ropeproject/config.py? I often work on my work box and my home box, and while they are both Macs, I have different usernames and keep my projects in different paths, so I’d love to be able to define the directories for ‘source_folders’ and ‘python_path’ as from the root of the project, but everything I’ve tried seems to fail (other than absolute paths, which I then have to change whenever I switch workstations).

I tried using os.listdir() from the project_opened method, to see where config.py is running from, and it seems like it’s running from the root directory of the machine…

I suppose a heavy-handed approach would be to write a bash script, or something else like this, which will return the actual directory where the project resides (be it at home, work, etc), and then pass that to config.py so it can use it as a prefix. Is there anything simpler that I’m missing?

The importance of this more evident when working with a team—I’d love to get the other developers hooked on ST2 :smile:

Thanks again!

0 Likes

#15

I’m having trouble getting auto imports to work for modules located outside the project. I have added

prefs.add('python_path', 'C:\\PathToMyOtherProjectsSrc')

in config.py but Rope does not seem to index these directories.I’ve tried to debug Rope but I’m getting nowhere. Could it be a Windows issue? Is Rope expecting Windows directory paths to be on a different format?

0 Likes

#16

If you read the comments directly above the examples of prefs.add(), you’ll see that it says to use / regardless of the platform you’re running on.

Hope that helps!

0 Likes

#17

Does this plugin provide assistance when entering function parameters, or is it simply a word list?
Does it suggest standard Python functions, or only those from the current project?

(I’m a little reluctant to install, and explore it, just to answer these two questions :smile: )

0 Likes

#18

I have been using this plugin along side SublimeCodeIntel with no problem.

Where SublimeCodeIntel will fall short (go-to definition, for instance), this tends to work better, given the required setup (you DID read the readme, right?) to point it to your standard/virtualenv path(s).

That said, are either perfect? No – but in running comparisons of CodeIntel against KomodoEdit (where the auto-complete engine is pulled from) I get similar results.

Additionally, the refactoring tools in Rope are nice – when they work.
I haven’t taken the time to debug the root cause, but I’m finding it to be a 50/50 shot at success.

-my $.02

0 Likes

#19

Here’s what I did, using the handy python var file and os.path:

from os import path
prefs.add('python_path', path.normpath(path.join(path.dirname(path.realpath(__file__)), '../../lib/python2.7/site-packages')))

As you might infer, my config.py is located in /Users/matt/Project/env/project/.ropeproject/config.py, so I have to go up two directories and then traverse back down to site-packages.

0 Likes

#20

I just got started with Sublime Text and have some trouble getting this plugin to work. Here is the error message I get when I try to use “Show Documentation” on highlighted text. Oddly, some other Rope commands (e.g., Go to Global) seem to be working okay. Any ideas?

Traceback (most recent call last): File "./sublime_plugin.py", line 362, in run_ File "./sublime_rope.py", line 146, in run maxfixes=3) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/contrib/codeassist.py", line 59, in get_doc pyname = fixer.pyname_at(offset) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/contrib/fixsyntax.py", line 63, in pyname_at return new_pyname() File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/contrib/fixsyntax.py", line 61, in new_pyname return rope.base.evaluate.eval_location(pymodule, newoffset) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 11, in eval_location return eval_location2(pymodule, offset)[1] File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 17, in eval_location2 return pyname_finder.get_primary_and_pyname_at(offset) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 108, in get_primary_and_pyname_at return eval_str2(holding_scope, name) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 44, in eval_str2 return eval_node2(holding_scope, node) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 30, in eval_node2 ast.walk(node, evaluator) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/ast.py", line 36, in walk walk(child, walker) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/ast.py", line 36, in walk walk(child, walker) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/ast.py", line 34, in walk return method(node) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 146, in _Attribute pyname = eval_node(self.scope, node.value) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 25, in eval_node return eval_node2(scope, node)[1] File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 30, in eval_node2 ast.walk(node, evaluator) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/ast.py", line 34, in walk return method(node) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 157, in _Call primary, pyobject = self._get_primary_and_object_for_node(node.func) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 277, in _get_primary_and_object_for_node primary, pyname = eval_node2(self.scope, stmt) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 30, in eval_node2 ast.walk(node, evaluator) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/ast.py", line 34, in walk return method(node) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 146, in _Attribute pyname = eval_node(self.scope, node.value) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 25, in eval_node return eval_node2(scope, node)[1] File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 30, in eval_node2 ast.walk(node, evaluator) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/ast.py", line 34, in walk return method(node) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/evaluate.py", line 143, in _Name self.result = self.scope.lookup(node.id) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyscopes.py", line 48, in lookup return self.parent._propagated_lookup(name) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyscopes.py", line 62, in _propagated_lookup if name in self.get_propagated_names(): File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyscopes.py", line 59, in get_propagated_names return self.get_names() File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyscopes.py", line 127, in get_names result.update(super(GlobalScope, self).get_names()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyscopes.py", line 16, in get_names return self.pyobject.get_attributes() File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjects.py", line 196, in get_attributes result = dict(self._get_concluded_attributes()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/utils.py", line 25, in newfunc return func(self, *args, **kwds) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjects.py", line 191, in _get_concluded_attributes self.concluded_attributes.set(self._create_concluded_attributes()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/utils.py", line 25, in newfunc return func(self, *args, **kwds) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 191, in _create_concluded_attributes result.update(star_import.get_names()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 534, in get_names for name in imported: File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjects.py", line 65, in __iter__ return iter(self.get_attributes()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjects.py", line 196, in get_attributes result = dict(self._get_concluded_attributes()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/utils.py", line 25, in newfunc return func(self, *args, **kwds) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjects.py", line 191, in _get_concluded_attributes self.concluded_attributes.set(self._create_concluded_attributes()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/utils.py", line 25, in newfunc return func(self, *args, **kwds) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 191, in _create_concluded_attributes result.update(star_import.get_names()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 533, in get_names imported = self.imported_module.get_object() File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pynames.py", line 130, in get_object if self._get_pymodule() is None: File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pynames.py", line 120, in _get_pymodule self._current_folder()) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pycore.py", line 84, in get_module return self.resource_to_pyobject(module) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pycore.py", line 194, in resource_to_pyobject return self.module_cache.get_pymodule(resource, force_errors) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pycore.py", line 320, in get_pymodule force_errors=force_errors) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 153, in __init__ source, node = self._init_source(pycore, source, resource) File "/Users/Stephan/Library/Application Support/Sublime Text 2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 182, in _init_source raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) rope.base.exceptions.ModuleSyntaxError: Syntax error in file <utils.py> line <127>: invalid syntax

0 Likes