1
0
forked from VimPlug/jedi

change the implementation of compiled.load_module and always use the sys.modules cache after an import, because it's easier. Doesn't require any logic.

This commit is contained in:
Dave Halter
2014-06-25 18:46:51 +02:00
parent e5efd6e5c8
commit 47205dd7f3
4 changed files with 50 additions and 31 deletions

View File

@@ -208,7 +208,31 @@ class CompiledName(FakeName):
pass # Just ignore this, FakeName tries to overwrite the parent attribute. pass # Just ignore this, FakeName tries to overwrite the parent attribute.
def dotted_from_fs_path(fs_path, sys_path=None):
"""
Changes `/usr/lib/python3.4/email/utils.py` to `email.utils`. I.e.
compares the path with sys.path and then returns the dotted_path. If the
path is not in the sys.path, just returns None.
"""
sep = os.path.sep
shortest = None
if sys_path is None:
sys_path = get_sys_path()
for s in sys_path:
if fs_path.startswith(s):
path = fs_path[len(s):].strip(sep)
path = re.sub('\.[^%s]*|%s__init__.py$' % (sep, sep), '', path)
dotted = path.split(sep)
dotted = '.'.join(dotted)
# At this point dotted could be both `lib-dynload.datetime` and
# `datetime`. The shorter one is typically the module we want.
if shortest is None or len(shortest) > len(dotted):
shortest = dotted
return shortest
def load_module(path, name): def load_module(path, name):
"""
if not name: if not name:
name = os.path.basename(path) name = os.path.basename(path)
name = name.rpartition('.')[0] # cut file type (normally .so) name = name.rpartition('.')[0] # cut file type (normally .so)
@@ -230,17 +254,22 @@ def load_module(path, name):
else: else:
path = os.path.dirname(path) path = os.path.dirname(path)
"""
if path is not None:
dotted_path = dotted_from_fs_path(path)
else:
dotted_path = name
sys_path = get_sys_path() sys_path = get_sys_path()
if path: if dotted_path is None:
sys_path.insert(0, path) p, _, dotted_path = path.partition(os.path.sep)
sys_path.insert(0, p)
temp, sys.path = sys.path, sys_path temp, sys.path = sys.path, sys_path
try: __import__(dotted_path)
module = __import__(name, {}, {}, dot_path[:-1]) # Just access the cache after import, because of #59 as well as the very
except AttributeError: # complicated import structure of Python.
# use sys.modules, because you cannot access some modules module = sys.modules[dotted_path]
# directly. -> github issue #59
module = sys.modules[name]
sys.path = temp sys.path = temp
return CompiledObject(module) return CompiledObject(module)

View File

@@ -12,7 +12,6 @@ This module also supports import autocompletion, which means to complete
statements like ``from datetim`` (curser at the end would return ``datetime``). statements like ``from datetim`` (curser at the end would return ``datetime``).
""" """
import os import os
import re
import pkgutil import pkgutil
import sys import sys
from itertools import chain from itertools import chain
@@ -511,7 +510,7 @@ def remove_star_imports(evaluator, scope, ignored_modules=()):
def _load_module(path=None, source=None, name=None, sys_path=None): def _load_module(path=None, source=None, name=None, sys_path=None):
def load(source): def load(source):
dotted_path = path and _reverse_fs_path(path, sys_path) dotted_path = path and compiled.dotted_from_fs_path(path, sys_path)
if path is not None and path.endswith('.py') \ if path is not None and path.endswith('.py') \
and not dotted_path in settings.auto_import_modules: and not dotted_path in settings.auto_import_modules:
if source is None: if source is None:
@@ -528,26 +527,6 @@ def _load_module(path=None, source=None, name=None, sys_path=None):
return load(source) if cached is None else cached.module return load(source) if cached is None else cached.module
def _reverse_fs_path(fs_path, sys_path=None):
"""
Changes `/usr/lib/python3.4/email/utils.py` to `email.utils`. I.e.
compares the path with sys.path and then returns the dotted_path. If the
path is not in the sys.path, just returns None.
"""
sep = os.path.sep
shortest = None
sys_path = get_sys_path()
for s in sys_path:
if fs_path.startswith(s):
path = fs_path[len(s):].strip(sep)
path = re.sub('\.[^%s]*|%s__init__.py$' % (sep, sep), '', path)
dotted = '.'.join(path.split(sep))
# At this point dotted could be both `lib-dynload.datetime` and
# `datetime`. The shorter one is typically the module we want.
if shortest is None or len(shortest) > len(dotted):
shortest = dotted
return shortest
def get_modules_containing_name(mods, name): def get_modules_containing_name(mods, name):
""" """
Search a name in the directories of modules. Search a name in the directories of modules.

View File

@@ -180,7 +180,9 @@ dynamic_flow_information = True
Check for `isinstance` and other information to infer a type. Check for `isinstance` and other information to infer a type.
""" """
auto_import_modules = ['hashlib'] auto_import_modules = [
'hashlib', # setattr
]
""" """
Modules that are not analyzed but imported, although they contain Python code. Modules that are not analyzed but imported, although they contain Python code.
This improves autocompletion for libraries that use ``setattr`` or This improves autocompletion for libraries that use ``setattr`` or

View File

@@ -114,3 +114,12 @@ def huhu(db):
""" """
#? sqlite3.Connection() #? sqlite3.Connection()
db db
# -----------------
# hashlib
# -----------------
import hashlib
#? ['md5']
hashlib.md5