diff --git a/builtin.py b/builtin.py index 99e6ef64..902f10b0 100644 --- a/builtin.py +++ b/builtin.py @@ -5,8 +5,53 @@ import os import debug import parsing +class CachedModule(object): + cache = {} -class Parser(object): + def __init__(self, name=None, path=None, sys_path=sys.path): + self.path = path + if name: + self.name = name + else: + name = os.path.basename(self.path) + self.name = name.rpartition('.')[0] # cut file type (normally .so) + self.path = os.path.dirname(self.path) + #print self.name, self.path + self._content = {} + self._parser = None + self._module = None + self.sys_path = sys_path + + @property + def parser(self): + """ get the parser lazy """ + if not self._parser: + try: + timestamp, parser = self.cache[self.path or self.name] + if not self.path or timestamp == os.path.getmtime(self.path): + self._parser = parser + else: + raise KeyError + except KeyError: + self._load_module() + return self._parser + + def _get_source(self): + raise NotImplementedError() + + def _load_module(self): + source = self._get_source() + self._parser = parsing.PyFuzzyParser(source, self.name) + #except: + # debug.warning('not possible to resolve', self.name, source) + #open('builtin_fail', 'w').write(code) + # raise + p_time = None if not self.path else os.path.getmtime(self.path) + + self.cache[self.path or self.name] = p_time, self._parser + + +class Parser(CachedModule): """ This module is a parser for all builtin modules, which are programmed in C/C++. It should also work on third party modules. @@ -32,9 +77,11 @@ class Parser(object): 'file object': 'file("")', # TODO things like dbg: ('not working', 'tuple of integers') } - cache = {} + module_cache = {} def __init__(self, name=None, path=None, sys_path=sys.path): + super(Parser, self).__init__(name, path) + self.path = path if name: self.name = name @@ -64,32 +111,8 @@ class Parser(object): #print 'mod', self._content['module'] return self._module - @property - def parser(self): - """ get the parser lazy """ - if not self._parser: - try: - timestamp, parser = Parser.cache[self.name, self.path] - if not self.path or timestamp == os.path.getmtime(self.path): - debug.dbg('hit builtin cache') - self._parser = parser - else: - raise KeyError - except KeyError: - code = self._generate_code(self.module) - try: - self._parser = parsing.PyFuzzyParser(code, self.name) - except: - debug.warning('not possible to resolve', self.name, code) - #open('builtin_fail', 'w').write(code) - raise - else: - if self.path: - p_time = os.path.getmtime(self.path) - else: - p_time = None - Parser.cache[self.name, self.path] = p_time, self._parser - return self._parser + def _get_source(self): + return self._generate_code(self.module) def _generate_code(self, scope, depth=0): """ diff --git a/functions.py b/functions.py index cd8da39d..44269533 100644 --- a/functions.py +++ b/functions.py @@ -9,7 +9,7 @@ import debug __all__ = ['complete', 'get_completion_parts', 'set_debug_function'] -class FileWithCursor(modules.File): +class FileWithCursor(modules.Module): """ Manages all files, that are parsed and caches them. Important are the params source and module_path, one of them has to diff --git a/modules.py b/modules.py index 62338e2b..9572a615 100644 --- a/modules.py +++ b/modules.py @@ -15,7 +15,7 @@ class ModuleNotFound(Exception): pass -class File(object): +class Module(builtin.CachedModule): """ Manages all files, that are parsed and caches them. @@ -32,21 +32,19 @@ class File(object): @property def parser(self): - if self._parser: - return self._parser - if not self.module_path and not self.source: - raise AttributeError("Submit a module name or the source code") - elif self.module_path: + if not self._parser: # check the cache try: - timestamp, _parser = File.module_cache[self.module_path] + timestamp, _parser = Module.module_cache[self.module_path] if timestamp == os.path.getmtime(self.module_path): debug.dbg('hit module cache') return _parser - except: - pass + except KeyError: + self._load_module() + return self._parser - return self._load_module() + def _get_source(self): + return self.source def _load_module(self): self._parser = parsing.PyFuzzyParser(self.source, self.module_path) @@ -54,8 +52,7 @@ class File(object): # insert into cache to_cache = (os.path.getmtime(self.module_path), self._parser) - File.module_cache[self.module_path] = to_cache - return self._parser + Module.module_cache[self.module_path] = to_cache def find_module(current_module, point_path): @@ -115,7 +112,7 @@ def find_module(current_module, point_path): else: source = current_namespace[0].read() if path.endswith('.py'): - f = File(path, source) + f = Module(path, source) else: f = builtin.Parser(path=path) else: diff --git a/parsetest.py b/parsetest.py index 08077c6d..7ebdd073 100644 --- a/parsetest.py +++ b/parsetest.py @@ -162,7 +162,7 @@ def gen(): yield 1 yield "" -gen_exe = gen() +gen_exe = t12343 + gen() def dec(func): def wrapper(*args, **kwargs): diff --git a/test/completion/functions.py b/test/completion/functions.py index fff65df9..0a9c9195 100644 --- a/test/completion/functions.py +++ b/test/completion/functions.py @@ -236,6 +236,6 @@ def gen(): yield 1 yield "" -exe = gen() +exe = next(gen()) #? ['upper'] exe.upper