diff --git a/jedi/cache.py b/jedi/cache.py index 931ddf88..64252851 100644 --- a/jedi/cache.py +++ b/jedi/cache.py @@ -147,6 +147,21 @@ def underscore_memoization(func): return wrapper +def memoize(func): + """A normal memoize function.""" + dct = {} + + def wrapper(*args, **kwargs): + key = (args, frozenset(kwargs.items())) + try: + return dct[key] + except KeyError: + result = func(*args, **kwargs) + dct[key] = result + return result + return wrapper + + def cache_star_import(func): def wrapper(evaluator, scope, *args, **kwargs): with common.ignored(KeyError): diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index 7a3eaf52..df82cbb8 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -8,7 +8,7 @@ import os from jedi._compatibility import builtins as _builtins, unicode from jedi import debug -from jedi.cache import underscore_memoization +from jedi.cache import underscore_memoization, memoize from jedi.evaluate.sys_path import get_sys_path from jedi.parser.representation import Param, SubModule, Base, IsScope, Operator from jedi.evaluate.helpers import FakeName @@ -307,11 +307,13 @@ def _parse_function_doc(doc): class Builtin(CompiledObject, IsScope): + @memoize def get_defined_names(self): # Filter None, because it's really just a keyword, nobody wants to # access it. return [d for d in super(Builtin, self).get_defined_names() if d.name != 'None'] + @memoize def get_by_name(self, name): item = [n for n in self.get_defined_names() if n.get_code() == name][0] return item.parent diff --git a/test/test_speed.py b/test/test_speed.py index be39cc08..dabc0d57 100644 --- a/test/test_speed.py +++ b/test/test_speed.py @@ -25,7 +25,7 @@ class TestSpeed(TestCase): func(self) single_time = (time.time() - first) / number print('\nspeed', func, single_time) - assert single_time < time_per_run, 'Too slow.' + assert single_time < time_per_run return wrapper return decorated