mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
again all sort of import related stuff, relative imports work now! fixes #2
This commit is contained in:
@@ -1509,7 +1509,7 @@ def goto(scopes, search_name=None, statement_path_offset=1):
|
||||
if isinstance(s, imports.ImportPath):
|
||||
try:
|
||||
s = s.follow()[0]
|
||||
except imports.ModuleNotFound:
|
||||
except IndexError:
|
||||
continue
|
||||
else:
|
||||
if not isinstance(s, parsing.Module):
|
||||
|
||||
20
functions.py
20
functions.py
@@ -193,21 +193,14 @@ def _prepare_goto(position, source_path, module, goto_path,
|
||||
if isinstance(user_stmt, parsing.Import):
|
||||
import_names = user_stmt.get_all_import_names()
|
||||
count = 0
|
||||
found_count = None
|
||||
kill_count = -1
|
||||
for i in import_names:
|
||||
for name_part in i.names:
|
||||
count += 1
|
||||
if name_part.start_pos <= position <= name_part.end_pos:
|
||||
found_count = count
|
||||
if found_count is None:
|
||||
found_count = count
|
||||
if is_like_search:
|
||||
# is_like_search will decrease also one, so change this here.
|
||||
found_count += 1
|
||||
else:
|
||||
return []
|
||||
if position <= name_part.end_pos:
|
||||
kill_count += 1
|
||||
scopes = [imports.ImportPath(user_stmt, is_like_search,
|
||||
kill_count=(count - found_count), direct_resolve=True)]
|
||||
kill_count=kill_count, direct_resolve=True)]
|
||||
else:
|
||||
# just parse one statement, take it and evaluate it
|
||||
r = parsing.PyFuzzyParser(goto_path, source_path, no_docstr=True)
|
||||
@@ -244,10 +237,7 @@ def get_definition(source, line, column, source_path):
|
||||
for s in scopes.copy():
|
||||
if isinstance(s, imports.ImportPath):
|
||||
scopes.remove(s)
|
||||
try:
|
||||
scopes.update(resolve_import_paths(set(s.follow())))
|
||||
except imports.ModuleNotFound:
|
||||
pass
|
||||
scopes.update(resolve_import_paths(set(s.follow())))
|
||||
return scopes
|
||||
|
||||
pos = (line, column)
|
||||
|
||||
33
imports.py
33
imports.py
@@ -21,8 +21,14 @@ class ImportPath(object):
|
||||
"""
|
||||
An ImportPath is the path of a `parsing.Import` object.
|
||||
"""
|
||||
class GlobalNamespace(object):
|
||||
pass
|
||||
class _GlobalNamespace(object):
|
||||
def get_defined_names(self):
|
||||
return []
|
||||
|
||||
def get_imports(self):
|
||||
return []
|
||||
|
||||
GlobalNamespace = _GlobalNamespace()
|
||||
|
||||
def __init__(self, import_stmt, is_like_search=False, kill_count=0,
|
||||
direct_resolve=False):
|
||||
@@ -45,7 +51,6 @@ class ImportPath(object):
|
||||
for i in range(kill_count + int(is_like_search)):
|
||||
self.import_path.pop()
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s: %s>' % (self.__class__.__name__, self.import_stmt)
|
||||
|
||||
@@ -79,8 +84,13 @@ class ImportPath(object):
|
||||
names = []
|
||||
for scope in self.follow():
|
||||
if scope is ImportPath.GlobalNamespace:
|
||||
names += self.get_module_names()
|
||||
names += self.get_module_names([self.file_path])
|
||||
if self.import_stmt.relative_count == 0:
|
||||
names += self.get_module_names()
|
||||
|
||||
path = os.path.abspath(self.file_path)
|
||||
for i in range(self.import_stmt.relative_count - 1):
|
||||
path = os.path.dirname(path)
|
||||
names += self.get_module_names([path])
|
||||
else:
|
||||
if on_import_stmt and isinstance(scope, parsing.Module) \
|
||||
and scope.path.endswith('__init__.py'):
|
||||
@@ -117,7 +127,13 @@ class ImportPath(object):
|
||||
Returns the imported modules.
|
||||
"""
|
||||
if self.import_path:
|
||||
scope, rest = self._follow_file_system()
|
||||
try:
|
||||
scope, rest = self._follow_file_system()
|
||||
except ModuleNotFound:
|
||||
debug.warning('Module not found: ' + str(self.import_stmt))
|
||||
return []
|
||||
return [ImportPath.GlobalNamespace]
|
||||
|
||||
if len(rest) > 1 or rest and self.is_like_search:
|
||||
scopes = []
|
||||
elif rest:
|
||||
@@ -214,10 +230,7 @@ def strip_imports(scopes):
|
||||
if isinstance(s, parsing.Import):
|
||||
# this is something like a statement following.
|
||||
evaluate.statement_path.append(s)
|
||||
try:
|
||||
result += ImportPath(s).follow()
|
||||
except ModuleNotFound:
|
||||
debug.warning('Module not found: ' + str(s))
|
||||
result += ImportPath(s).follow()
|
||||
else:
|
||||
result.append(s)
|
||||
return result
|
||||
|
||||
34
parsing.py
34
parsing.py
@@ -515,7 +515,7 @@ class Import(Simple):
|
||||
:type defunct: bool
|
||||
"""
|
||||
def __init__(self, start_pos, end_pos, namespace, alias=None, \
|
||||
from_ns=None, star=False, relative_count=None, defunct=False):
|
||||
from_ns=None, star=False, relative_count=0, defunct=False):
|
||||
super(Import, self).__init__(start_pos, end_pos)
|
||||
|
||||
self.namespace = namespace
|
||||
@@ -1138,6 +1138,10 @@ class PyFuzzyParser(object):
|
||||
else:
|
||||
token_type, tok = pre_used_token
|
||||
|
||||
if token_type != tokenize.NAME and tok != '*':
|
||||
# token maybe a name or star
|
||||
return (None, token_type, tok)
|
||||
|
||||
append((tok, self.start_pos))
|
||||
first_pos = self.start_pos
|
||||
while True:
|
||||
@@ -1175,6 +1179,8 @@ class PyFuzzyParser(object):
|
||||
while True:
|
||||
defunct = False
|
||||
token_type, tok = self.next()
|
||||
if token_type == tokenize.ENDMARKER:
|
||||
break
|
||||
if brackets and tok == '\n':
|
||||
self.next()
|
||||
if tok == '(': # python allows only one `(` in the statement.
|
||||
@@ -1421,15 +1427,16 @@ class PyFuzzyParser(object):
|
||||
else:
|
||||
n, token_type, tok = self._parsedotname(self.current)
|
||||
tok_list.pop() # removed last entry, because we add Name
|
||||
tok_list.append(n)
|
||||
if tok == '(':
|
||||
# it must be a function
|
||||
used_funcs.append(n)
|
||||
else:
|
||||
used_vars.append(n)
|
||||
if string and re.match(r'[\w\d\'"]', string[-1]):
|
||||
string += ' '
|
||||
string += ".".join(n.names)
|
||||
if n:
|
||||
tok_list.append(n)
|
||||
if tok == '(':
|
||||
# it must be a function
|
||||
used_funcs.append(n)
|
||||
else:
|
||||
used_vars.append(n)
|
||||
if string and re.match(r'[\w\d\'"]', string[-1]):
|
||||
string += ' '
|
||||
string += ".".join(n.names)
|
||||
continue
|
||||
elif '=' in tok and not tok in ['>=', '<=', '==', '!=']:
|
||||
# there has been an assignement -> change vars
|
||||
@@ -1474,7 +1481,7 @@ class PyFuzzyParser(object):
|
||||
except AttributeError:
|
||||
debug.warning('return in non-function')
|
||||
|
||||
if list_comp or tok in always_break:
|
||||
if tok in always_break:
|
||||
self.gen.push_back(self._current_full)
|
||||
return stmt, tok
|
||||
|
||||
@@ -1584,9 +1591,11 @@ class PyFuzzyParser(object):
|
||||
debug.warning("from: syntax error@%s" %
|
||||
self.start_pos[0])
|
||||
defunct = True
|
||||
if tok != 'import':
|
||||
self.gen.push_back(self._current_full)
|
||||
names = self._parseimportlist()
|
||||
for name, alias, defunct2 in names:
|
||||
star = name.names[0] == '*'
|
||||
star = name is not None and name.names[0] == '*'
|
||||
if star:
|
||||
name = None
|
||||
i = Import(first_pos, self.end_pos, name, alias, mod,
|
||||
@@ -1596,6 +1605,7 @@ class PyFuzzyParser(object):
|
||||
if not names:
|
||||
i = Import(first_pos, self.end_pos, mod, defunct=True,
|
||||
relative_count=relative_count)
|
||||
print i, repr(mod)
|
||||
self._check_user_stmt(i)
|
||||
self.scope.add_import(i)
|
||||
self.freshscope = False
|
||||
|
||||
@@ -172,6 +172,10 @@ mod1.
|
||||
#? str()
|
||||
imp_tree.a
|
||||
|
||||
|
||||
# -----------------
|
||||
# special positions -> edge cases
|
||||
# -----------------
|
||||
import datetime
|
||||
|
||||
#? 6 datetime
|
||||
@@ -187,3 +191,13 @@ from import_tree. import pkg
|
||||
|
||||
#? 18 ['pkg']
|
||||
from import_tree.p import pkg
|
||||
|
||||
#? 17 ['import_tree']
|
||||
from .import_tree import
|
||||
#? 10 ['run']
|
||||
from ..run import
|
||||
#? ['run']
|
||||
from .. import run
|
||||
|
||||
#? []
|
||||
from not_a_module import
|
||||
|
||||
@@ -87,6 +87,12 @@ class TestRegression(unittest.TestCase):
|
||||
assert self.get_def("import sys_blabla", (1, 8)) == []
|
||||
assert len(self.get_def("import sys", (1, 8))) == 1
|
||||
|
||||
def test_complete_on_empty_import(self):
|
||||
# should just list the files in the directory
|
||||
assert 10 < len(self.complete("from .", (1, 5))) < 30
|
||||
assert 10 < len(self.complete("from . import", (1, 5))) < 30
|
||||
assert 10 < len(self.complete("from . import classes", (1, 5))) < 30
|
||||
|
||||
def test_new(self):
|
||||
""" This is just to try out things, removing or deleting it is ok. """
|
||||
s = ("def abc(): pass\n"
|
||||
|
||||
Reference in New Issue
Block a user