X-Git-Url: https://git.madduck.net/etc/taskwarrior.git/blobdiff_plain/5fe9dbdc944f57eacd1041f518a6703057f6e5f5..628b2d244b841be6494b87a14c3f78f0aa1cfc0e:/tasklib/task.py diff --git a/tasklib/task.py b/tasklib/task.py index 73280b0..dc27460 100644 --- a/tasklib/task.py +++ b/tasklib/task.py @@ -28,6 +28,40 @@ class TaskWarriorException(Exception): pass +class ReadOnlyDictView(object): + """ + Provides simplified read-only view upon dict object. + """ + + def __init__(self, viewed_dict): + self.viewed_dict = viewed_dict + + def __getitem__(self, key): + return copy.deepcopy(self.viewed_dict.__getitem__(key)) + + def __contains__(self, k): + return self.viewed_dict.__contains__(k) + + def __iter__(self): + for value in self.viewed_dict: + yield copy.deepcopy(value) + + def __len__(self): + return len(self.viewed_dict) + + def get(self, key, default=None): + return copy.deepcopy(self.viewed_dict.get(key, default)) + + def has_key(self, key): + return self.viewed_dict.has_key(key) + + def items(self): + return [copy.deepcopy(v) for v in self.viewed_dict.items()] + + def values(self): + return [copy.deepcopy(v) for v in self.viewed_dict.values()] + + class SerializingObject(object): """ Common ancestor for TaskResource & TaskFilter, since they both @@ -195,7 +229,13 @@ class SerializingObject(object): localized = value return localized - + + def normalize_uuid(self, value): + # Enforce sane UUID + if not isinstance(value, six.text_type) or value == '': + raise ValueError("UUID must be a valid non-empty string.") + + return value class TaskResource(SerializingObject): @@ -777,14 +817,14 @@ class TaskWarrior(object): stdout, stderr = [x.decode('utf-8') for x in p.communicate()] return stdout.strip('\n') - def execute_command(self, args, config_override={}): + def execute_command(self, args, config_override={}, allow_failure=True): command_args = self._get_command_args( args, config_override=config_override) logger.debug(' '.join(command_args)) p = subprocess.Popen(command_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = [x.decode('utf-8') for x in p.communicate()] - if p.returncode: + if p.returncode and allow_failure: if stderr.strip(): error_msg = stderr.strip().splitlines()[-1] else: @@ -792,7 +832,15 @@ class TaskWarrior(object): raise TaskWarriorException(error_msg) return stdout.strip().split('\n') + def enforce_recurrence(self): + # Run arbitrary report command which will trigger generation + # of recurrent tasks. + # TODO: Make a version dependant enforcement once + # TW-1531 is handled + self.execute_command(['next'], allow_failure=False) + def filter_tasks(self, filter_obj): + self.enforce_recurrence() args = ['export', '--'] + filter_obj.get_filter_params() tasks = [] for line in self.execute_command(args):