1
0
forked from VimPlug/jedi

remove a lot of modules crap and replace it with a simple method called load_module

This commit is contained in:
Dave Halter
2014-01-04 14:34:56 +01:00
parent 962a678417
commit 29e661ea74
3 changed files with 34 additions and 73 deletions

View File

@@ -3,7 +3,7 @@ This caching is very important for speed and memory optimizations. There's
nothing really spectacular, just some decorators. The following cache types are nothing really spectacular, just some decorators. The following cache types are
available: available:
- module caching (`load_module` and `save_module`), which uses pickle and is - module caching (`load_parser` and `save_parser`), which uses pickle and is
really important to assure low load times of modules like ``numpy``. really important to assure low load times of modules like ``numpy``.
- ``time_cache`` can be used to cache something for just a limited time span, - ``time_cache`` can be used to cache something for just a limited time span,
which can be useful if there's user interaction and the user cannot react which can be useful if there's user interaction and the user cannot react
@@ -135,18 +135,18 @@ def invalidate_star_import_cache(module, only_main=False):
invalidate_star_import_cache(key) invalidate_star_import_cache(key)
def load_module(path, name): def load_parser(path, name):
""" """
Returns the module or None, if it fails. Returns the module or None, if it fails.
""" """
if path is None and name is None: if path is None and name is None:
return None return None
tim = os.path.getmtime(path) if path else None p_time = os.path.getmtime(path) if path else None
n = name if path is None else path n = name if path is None else path
try: try:
parser_cache_item = parser_cache[n] parser_cache_item = parser_cache[n]
if not path or tim <= parser_cache_item.change_time: if not path or p_time <= parser_cache_item.change_time:
return parser_cache_item.parser return parser_cache_item.parser
else: else:
# In case there is already a module cached and this module # In case there is already a module cached and this module
@@ -155,10 +155,10 @@ def load_module(path, name):
invalidate_star_import_cache(parser_cache_item.parser.module) invalidate_star_import_cache(parser_cache_item.parser.module)
except KeyError: except KeyError:
if settings.use_filesystem_cache: if settings.use_filesystem_cache:
return ModulePickling.load_module(n, tim) return ParserPickling.load_parser(n, p_time)
def save_module(path, name, parser, pickling=True): def save_parser(path, name, parser, pickling=True):
try: try:
p_time = None if not path else os.path.getmtime(path) p_time = None if not path else os.path.getmtime(path)
except OSError: except OSError:
@@ -169,10 +169,10 @@ def save_module(path, name, parser, pickling=True):
item = ParserCacheItem(parser, p_time) item = ParserCacheItem(parser, p_time)
parser_cache[n] = item parser_cache[n] = item
if settings.use_filesystem_cache and pickling: if settings.use_filesystem_cache and pickling:
ModulePickling.save_module(n, item) ParserPickling.save_parser(n, item)
class _ModulePickling(object): class ParserPickling(object):
version = 7 version = 7
""" """
@@ -200,7 +200,7 @@ class _ModulePickling(object):
.. todo:: Detect interpreter (e.g., PyPy). .. todo:: Detect interpreter (e.g., PyPy).
""" """
def load_module(self, path, original_changed_time): def load_parser(self, path, original_changed_time):
try: try:
pickle_changed_time = self._index[path] pickle_changed_time = self._index[path]
except KeyError: except KeyError:
@@ -221,7 +221,7 @@ class _ModulePickling(object):
parser_cache[path] = parser_cache_item parser_cache[path] = parser_cache_item
return parser_cache_item.parser return parser_cache_item.parser
def save_module(self, path, parser_cache_item): def save_parser(self, path, parser_cache_item):
self.__index = None self.__index = None
try: try:
files = self._index files = self._index
@@ -282,4 +282,4 @@ class _ModulePickling(object):
# is a singleton # is a singleton
ModulePickling = _ModulePickling() ParserPickling = ParserPickling()

View File

@@ -24,7 +24,6 @@ from jedi import common
from jedi import debug from jedi import debug
from jedi.parser import representation as pr from jedi.parser import representation as pr
from jedi import cache from jedi import cache
from jedi.evaluate import builtin
class ModuleNotFound(Exception): class ModuleNotFound(Exception):
@@ -359,14 +358,9 @@ class ImportPath(pr.Base):
else: else:
source = current_namespace[0].read() source = current_namespace[0].read()
current_namespace[0].close() current_namespace[0].close()
if path.endswith('.py'): return modules.load_module(path, source), rest
f = modules.Module(path, source)
else:
f = builtin.BuiltinModule(path=path)
else: else:
f = builtin.BuiltinModule(name=path) return modules.load_module(name=path), rest
return f.parser.module, rest
def strip_imports(evaluator, scopes): def strip_imports(evaluator, scopes):

View File

@@ -29,59 +29,26 @@ from jedi import debug
from jedi import common from jedi import common
class CachedModule(object): def load_module(path=None, source=None, name=None):
""" def load(source):
The base type for all modules, which is not to be confused with if path.endswith('.py'):
`parsing_representation.Module`. Caching happens here. if source is None:
""" with open(path) as f:
source = f.read()
else:
# TODO refactoring remove
from jedi.evaluate import builtin
return builtin.BuiltinModule(name=path).parser.module
p = path or name
p = fast.FastParser(source_to_unicode(source), p)
cache.save_parser(path, name, p)
return p.module
def __init__(self, path=None, name=None): cached = cache.load_parser(path, name)
self.path = path and os.path.abspath(path) return load(source) if cached is None else cached.module
self.name = name
self._parser = None
@property
def parser(self):
""" get the parser lazy """
if self._parser is None:
self._parser = cache.load_module(self.path, self.name) \
or self._load_module()
return self._parser
def _get_source(self):
raise NotImplementedError()
def _load_module(self):
source = self._get_source()
p = self.path or self.name
p = fast.FastParser(source, p)
cache.save_module(self.path, self.name, p)
return p
class Module(CachedModule): class ModuleWithCursor(object):
"""
Manages all files, that are parsed and caches them.
:param path: The module path of the file.
:param source: The source code of the file.
"""
def __init__(self, path, source=None):
super(Module, self).__init__(path=path)
if source is None:
with open(path) as f:
source = f.read()
self.source = source_to_unicode(source)
self._line_cache = None
def _get_source(self):
""" Just one time """
s = self.source
del self.source # memory efficiency
return s
class ModuleWithCursor(Module):
""" """
Manages all files, that are parsed and caches them. Manages all files, that are parsed and caches them.
Important are the params source and path, one of them has to Important are the params source and path, one of them has to
@@ -93,7 +60,7 @@ class ModuleWithCursor(Module):
for the main file. for the main file.
""" """
def __init__(self, path, source, position): def __init__(self, path, source, position):
super(ModuleWithCursor, self).__init__(path, source) super(ModuleWithCursor, self).__init__()
self.position = position self.position = position
self.source = source self.source = source
self._path_until_cursor = None self._path_until_cursor = None
@@ -114,7 +81,7 @@ class ModuleWithCursor(Module):
# default), therefore fill the cache here. # default), therefore fill the cache here.
self._parser = fast.FastParser(self.source, self.path, self.position) self._parser = fast.FastParser(self.source, self.path, self.position)
# don't pickle that module, because it's changing fast # don't pickle that module, because it's changing fast
cache.save_module(self.path, self.name, self._parser, cache.save_parser(self.path, self.name, self._parser,
pickling=False) pickling=False)
return self._parser return self._parser
@@ -363,14 +330,14 @@ def sys_path_with_modifications(module):
os.chdir(os.path.dirname(module.path)) os.chdir(os.path.dirname(module.path))
result = check_module(module) result = check_module(module)
result += detect_django_path(module.path) result += _detect_django_path(module.path)
# cleanup, back to old directory # cleanup, back to old directory
os.chdir(curdir) os.chdir(curdir)
return result return result
def detect_django_path(module_path): def _detect_django_path(module_path):
""" Detects the path of the very well known Django library (if used) """ """ Detects the path of the very well known Django library (if used) """
result = [] result = []
while True: while True: