again all sort of import related stuff, relative imports work now! fixes #2

This commit is contained in:
David Halter
2012-09-13 15:03:10 +02:00
parent c2d1b2d865
commit 6f0cbf18db
6 changed files with 71 additions and 38 deletions

View File

@@ -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):

View File

@@ -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
return scopes
pos = (line, column)

View File

@@ -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:
if self.import_stmt.relative_count == 0:
names += self.get_module_names()
names += self.get_module_names([self.file_path])
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:
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))
else:
result.append(s)
return result

View File

@@ -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,6 +1427,7 @@ class PyFuzzyParser(object):
else:
n, token_type, tok = self._parsedotname(self.current)
tok_list.pop() # removed last entry, because we add Name
if n:
tok_list.append(n)
if tok == '(':
# it must be a function
@@ -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

View File

@@ -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

View File

@@ -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"