1
0
forked from VimPlug/jedi

significant speedup due to compiled caching

This commit is contained in:
Dave Halter
2014-04-13 16:31:38 +02:00
parent edeebd0bb9
commit 4bc55be103
6 changed files with 25 additions and 17 deletions

View File

@@ -80,7 +80,7 @@ class LazyName(helpers.FakeName):
mod)
module = compiled.CompiledObject(raw_module)
return compiled.create(self._value, module, module)
return compiled.create(self._evaluator, self._value, module, module)
@parent.setter
def parent(self, value):

View File

@@ -89,6 +89,7 @@ class Evaluator(object):
def __init__(self):
self.memoize_cache = {} # for memoize decorators
self.import_cache = {} # like `sys.modules`.
self.compiled_cache = {} # see `compiled.create()`
self.recursion_detector = recursion.RecursionDetector()
self.execution_recursion_detector = recursion.ExecutionRecursionDetector()
@@ -137,10 +138,10 @@ class Evaluator(object):
# only in for loops without clutter, because they are
# predictable.
for r in result:
left = precedence.calculate(left, operator, [r])
left = precedence.calculate(self, left, operator, [r])
result = left
else:
result = precedence.calculate(left, operator, result)
result = precedence.calculate(self, left, operator, result)
elif len(stmt.get_set_vars()) > 1 and seek_name and ass_details:
# Assignment checking is only important if the statement defines
# multiple variables.
@@ -173,7 +174,7 @@ class Evaluator(object):
def _eval_precedence(self, _precedence):
left = self.process_precedence_element(_precedence.left)
right = self.process_precedence_element(_precedence.right)
return precedence.calculate(left, _precedence.operator, right)
return precedence.calculate(self, left, _precedence.operator, right)
def _eval_statement_element(self, element):
if pr.Array.is_type(element, pr.Array.NOARRAY):
@@ -227,7 +228,7 @@ class Evaluator(object):
search_global=True)
else:
# for pr.Literal
types = [compiled.create(current.value)]
types = [compiled.create(self, current.value)]
types = imports.strip_imports(self, types)
return self.follow_path(path, types, scope)

View File

@@ -337,11 +337,18 @@ def _create_from_name(module, parent, name):
return CompiledObject(obj, parent)
def create(obj, parent=builtin, module=None):
def create(evaluator, obj, parent=builtin, module=None):
"""
A very weird interface class to this module. The more options provided the
more acurate loading compiled objects is.
"""
# Do a very cheap form of caching here.
key = id(obj), id(parent), id(module)
try:
return evaluator.compiled_cache[key]
except KeyError:
pass
if not inspect.ismodule(obj):
faked = fake.get_faked(module and module.obj, obj)
if faked is not None:

View File

@@ -102,7 +102,7 @@ class NameFinder(object):
"""Checks for both __getattr__ and __getattribute__ methods"""
result = []
# str is important to lose the NamePart!
name = compiled.create(str(self.name_str))
name = compiled.create(self._evaluator, str(self.name_str))
with common.ignored(KeyError):
result = inst.execute_subscope_by_name('__getattr__', [name])
if not result:

View File

@@ -174,12 +174,12 @@ def _check_operator(iterator, priority=PythonGrammar.LOWEST_PRIORITY):
return left
def calculate(left_result, operator, right_result):
def calculate(evaluator, left_result, operator, right_result):
result = []
if left_result is None and right_result:
# cases like `-1` or `1 + ~1`
for right in right_result:
result.append(_factor_calculate(operator, right))
result.append(_factor_calculate(evaluator, operator, right))
return result
else:
if not left_result or not right_result:
@@ -187,14 +187,14 @@ def calculate(left_result, operator, right_result):
for left in left_result:
for right in right_result:
result += _element_calculate(left, operator, right)
result += _element_calculate(evaluator, left, operator, right)
return result
def _factor_calculate(operator, right):
def _factor_calculate(evaluator, operator, right):
if _is_number(right):
if operator == '-':
return create(-right.obj)
return create(evaluator, -right.obj)
return right
@@ -203,7 +203,7 @@ def _is_number(obj):
and isinstance(obj.obj, (int, float))
def _element_calculate(left, operator, right):
def _element_calculate(evaluator, left, operator, right):
def is_string(obj):
return isinstance(obj, CompiledObject) \
and isinstance(obj.obj, (str, unicode))
@@ -215,8 +215,8 @@ def _element_calculate(left, operator, right):
return [left]
elif operator == '+':
if _is_number(left) and _is_number(right) or is_string(left) and is_string(right):
return [create(left.obj + right.obj)]
return [create(evaluator, left.obj + right.obj)]
elif operator == '-':
if _is_number(left) and _is_number(right):
return [create(left.obj - right.obj)]
return [create(evaluator, left.obj - right.obj)]
return [left, right]

View File

@@ -16,7 +16,7 @@ def test_simple():
def test_fake_loading():
assert isinstance(compiled.create(next), Function)
assert isinstance(compiled.create(Evaluator(), next), Function)
string = compiled.builtin.get_subscope_by_name('str')
from_name = compiled._create_from_name(
@@ -28,7 +28,7 @@ def test_fake_loading():
def test_fake_docstr():
assert compiled.create(next).raw_doc == next.__doc__
assert compiled.create(Evaluator(), next).raw_doc == next.__doc__
def test_parse_function_doc_illegal_docstr():