1
0
forked from VimPlug/jedi

sys path modifications

This commit is contained in:
David Halter
2012-09-14 03:05:31 +02:00
parent 65064b1312
commit 9a2ec13230
8 changed files with 140 additions and 6 deletions

View File

@@ -53,11 +53,11 @@ Jedi supports many of the widely used Python features:
I don't know what to do with them.)
- class decorators (py3k feature, are being ignored too, until I find a use
case, that doesn't work with Jedi)
- simple/usual `sys.path` modifications
However, it does not yet support (and probably will in future versions, because
they are on my todo list):
- `sys.path` modifications
- assert / isinstance
- manipulations of instances outside the instance variables, without using
functions

View File

@@ -10,6 +10,7 @@ import re
import os
import parsing
import modules
import evaluate
import helpers
import settings

View File

@@ -1,13 +1,12 @@
import re
import weakref
import os
import parsing
import dynamic # must be before evaluate, because it needs to be loaded first.
import dynamic
import imports
import evaluate
import modules
import debug
import imports
import settings
import keywords

View File

@@ -115,13 +115,18 @@ class ImportPath(object):
Get the names of all modules in the search_path. This means file names
and not names defined in the files.
"""
if not search_path:
search_path = self.sys_path_with_modifications()
names = []
for module_loader, name, is_pkg in pkgutil.iter_modules(search_path):
inf = float('inf')
inf_pos = (inf, inf)
inf_pos = (float('inf'), float('inf'))
names.append(parsing.Name([(name, inf_pos)], inf_pos, inf_pos))
return names
def sys_path_with_modifications(self):
module = self.import_stmt.get_parent_until()
return modules.sys_path_with_modifications(module)
def follow(self):
"""
Returns the imported modules.

View File

@@ -1,11 +1,16 @@
from __future__ import with_statement
from _compatibility import exec_function
import re
import tokenize
import sys
import os
import parsing
import builtin
import debug
import evaluate
class Module(builtin.CachedModule):
@@ -170,3 +175,64 @@ class ModuleWithCursor(Module):
return self._line_cache[line_nr - 1]
except IndexError:
raise StopIteration()
@evaluate.memoize_default([])
def sys_path_with_modifications(module):
def execute_code(code):
c = "import os; from os.path import *; result=%s"
variables = {}
try:
exec_function(c % code, variables)
except Exception:
return None
try:
return os.path.abspath(variables['result'])
except KeyError:
return None
curdir = os.path.abspath(os.curdir)
try:
os.chdir(os.path.dirname(module.path))
except OSError:
pass
sys_path = list(builtin.module_find_path) # copy
try:
possible_stmts = module.used_names['path']
except KeyError:
return []
for p in possible_stmts:
try:
call = p.get_assignment_calls().get_only_subelement()
except AttributeError:
continue
n = call.name
if not isinstance(n, parsing.Name) or len(n.names) != 3:
continue
if n.names[:2] != ('sys', 'path'):
continue
array_cmd = n.names[2]
if call.execution is None:
continue
exe = call.execution
if not (array_cmd == 'insert' and len(exe) == 2 \
or array_cmd == 'append' and len(exe) == 1):
continue
if array_cmd == 'insert':
exe_type, exe.type = exe.type, parsing.Array.NOARRAY
exe_pop = exe.values.pop(0)
res = execute_code(exe.get_code())
if res:
sys_path.insert(0, res)
exe.type = exe_type
exe.values.insert(0, exe_pop)
elif array_cmd == 'append':
res = execute_code(exe.get_code())
if res:
sys_path.append(res)
# cleanup, back to old directory
os.chdir(curdir)
return sys_path

View File

@@ -900,6 +900,17 @@ class Call(Base):
for y in self.next.generate_call_path():
yield y
def get_code(self):
if self.type == Call.NAME:
s = self.name.get_code()
else:
s = repr(self.name)
if self.execution is not None:
s += '(%s)' % self.execution.get_code()
if self.next is not None:
s += self.next.get_code()
return s
def __repr__(self):
return "<%s: %s>" % \
(self.__class__.__name__, self.name)
@@ -991,6 +1002,34 @@ class Array(Call):
else:
return iter(self.values)
def get_code(self):
def to_str(el):
try:
return el.get_code()
except AttributeError:
return str(el)
map = {Array.NOARRAY: '%s',
Array.TUPLE: '(%s)',
Array.LIST: '[%s]',
Array.DICT: '{%s}',
Array.SET: '{%s}'
}
inner = []
for i, value in enumerate(self.values):
s = ''
try:
key = self.keys[i]
except IndexError:
pass
else:
for el in key[i]:
s += to_str(el)
for el in value:
s += to_str(el)
inner.append(s)
return map[self.type] % ', '.join(inner)
def __repr__(self):
if self.type == self.NOARRAY:
type = 'noarray'

View File

@@ -0,0 +1,22 @@
import sys
import os
from os import dirname
sys.path.insert(0, '../..')
sys.path.append(dirname(os.path.abspath('thirdparty' + os.path.sep + 'asdf')))
# modifications, that should fail:
# because of sys module
sys.path.append(sys.path[1] + '/thirdparty')
# syntax err
sys.path.append('a' +* '/thirdparty')
#? ['evaluate']
import evaluate
#? ['goto']
evaluate.goto
#? ['pylab_']
import pylab_

View File

@@ -12,6 +12,8 @@ from _compatibility import unicode, BytesIO, reduce, literal_eval, is_py25
import functions
import debug
sys.path.pop() # pop again, because it might affect the completion
def run_completion_test(correct, source, line_nr, index, line, path):
"""