probably finished the load_module method migration

This commit is contained in:
Dave Halter
2014-01-05 01:37:43 +01:00
parent 29e661ea74
commit 4d7349411e
6 changed files with 55 additions and 34 deletions

View File

@@ -35,10 +35,12 @@ import inspect
from jedi import common from jedi import common
from jedi import debug from jedi import debug
from jedi.parser import Parser from jedi.parser import Parser
from jedi.parser import fast
from jedi import modules from jedi import modules
from jedi import cache
class BuiltinModule(modules.CachedModule): class BuiltinModule(object):
""" """
This module is a parser for all builtin modules, which are programmed in This module is a parser for all builtin modules, which are programmed in
C/C++. It should also work on third party modules. C/C++. It should also work on third party modules.
@@ -69,14 +71,32 @@ class BuiltinModule(modules.CachedModule):
def __init__(self, path=None, name=None, sys_path=None): def __init__(self, path=None, name=None, sys_path=None):
if sys_path is None: if sys_path is None:
sys_path = modules.get_sys_path() sys_path = modules.get_sys_path()
self.sys_path = list(sys_path)
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)
super(BuiltinModule, self).__init__(path=path, name=name) self.name = name
self.sys_path = list(sys_path) self.path = path and os.path.abspath(path)
self._parser = None
self._module = None self._module = None
@property
def parser(self):
""" get the parser lazy """
if self._parser is None:
self._parser = cache.load_parser(self.path, self.name) \
or self._load_module()
return self._parser
def _load_module(self):
source = _generate_code(self.module, self._load_mixins())
p = self.path or self.name
p = fast.FastParser(source, p)
cache.save_parser(self.path, self.name, p)
return p
@property @property
def module(self): def module(self):
def load_module(name, path): def load_module(name, path):
@@ -118,10 +138,6 @@ class BuiltinModule(modules.CachedModule):
load_module(name, path) load_module(name, path)
return self._module return self._module
def _get_source(self):
""" Override this abstract method """
return _generate_code(self.module, self._load_mixins())
def _load_mixins(self): def _load_mixins(self):
""" """
Load functions that are mixed in to the standard library. Load functions that are mixed in to the standard library.
@@ -158,14 +174,14 @@ class BuiltinModule(modules.CachedModule):
raise NotImplementedError() raise NotImplementedError()
return funcs return funcs
try: name = self.name
name = self.name # sometimes there are stupid endings like `_sqlite3.cpython-32mu`
# sometimes there are stupid endings like `_sqlite3.cpython-32mu` name = re.sub(r'\..*', '', name)
name = re.sub(r'\..*', '', name)
if name == '__builtin__' and not is_py3k: if name == '__builtin__' and not is_py3k:
name = 'builtins' name = 'builtins'
path = os.path.dirname(os.path.abspath(__file__)) path = os.path.dirname(os.path.abspath(__file__))
try:
with open(os.path.join(path, 'mixin', name) + '.pym') as f: with open(os.path.join(path, 'mixin', name) + '.pym') as f:
s = f.read() s = f.read()
except IOError: except IOError:

View File

@@ -83,7 +83,7 @@ def get_directory_modules_for_name(mods, name):
with open(path) as f: with open(path) as f:
source = modules.source_to_unicode(f.read()) source = modules.source_to_unicode(f.read())
if name in source: if name in source:
return modules.Module(path, source).parser.module return modules.load_module(path, source)
# skip non python modules # skip non python modules
mods = set(m for m in mods if m.path is None or m.path.endswith('.py')) mods = set(m for m in mods if m.path is None or m.path.endswith('.py'))

View File

@@ -110,9 +110,9 @@ class ImportPath(pr.Base):
if self._is_relative_import(): if self._is_relative_import():
rel_path = self._get_relative_path() + '/__init__.py' rel_path = self._get_relative_path() + '/__init__.py'
with common.ignored(IOError): if os.path.exists(rel_path):
m = modules.Module(rel_path) m = modules.load_module(rel_path)
names += m.parser.module.get_defined_names() names += m.get_defined_names()
else: else:
if on_import_stmt and isinstance(scope, pr.Module) \ if on_import_stmt and isinstance(scope, pr.Module) \
and scope.path.endswith('__init__.py'): and scope.path.endswith('__init__.py'):

View File

@@ -31,14 +31,14 @@ from jedi import common
def load_module(path=None, source=None, name=None): def load_module(path=None, source=None, name=None):
def load(source): def load(source):
if path.endswith('.py'): if path is not None and path.endswith('.py'):
if source is None: if source is None:
with open(path) as f: with open(path) as f:
source = f.read() source = f.read()
else: else:
# TODO refactoring remove # TODO refactoring remove
from jedi.evaluate import builtin from jedi.evaluate import builtin
return builtin.BuiltinModule(name=path).parser.module return builtin.BuiltinModule(path, name).parser.module
p = path or name p = path or name
p = fast.FastParser(source_to_unicode(source), p) p = fast.FastParser(source_to_unicode(source), p)
cache.save_parser(path, name, p) cache.save_parser(path, name, p)
@@ -61,9 +61,13 @@ class ModuleWithCursor(object):
""" """
def __init__(self, path, source, position): def __init__(self, path, source, position):
super(ModuleWithCursor, self).__init__() super(ModuleWithCursor, self).__init__()
self.position = position self.path = path and os.path.abspath(path)
self.name = None
self.source = source self.source = source
self.position = position
self._path_until_cursor = None self._path_until_cursor = None
self._line_cache = None
self._parser = None
# this two are only used, because there is no nonlocal in Python 2 # this two are only used, because there is no nonlocal in Python 2
self._line_temp = None self._line_temp = None

View File

@@ -8,15 +8,16 @@ import pytest
import jedi import jedi
from jedi import settings, cache from jedi import settings, cache
from jedi.cache import ParserCacheItem, _ModulePickling from jedi.cache import ParserCacheItem, ParserPickling
ModulePickling = _ModulePickling() ParserPicklingCls = type(ParserPickling)
ParserPickling = ParserPicklingCls()
def test_modulepickling_change_cache_dir(monkeypatch, tmpdir): def test_modulepickling_change_cache_dir(monkeypatch, tmpdir):
""" """
ModulePickling should not save old cache when cache_directory is changed. ParserPickling should not save old cache when cache_directory is changed.
See: `#168 <https://github.com/davidhalter/jedi/pull/168>`_ See: `#168 <https://github.com/davidhalter/jedi/pull/168>`_
""" """
@@ -29,19 +30,19 @@ def test_modulepickling_change_cache_dir(monkeypatch, tmpdir):
path_2 = 'fake path 2' path_2 = 'fake path 2'
monkeypatch.setattr(settings, 'cache_directory', dir_1) monkeypatch.setattr(settings, 'cache_directory', dir_1)
ModulePickling.save_module(path_1, item_1) ParserPickling.save_parser(path_1, item_1)
cached = load_stored_item(ModulePickling, path_1, item_1) cached = load_stored_item(ParserPickling, path_1, item_1)
assert cached == item_1.parser assert cached == item_1.parser
monkeypatch.setattr(settings, 'cache_directory', dir_2) monkeypatch.setattr(settings, 'cache_directory', dir_2)
ModulePickling.save_module(path_2, item_2) ParserPickling.save_parser(path_2, item_2)
cached = load_stored_item(ModulePickling, path_1, item_1) cached = load_stored_item(ParserPickling, path_1, item_1)
assert cached is None assert cached is None
def load_stored_item(cache, path, item): def load_stored_item(cache, path, item):
"""Load `item` stored at `path` in `cache`.""" """Load `item` stored at `path` in `cache`."""
return cache.load_module(path, item.change_time - 1) return cache.load_parser(path, item.change_time - 1)
@pytest.mark.usefixtures("isolated_jedi_cache") @pytest.mark.usefixtures("isolated_jedi_cache")
@@ -49,13 +50,13 @@ def test_modulepickling_delete_incompatible_cache():
item = ParserCacheItem('fake parser') item = ParserCacheItem('fake parser')
path = 'fake path' path = 'fake path'
cache1 = _ModulePickling() cache1 = ParserPicklingCls()
cache1.version = 1 cache1.version = 1
cache1.save_module(path, item) cache1.save_parser(path, item)
cached1 = load_stored_item(cache1, path, item) cached1 = load_stored_item(cache1, path, item)
assert cached1 == item.parser assert cached1 == item.parser
cache2 = _ModulePickling() cache2 = ParserPicklingCls()
cache2.version = 2 cache2.version = 2
cached2 = load_stored_item(cache2, path, item) cached2 = load_stored_item(cache2, path, item)
assert cached2 is None assert cached2 is None

View File

@@ -11,6 +11,7 @@ from .helpers import TestCase, cwd_at
import jedi import jedi
from jedi import Script from jedi import Script
from jedi import api from jedi import api
from jedi import modules
from jedi.parser import Parser from jedi.parser import Parser
#jedi.set_debug_function() #jedi.set_debug_function()
@@ -81,8 +82,7 @@ class TestRegression(TestCase):
src1 = "def r(a): return a" src1 = "def r(a): return a"
# Other fictional modules in another place in the fs. # Other fictional modules in another place in the fs.
src2 = 'from .. import setup; setup.r(1)' src2 = 'from .. import setup; setup.r(1)'
# .parser to load the module modules.load_module(os.path.abspath(fname), src2)
api.modules.Module(os.path.abspath(fname), src2).parser
result = Script(src1, path='../setup.py').goto_definitions() result = Script(src1, path='../setup.py').goto_definitions()
assert len(result) == 1 assert len(result) == 1
assert result[0].description == 'class int' assert result[0].description == 'class int'