X-Git-Url: https://git.madduck.net/etc/taskwarrior.git/blobdiff_plain/e81c1cd2f8bda4c8a6d1c29d75a6835a405a08b4..1225677a596f1c36eb54ed15459ac9a40f0233e2:/tasklib/task.py diff --git a/tasklib/task.py b/tasklib/task.py index b9cc447..c97aee8 100644 --- a/tasklib/task.py +++ b/tasklib/task.py @@ -1,6 +1,5 @@ from __future__ import print_function import copy -import datetime import importlib import json import logging @@ -14,6 +13,9 @@ DATE_FORMAT = '%Y%m%dT%H%M%SZ' REPR_OUTPUT_SIZE = 10 PENDING = 'pending' COMPLETED = 'completed' +DELETED = 'deleted' +WAITING = 'waiting' +RECURRING = 'recurring' logger = logging.getLogger(__name__) @@ -39,6 +41,11 @@ class ReadOnlyDictView(object): def __len__(self): return len(self.viewed_dict) + def __unicode__(self): + return six.u('ReadOnlyDictView: {0}'.format(repr(self.viewed_dict))) + + __repr__ = __unicode__ + def get(self, key, default=None): return copy.deepcopy(self.viewed_dict.get(key, default)) @@ -76,7 +83,6 @@ class TaskResource(SerializingObject): if update_original: self._original_data = copy.deepcopy(self._data) - def __getitem__(self, key): # This is a workaround to make TaskResource non-iterable # over simple index-based iteration @@ -121,7 +127,7 @@ class TaskResource(SerializingObject): # to pass that to TaskWarrior. data_tuples = filter(lambda t: t[1] is not '', data_tuples) data = dict(data_tuples) - return json.dumps(data, separators=(',',':')) + return json.dumps(data, separators=(',', ':')) @property def _modified_fields(self): @@ -162,6 +168,9 @@ class TaskAnnotation(TaskResource): # their data dics are the same return self.task == other.task and self._data == other._data + def __ne__(self, other): + return not self.__eq__(other) + __repr__ = __unicode__ @@ -225,7 +234,7 @@ class Task(TaskResource): # Create the TaskWarrior instance if none passed if backend is None: - backends = importlib.import_module('.backends') + backends = importlib.import_module('tasklib.backends') hook_parent_dir = os.path.dirname(os.path.dirname(sys.argv[0])) backend = backends.TaskWarrior(data_location=hook_parent_dir) @@ -274,6 +283,8 @@ class Task(TaskResource): # If the tasks are not saved, compare the actual instances return id(self) == id(other) + def __ne__(self, other): + return not self.__eq__(other) def __hash__(self): if self['uuid']: @@ -299,6 +310,10 @@ class Task(TaskResource): def pending(self): return self['status'] == six.text_type('pending') + @property + def recurring(self): + return self['status'] == six.text_type('recurring') + @property def active(self): return self['start'] is not None @@ -318,7 +333,8 @@ class Task(TaskResource): def delete(self): if not self.saved: - raise Task.NotSaved("Task needs to be saved before it can be deleted") + raise Task.NotSaved( + "Task needs to be saved before it can be deleted") # Refresh the status, and raise exception if the task is deleted self.refresh(only_fields=['status']) @@ -333,7 +349,8 @@ class Task(TaskResource): def start(self): if not self.saved: - raise Task.NotSaved("Task needs to be saved before it can be started") + raise Task.NotSaved( + "Task needs to be saved before it can be started") # Refresh, and raise exception if task is already completed/deleted self.refresh(only_fields=['status']) @@ -352,7 +369,8 @@ class Task(TaskResource): def stop(self): if not self.saved: - raise Task.NotSaved("Task needs to be saved before it can be stopped") + raise Task.NotSaved( + "Task needs to be saved before it can be stopped") # Refresh, and raise exception if task is already completed/deleted self.refresh(only_fields=['status']) @@ -367,7 +385,8 @@ class Task(TaskResource): def done(self): if not self.saved: - raise Task.NotSaved("Task needs to be saved before it can be completed") + raise Task.NotSaved( + "Task needs to be saved before it can be completed") # Refresh, and raise exception if task is already completed/deleted self.refresh(only_fields=['status']) @@ -420,12 +439,13 @@ class Task(TaskResource): else: self._load_data(new_data) + class TaskQuerySet(object): """ Represents a lazy lookup for a task objects. """ - def __init__(self, backend=None, filter_obj=None): + def __init__(self, backend, filter_obj=None): self.backend = backend self._result_cache = None self.filter_obj = filter_obj or self.backend.filter_class(backend) @@ -434,7 +454,7 @@ class TaskQuerySet(object): """ Deep copy of a QuerySet doesn't populate the cache """ - obj = self.__class__() + obj = self.__class__(backend=self.backend) for k, v in self.__dict__.items(): if k in ('_iter', '_result_cache'): obj.__dict__[k] = None @@ -501,6 +521,15 @@ class TaskQuerySet(object): def completed(self): return self.filter(status=COMPLETED) + def deleted(self): + return self.filter(status=DELETED) + + def waiting(self): + return self.filter(status=WAITING) + + def recurring(self): + return self.filter(status=RECURRING) + def filter(self, *args, **kwargs): """ Returns a new TaskQuerySet with the given filters added.