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

frequent traceback on autocomplete #6

Closed
glyph opened this issue Dec 29, 2011 · 10 comments
Closed

frequent traceback on autocomplete #6

glyph opened this issue Dec 29, 2011 · 10 comments

Comments

@glyph
Copy link

glyph commented Dec 29, 2011

I'm not sure what the difference is between when I see this and when autocompletion just works, but I frequently see this in my log:

Traceback (most recent call last):
File "./sublime_plugin.py", line 175, in on_query_completions
File "./python_completions.py", line 64, in on_query_completions
context.project, context.input, loc, context.resource)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/contrib/codeassist.py", line 33, in code_assist
return assist()
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/contrib/codeassist.py", line 325, in call
completions = list(self._code_completions().values())
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/contrib/codeassist.py", line 408, in _code_completions
self._undotted_completions(inner_scope, result, lineno=lineno)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/contrib/codeassist.py", line 351, in _undotted_completions
names = scope.get_names()
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyscopes.py", line 16, in get_names
return self.pyobject.get_attributes()
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjects.py", line 196, in get_attributes
result = dict(self._get_concluded_attributes())
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/utils.py", line 25, in newfunc
return func(self, _args, *_kwds)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjects.py", line 191, in _get_concluded_attributes
self.concluded_attributes.set(self._create_concluded_attributes())
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 127, in _create_concluded_attributes
for base in reversed(self.get_superclasses()):
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 119, in get_superclasses
self._superclasses.set(self._get_bases())
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 135, in _get_bases
base_name)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/evaluate.py", line 25, in eval_node
return eval_node2(scope, node)[1]
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/evaluate.py", line 30, in eval_node2
ast.walk(node, evaluator)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/ast.py", line 34, in walk
return method(node)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/evaluate.py", line 150, in _Attribute
if pyname.get_object() != rope.base.pyobjects.get_unknown():
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/utils.py", line 25, in newfunc
return func(self, _args, *_kwds)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pynames.py", line 158, in get_object
return self._get_imported_pyname().get_object()
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pynames.py", line 149, in _get_imported_pyname
result = self.imported_module.get_object()[self.imported_name]
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjects.py", line 28, in getitem
return self.get_attribute(key)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjects.py", line 202, in get_attribute
if name in self._get_structural_attributes():
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/utils.py", line 25, in newfunc
return func(self, _args, *_kwds)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjects.py", line 184, in _get_structural_attributes
self.structural_attributes = self._create_structural_attributes()
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pyobjectsdef.py", line 225, in _create_structural_attributes
extension_submodules = self.pycore._builtin_submodules(modname)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pycore.py", line 88, in _builtin_submodules
for extension in self.extension_modules:
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/utils.py", line 10, in _wrapper
setattr(self, name, func(self, _args, *_kwds))
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/pycore.py", line 294, in extension_modules
result.update(stdmods.dynload_modules())
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/utils.py", line 74, in call
result = self.func(_args, *_kwds)
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/stdmods.py", line 33, in dynload_modules
dynload_path = os.path.join(_stdlib_path(), 'lib-dynload')
File "/home/glyph/.config/sublime-text-2/Packages/SublimeRope/rope/base/stdmods.py", line 8, in _stdlib_path
import distutils.sysconfig
ImportError: No module named distutils.sysconfig

@OscarL
Copy link
Contributor

OscarL commented Dec 30, 2011

The rope library included in SublimeRope is trying to figure out the path to the installed Python standard lib, and since Julian updated rope (changeset: 92fcb6e) it does this assuming "distutils" is available. That is not always the case (certainly not a stdlib package), and it is not included in SublimeText's Python library (python26.zip).

The specific change was (on rope/base/stdmods.py):

def _stdlib_path():
-    import inspect
-    return os.path.dirname(inspect.getsourcefile(inspect))
+    import distutils.sysconfig
+    return distutils.sysconfig.get_python_lib(standard_lib=True)

The old code always returned 'python26.zip', that is, the Python stdlib, but the one included in SublimeText, not the one for the system-wide Python installation.

@OscarL
Copy link
Contributor

OscarL commented Jan 4, 2012

As a possible solution, I would change that function into this:

def _stdlib_path():
    try:
        # Try to get Python's libs path from the systems's default python interpreter.
        import subprocess
        args = ['python', '-c', 'import os; print os.path.dirname(os.__file__)']
        return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].splitlines()[0]
    except OSError:
        # Get the Python's libs path for the interpreter executing this function.
        import os
        return os.path.dirname(os.__file__)

@glyph
Copy link
Author

glyph commented Jan 4, 2012

Actually, distutils is a standard library package. See http://docs.python.org/library/distutils.html for example - notice the breadcrumbs:

Python v2.7.2 documentation » The Python Standard Library » 27. Python Runtime Services »

@OscarL
Copy link
Contributor

OscarL commented Jan 5, 2012

Silly me. Your are, of course, correct.

The problem you are seeing has, still, the same cause: rope assuming distutils is available on the interpreter that is running it. And as SublimeText2 Python's libs do not include it... we end up having those tracebacks.

So, we patch rope, or ST2 starts to include distutils :-).

@JulianEberius
Copy link
Owner

Hi,

Sorry I didn't have a look at SublimeRope in a long time so I saw your discussion just now.
I do not know what the simplest way of finding the standard lib path is without using distutils...
os.path.dirname(os.file) seems very simple and nice, and I would patch the bundled Rope to use it, but I don't know if this will work on all platforms.

@OscarL
Copy link
Contributor

OscarL commented Jan 6, 2012

Ok. Just for the record, it works on Windows XP (Python 2.5 and 2.7), and I've just tested it on Ubuntu 10.10 (Python 2.6 and 2.7). There, it returns "/usr/lib/python2.6" and "/usr/lib/python2.7", which seems correct to me. I have no access to any OS X system, so that remains untested.

edit: also works on Linux Mint 11 (python 2.7).

@JulianEberius
Copy link
Owner

I have decided for the common solution of using "try... except ImportError"
The old code is executed when distutils can not be imported. This should (in theory) work for everybody.

Greetings,
Julian

@OscarL
Copy link
Contributor

OscarL commented Jan 6, 2012

Looks good to me.

It remains to be seen if there is actually any noticeable difference in returning the lib's path for the interpreter running rope (ST2's py2.6), and the one for the interpreter that will run the code that rope is analyzing (who knows what python version?, that's why I've proposed the "python -c" solution).

On my quick tests, I haven't found anything unusual, at least with the rope's functionality actually used by SublimeRope.

@glyph
Copy link
Author

glyph commented Jan 7, 2012

I like the python -c solution too; ST2's py2.6 may not include source code, and may not include the right version of the source anyway (I'm developing against py2.7).

@JulianEberius
Copy link
Owner

I think choosing the correct Python should be done through a virtualenv. Select "Rope: New Project" in the Command Palette.
Then you can specify the project dir and the virtualenv dir. Even if you do not use virtualenv, I think you should be able to specify your Python's root directory as virtualenv directory. For example, running OSX and installing Python2.7 with Homebrew will put Python in "/usr/local/Cellar/python/2.7.2".
If I give this to "Rope: New Project" it picks up the correct standard lib.

I do no like running a new process (python -c starts a new process) for every completion. But of course it could be done if necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants