summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2017-06-15 10:08:18 +0100
committerPatrick Totzke <patricktotzke@gmail.com>2017-06-15 11:01:48 +0100
commit36e9d2948190891df7407f5fb98f0cf181f659d0 (patch)
tree3024e52e86659f6e4929cf2ca524d797038ebbb8
parentcc140e518be6f97ca7856d5121e4246c495af29b (diff)
conservative lookup of sub-completers
via cached properties
-rw-r--r--alot/completion.py36
-rw-r--r--alot/utils/cached_property.py43
2 files changed, 72 insertions, 7 deletions
diff --git a/alot/completion.py b/alot/completion.py
index 08089930..046f4571 100644
--- a/alot/completion.py
+++ b/alot/completion.py
@@ -19,6 +19,7 @@ from .utils import argparse as cargparse
from .helper import split_commandline
from .addressbook import AddressbookError
from .errors import CompletionError
+from .utils.cached_property import cached_property
class Completer(object):
@@ -320,14 +321,35 @@ class CommandCompleter(Completer):
self.mode = mode
self.currentbuffer = currentbuffer
self._commandnamecompleter = CommandNameCompleter(mode)
- self._querycompleter = QueryCompleter(dbman)
- self._tagcompleter = TagCompleter(dbman)
+
+ @cached_property
+ def _querycompleter(self):
+ return QueryCompleter(self.dbman)
+
+ @cached_property
+ def _tagcompleter(self):
+ return TagCompleter(self.dbman)
+
+ @cached_property
+ def _contactscompleter(self):
abooks = settings.get_addressbooks()
- self._contactscompleter = ContactsCompleter(abooks)
- self._pathcompleter = PathCompleter()
- self._accountscompleter = AccountCompleter()
- self._secretkeyscompleter = CryptoKeyCompleter(private=True)
- self._publickeyscompleter = CryptoKeyCompleter(private=False)
+ return ContactsCompleter(abooks)
+
+ @cached_property
+ def _pathcompleter(self):
+ return PathCompleter()
+
+ @cached_property
+ def _accountscompleter(self):
+ return AccountCompleter()
+
+ @cached_property
+ def _secretkeyscompleter(self):
+ return CryptoKeyCompleter(private=True)
+
+ @cached_property
+ def _publickeyscompleter(self):
+ return CryptoKeyCompleter(private=False)
def complete(self, line, pos):
# remember how many preceding space characters we see until the command
diff --git a/alot/utils/cached_property.py b/alot/utils/cached_property.py
new file mode 100644
index 00000000..95ca954b
--- /dev/null
+++ b/alot/utils/cached_property.py
@@ -0,0 +1,43 @@
+# werkzeug.utils.cached_property
+
+_missing = object()
+
+class cached_property(object):
+ """A decorator that converts a function into a lazy property. The
+ function wrapped is called the first time to retrieve the result
+ and then that calculated result is used the next time you access
+ the value::
+
+ class Foo(object):
+
+ @cached_property
+ def foo(self):
+ # calculate something important here
+ return 42
+
+ The class has to have a `__dict__` in order for this property to
+ work.
+ """
+
+ # implementation detail: this property is implemented as non-data
+ # descriptor. non-data descriptors are only invoked if there is
+ # no entry with the same name in the instance's __dict__.
+ # this allows us to completely get rid of the access function call
+ # overhead. If one choses to invoke __get__ by hand the property
+ # will still work as expected because the lookup logic is replicated
+ # in __get__ for manual invocation.
+
+ def __init__(self, func, name=None, doc=None):
+ self.__name__ = name or func.__name__
+ self.__module__ = func.__module__
+ self.__doc__ = doc or func.__doc__
+ self.func = func
+
+ def __get__(self, obj, type=None):
+ if obj is None:
+ return self
+ value = obj.__dict__.get(self.__name__, _missing)
+ if value is _missing:
+ value = self.func(obj)
+ obj.__dict__[self.__name__] = value
+ return value