mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 06:24:27 +08:00
relative imports should work now
This commit is contained in:
@@ -46,6 +46,7 @@ Jedi supports many of the widely used Python features:
|
|||||||
`__get__`, `__getitem__`, `__init__`
|
`__get__`, `__getitem__`, `__init__`
|
||||||
- support for list.append, set.add, list.extend, etc.
|
- support for list.append, set.add, list.extend, etc.
|
||||||
- (nested) list comprehensions / ternary expressions
|
- (nested) list comprehensions / ternary expressions
|
||||||
|
- relative imports
|
||||||
- function annotations (py3k feature, are ignored right now, but being parsed.
|
- function annotations (py3k feature, are ignored right now, but being parsed.
|
||||||
I don't know what to do with them.)
|
I don't know what to do with them.)
|
||||||
- class decorators (py3k feature, are being ignored too, until I find a use
|
- class decorators (py3k feature, are being ignored too, until I find a use
|
||||||
@@ -59,7 +60,6 @@ they are on my todo list):
|
|||||||
- manipulations of instances outside the instance variables, without using
|
- manipulations of instances outside the instance variables, without using
|
||||||
functions
|
functions
|
||||||
- mro
|
- mro
|
||||||
- relative imports
|
|
||||||
- operation support -> \_\_mul\_\_, \_\_add\_\_, etc.
|
- operation support -> \_\_mul\_\_, \_\_add\_\_, etc.
|
||||||
- assert / isinstance
|
- assert / isinstance
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ statement.
|
|||||||
TODO magic methods: __mul__, __add__, etc.
|
TODO magic methods: __mul__, __add__, etc.
|
||||||
TODO evaluate asserts/isinstance (type safety)
|
TODO evaluate asserts/isinstance (type safety)
|
||||||
|
|
||||||
python 3 stuff:
|
TODO nonlocal statement, needed or can be ignored? (py3k)
|
||||||
TODO nonlocal statement, needed or can be ignored?
|
|
||||||
|
|
||||||
TODO __ instance attributes should not be visible outside of the class.
|
TODO __ instance attributes should not be visible outside of the class.
|
||||||
TODO getattr / __getattr__ / __getattribute__ ?
|
TODO getattr / __getattr__ / __getattribute__ ?
|
||||||
|
|||||||
18
imports.py
18
imports.py
@@ -121,15 +121,22 @@ class ImportPath(object):
|
|||||||
def follow_file_system(self):
|
def follow_file_system(self):
|
||||||
"""
|
"""
|
||||||
Find a module with a path (of the module, like usb.backend.libusb10).
|
Find a module with a path (of the module, like usb.backend.libusb10).
|
||||||
TODO: relative imports
|
|
||||||
"""
|
"""
|
||||||
def follow_str(ns, string):
|
def follow_str(ns, string):
|
||||||
debug.dbg('follow_module', ns, string)
|
debug.dbg('follow_module', ns, string)
|
||||||
if ns:
|
|
||||||
return imp.find_module(string, [ns[1]])
|
|
||||||
else:
|
|
||||||
path = None
|
path = None
|
||||||
debug.dbg('search_module', string, path, self.file_path)
|
if ns:
|
||||||
|
path = ns[1]
|
||||||
|
elif self.import_stmt.relative_count:
|
||||||
|
module = self.import_stmt.get_parent_until()
|
||||||
|
path = os.path.abspath(module.path)
|
||||||
|
for i in range(self.import_stmt.relative_count):
|
||||||
|
path = os.path.dirname(path)
|
||||||
|
|
||||||
|
if path is not None:
|
||||||
|
return imp.find_module(string, [path])
|
||||||
|
else:
|
||||||
|
debug.dbg('search_module', string, self.file_path)
|
||||||
# Override the sys.path. It works only good that way.
|
# Override the sys.path. It works only good that way.
|
||||||
# Injecting the path directly into `find_module` did not work.
|
# Injecting the path directly into `find_module` did not work.
|
||||||
sys.path, temp = builtin.module_find_path, sys.path
|
sys.path, temp = builtin.module_find_path, sys.path
|
||||||
@@ -137,7 +144,6 @@ class ImportPath(object):
|
|||||||
sys.path = temp
|
sys.path = temp
|
||||||
return i
|
return i
|
||||||
|
|
||||||
# TODO handle relative paths - they are included in the import object
|
|
||||||
current_namespace = None
|
current_namespace = None
|
||||||
builtin.module_find_path.insert(0, self.file_path)
|
builtin.module_find_path.insert(0, self.file_path)
|
||||||
# now execute those paths
|
# now execute those paths
|
||||||
|
|||||||
38
parsing.py
38
parsing.py
@@ -503,37 +503,38 @@ class Import(Simple):
|
|||||||
:param defunct: An Import is valid or not.
|
:param defunct: An Import is valid or not.
|
||||||
:type defunct: bool
|
:type defunct: bool
|
||||||
"""
|
"""
|
||||||
def __init__(self, start_pos, end_pos, namespace, alias='', from_ns='', \
|
def __init__(self, start_pos, end_pos, namespace, alias=None, \
|
||||||
star=False, relative_count=None, defunct=False):
|
from_ns=None, star=False, relative_count=None, defunct=False):
|
||||||
super(Import, self).__init__(start_pos, end_pos)
|
super(Import, self).__init__(start_pos, end_pos)
|
||||||
|
|
||||||
self.namespace = namespace
|
self.namespace = namespace
|
||||||
if namespace:
|
|
||||||
namespace.parent = weakref.ref(self)
|
|
||||||
|
|
||||||
self.alias = alias
|
self.alias = alias
|
||||||
if alias:
|
|
||||||
alias.parent = weakref.ref(self)
|
|
||||||
|
|
||||||
self.from_ns = from_ns
|
self.from_ns = from_ns
|
||||||
if from_ns:
|
for n in [namespace, alias, from_ns]:
|
||||||
from_ns.parent = weakref.ref(self)
|
if n:
|
||||||
|
n.parent = weakref.ref(self)
|
||||||
|
|
||||||
self.star = star
|
self.star = star
|
||||||
self.relative_count = relative_count
|
self.relative_count = relative_count
|
||||||
self.defunct = defunct
|
self.defunct = defunct
|
||||||
|
|
||||||
def get_code(self):
|
def get_code(self):
|
||||||
|
# in case one thing is None
|
||||||
|
alias = self.alias or ''
|
||||||
|
namespace = self.namespace or ''
|
||||||
|
from_ns = self.from_ns or ''
|
||||||
|
|
||||||
if self.alias:
|
if self.alias:
|
||||||
ns_str = "%s as %s" % (self.namespace, self.alias)
|
ns_str = "%s as %s" % (namespace, alias)
|
||||||
else:
|
else:
|
||||||
ns_str = str(self.namespace)
|
ns_str = str(namespace)
|
||||||
if self.from_ns:
|
if self.from_ns or self.relative_count:
|
||||||
if self.star:
|
if self.star:
|
||||||
ns_str = '*'
|
ns_str = '*'
|
||||||
return "from %s import %s" % (self.from_ns, ns_str) + '\n'
|
dots = '.' * self.relative_count
|
||||||
|
return "from %s%s import %s\n" % (dots, from_ns, ns_str)
|
||||||
else:
|
else:
|
||||||
return "import " + ns_str + '\n'
|
return "import %s\n" % ns_str
|
||||||
|
|
||||||
def get_defined_names(self):
|
def get_defined_names(self):
|
||||||
if self.defunct:
|
if self.defunct:
|
||||||
@@ -1533,7 +1534,11 @@ class PyFuzzyParser(object):
|
|||||||
relative_count += 1
|
relative_count += 1
|
||||||
# the from import
|
# the from import
|
||||||
mod, token_type, tok = self._parsedotname(self.current)
|
mod, token_type, tok = self._parsedotname(self.current)
|
||||||
if not mod or tok != "import":
|
if str(mod) == 'import' and relative_count:
|
||||||
|
self.gen.push_back(self._current_full)
|
||||||
|
tok = 'import'
|
||||||
|
mod = None
|
||||||
|
if not mod and not relative_count or tok != "import":
|
||||||
debug.warning("from: syntax error@%s" %
|
debug.warning("from: syntax error@%s" %
|
||||||
self.start_pos[0])
|
self.start_pos[0])
|
||||||
defunct = True
|
defunct = True
|
||||||
@@ -1550,6 +1555,7 @@ class PyFuzzyParser(object):
|
|||||||
i = Import(first_pos, self.end_pos, mod, defunct=True,
|
i = Import(first_pos, self.end_pos, mod, defunct=True,
|
||||||
relative_count=relative_count)
|
relative_count=relative_count)
|
||||||
self._check_user_stmt(i)
|
self._check_user_stmt(i)
|
||||||
|
self.scope.add_import(i)
|
||||||
self.freshscope = False
|
self.freshscope = False
|
||||||
#loops
|
#loops
|
||||||
elif tok == 'for':
|
elif tok == 'for':
|
||||||
|
|||||||
@@ -132,3 +132,39 @@ from datetime.timedelta import
|
|||||||
|
|
||||||
#? ['Cursor']
|
#? ['Cursor']
|
||||||
from sqlite3 import Cursor
|
from sqlite3 import Cursor
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# relative imports
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
from .import_tree import mod1
|
||||||
|
#? int()
|
||||||
|
mod1.a
|
||||||
|
|
||||||
|
from ..import_tree import mod1
|
||||||
|
#?
|
||||||
|
mod1.a
|
||||||
|
|
||||||
|
from .......import_tree import mod1
|
||||||
|
#?
|
||||||
|
mod1.a
|
||||||
|
|
||||||
|
from .. import run
|
||||||
|
#? int()
|
||||||
|
run.tests_fail
|
||||||
|
|
||||||
|
from ..run import tests_fail as f
|
||||||
|
#? int()
|
||||||
|
f
|
||||||
|
|
||||||
|
from . import run
|
||||||
|
#? []
|
||||||
|
run.
|
||||||
|
|
||||||
|
from . import import_tree as imp_tree
|
||||||
|
#? str()
|
||||||
|
imp_tree.a
|
||||||
|
|
||||||
|
from . import datetime
|
||||||
|
#? []
|
||||||
|
mod1.
|
||||||
|
|||||||
Reference in New Issue
Block a user