X-Git-Url: https://git.madduck.net/etc/taskwarrior.git/blobdiff_plain/73b53d933f2285aaa2ecf1672be44eabf2979316..dd44e7a4b6a175a6d88d16ccb2bd6ca05f6d9dc5:/tasklib/backends.py?ds=inline

diff --git a/tasklib/backends.py b/tasklib/backends.py
index 6bba35d..fa5ce86 100644
--- a/tasklib/backends.py
+++ b/tasklib/backends.py
@@ -1,4 +1,5 @@
 import abc
+import copy
 import datetime
 import json
 import logging
@@ -6,8 +7,9 @@ import os
 import re
 import six
 import subprocess
+import copy
 
-from .task import Task, TaskQuerySet
+from .task import Task, TaskQuerySet, ReadOnlyDictView
 from .filters import TaskWarriorFilter
 from .serializing import local_zone
 
@@ -15,6 +17,7 @@ DATE_FORMAT_CALC = '%Y-%m-%dT%H:%M:%S'
 
 logger = logging.getLogger(__name__)
 
+
 class Backend(object):
 
     @abc.abstractproperty
@@ -80,7 +83,7 @@ class TaskWarriorException(Exception):
     pass
 
 
-class TaskWarrior(object):
+class TaskWarrior(Backend):
 
     VERSION_2_1_0 = six.u('2.1.0')
     VERSION_2_2_0 = six.u('2.2.0')
@@ -100,8 +103,9 @@ class TaskWarrior(object):
         if not os.path.exists(self.taskrc_location):
             self.taskrc_location = '/'
 
+        self._config = None
         self.version = self._get_version()
-        self.config = {
+        self.overrides = {
             'confirmation': 'no',
             'dependency.confirmation': 'no',  # See TW-1483 or taskrc man page
             'recurrence.confirmation': 'no',  # Necessary for modifying R tasks
@@ -119,24 +123,24 @@ class TaskWarrior(object):
             data_location = os.path.expanduser(data_location)
             if create and not os.path.exists(data_location):
                 os.makedirs(data_location)
-            self.config['data.location'] = data_location
+            self.overrides['data.location'] = data_location
 
         self.tasks = TaskQuerySet(self)
 
     def _get_command_args(self, args, config_override=None):
         command_args = ['task', 'rc:{0}'.format(self.taskrc_location)]
-        config = self.config.copy()
-        config.update(config_override or dict())
-        for item in config.items():
+        overrides = self.overrides.copy()
+        overrides.update(config_override or dict())
+        for item in overrides.items():
             command_args.append('rc.{0}={1}'.format(*item))
         command_args.extend(map(six.text_type, args))
         return command_args
 
     def _get_version(self):
         p = subprocess.Popen(
-                ['task', '--version'],
-                stdout=subprocess.PIPE,
-                stderr=subprocess.PIPE)
+            ['task', '--version'],
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE)
         stdout, stderr = [x.decode('utf-8') for x in p.communicate()]
         return stdout.strip('\n')
 
@@ -153,10 +157,11 @@ class TaskWarrior(object):
             if serialized_value is '':
                 escaped_serialized_value = ''
             else:
-                escaped_serialized_value = six.u("'{0}'").format(serialized_value)
+                escaped_serialized_value = six.u("'{0}'").format(
+                    serialized_value)
 
-            format_default = lambda task: six.u("{0}:{1}").format(field,
-                                                      escaped_serialized_value)
+            format_default = lambda task: six.u("{0}:{1}").format(
+                field, escaped_serialized_value)
 
             format_func = getattr(self, 'format_{0}'.format(field),
                                   format_default)
@@ -186,14 +191,14 @@ class TaskWarrior(object):
 
         old_dependencies = task._original_data.get('depends', set())
 
-        added = self['depends'] - old_dependencies
-        removed = old_dependencies - self['depends']
+        added = task['depends'] - old_dependencies
+        removed = old_dependencies - task['depends']
 
         # Removed dependencies need to be prefixed with '-'
         return 'depends:' + ','.join(
-                [t['uuid'] for t in added] +
-                ['-' + t['uuid'] for t in removed]
-            )
+            [t['uuid'] for t in added] +
+            ['-' + t['uuid'] for t in removed]
+        )
 
     def format_description(self, task):
         # Task version older than 2.4.0 ignores first word of the
@@ -217,17 +222,25 @@ class TaskWarrior(object):
                              "datetime, its type is not supported: {}"
                              .format(type(value)))
 
+        return localized
+
     @property
     def filter_class(self):
         return TaskWarriorFilter
 
     # Public interface
 
-    def get_config(self):
+    @property
+    def config(self):
+        # First, check if memoized information is available
+        if self._config:
+            return self._config
+
+        # If not, fetch the config using the 'show' command
         raw_output = self.execute_command(
-                ['show'],
-                config_override={'verbose': 'nothing'}
-            )
+            ['show'],
+            config_override={'verbose': 'nothing'}
+        )
 
         config = dict()
         config_regex = re.compile(r'^(?P<key>[^\s]+)\s+(?P<value>[^\s].+$)')
@@ -237,7 +250,10 @@ class TaskWarrior(object):
             if match:
                 config[match.group('key')] = match.group('value').strip()
 
-        return config
+        # Memoize the config dict
+        self._config = ReadOnlyDictView(config)
+
+        return self._config
 
     def execute_command(self, args, config_override=None, allow_failure=True,
                         return_all=False):
@@ -378,14 +394,14 @@ class TaskWarrior(object):
                 taskfilter.add_filter_param(key, value)
 
             output = self.execute_command(['export', '--'] +
-                taskfilter.get_filter_params())
+                                          taskfilter.get_filter_params())
 
         # If more than 1 task has been matched still, raise an exception
         if not valid(output):
             raise TaskWarriorException(
                 "Unique identifiers {0} with description: {1} matches "
                 "multiple tasks: {2}".format(
-                task['uuid'] or task['id'], task['description'], output)
+                    task['uuid'] or task['id'], task['description'], output)
             )
 
         return json.loads(output[0])