X-Git-Url: https://git.madduck.net/etc/taskwarrior.git/blobdiff_plain/01590b11dce299da1d20ced3561bc78786dacac7..3c47c1b8537fcd2557ee86374b8e234b521eee8f:/tasklib/task.py diff --git a/tasklib/task.py b/tasklib/task.py index 65679dc..f2b020d 100644 --- a/tasklib/task.py +++ b/tasklib/task.py @@ -71,11 +71,23 @@ class TaskAnnotation(TaskResource): class Task(TaskResource): - read_only_fields = ['id', 'entry', 'urgency'] + read_only_fields = ['id', 'entry', 'urgency', 'uuid'] class DoesNotExist(Exception): pass + class CompletedTask(Exception): + """ + Raised when the operation cannot be performed on the completed task. + """ + pass + + class DeletedTask(Exception): + """ + Raised when the operation cannot be performed on the deleted task. + """ + pass + def __init__(self, warrior, data={}): self.warrior = warrior self._load_data(data) @@ -84,6 +96,22 @@ class Task(TaskResource): def __unicode__(self): return self['description'] + @property + def completed(self): + return self['status'] == six.text_type('completed') + + @property + def deleted(self): + return self['status'] == six.text_type('deleted') + + @property + def waiting(self): + return self['status'] == six.text_type('waiting') + + @property + def pending(self): + return self['status'] == six.text_type('pending') + def serialize_due(self, date): return date.strftime(DATE_FORMAT) @@ -104,28 +132,49 @@ class Task(TaskResource): return ','.join(tags) if tags else '' def delete(self): - self.warrior.execute_command([self['id'], 'delete'], config_override={ + # Refresh the status, and raise exception if the task is deleted + self.refresh(only_fields=['status']) + + if self.deleted: + raise self.DeletedTask("Task was already deleted") + + self.warrior.execute_command([self['uuid'], 'delete'], config_override={ 'confirmation': 'no', }) + # Refresh the status again, so that we have updated info stored + self.refresh(only_fields=['status']) + + def done(self): - self.warrior.execute_command([self['id'], 'done']) + # Refresh, and raise exception if task is already completed/deleted + self.refresh(only_fields=['status']) + + if self.completed: + raise self.CompletedTask("Cannot complete a completed task") + elif self.deleted: + raise self.DeletedTask("Deleted task cannot be completed") + + self.warrior.execute_command([self['uuid'], 'done']) + + # Refresh the status again, so that we have updated info stored + self.refresh(only_fields=['status']) def save(self): - args = [self['id'], 'modify'] if self['id'] else ['add'] + args = [self['uuid'], 'modify'] if self['uuid'] else ['add'] args.extend(self._get_modified_fields_as_args()) self.warrior.execute_command(args) self._modified_fields.clear() def add_annotation(self, annotation): - args = [self['id'], 'annotate', annotation] + args = [self['uuid'], 'annotate', annotation] self.warrior.execute_command(args) self.refresh(only_fields=['annotations']) def remove_annotation(self, annotation): if isinstance(annotation, TaskAnnotation): annotation = annotation['description'] - args = [self['id'], 'denotate', annotation] + args = [self['uuid'], 'denotate', annotation] self.warrior.execute_command(args) self.refresh(only_fields=['annotations']) @@ -159,6 +208,10 @@ class TaskFilter(object): def add_filter_param(self, key, value): key = key.replace('__', '.') + + # Replace the value with empty string, since that is the + # convention in TW for empty values + value = value if value is not None else '' self.filter_params.append('{0}:{1}'.format(key, value)) def get_filter_params(self):