X-Git-Url: https://git.madduck.net/etc/taskwarrior.git/blobdiff_plain/092349699c57d6b36346e44a80220e941033d1ca..f58549e864220709de81b141b0343195e70fc6f5:/tasklib/task.py?ds=sidebyside diff --git a/tasklib/task.py b/tasklib/task.py index a24f8db..6e3e432 100644 --- a/tasklib/task.py +++ b/tasklib/task.py @@ -1,25 +1,22 @@ from __future__ import print_function import copy -import datetime +import importlib import json import logging import os -import pytz import six import sys -import tzlocal -from backends import TaskWarrior, TaskWarriorException -from serializing import SerializingObject +from .serializing import SerializingObject DATE_FORMAT = '%Y%m%dT%H%M%SZ' -DATE_FORMAT_CALC = '%Y-%m-%dT%H:%M:%S' REPR_OUTPUT_SIZE = 10 PENDING = 'pending' COMPLETED = 'completed' +DELETED = 'deleted' +WAITING = 'waiting' logger = logging.getLogger(__name__) -local_zone = tzlocal.get_localzone() class ReadOnlyDictView(object): @@ -43,6 +40,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)) @@ -80,7 +82,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 @@ -125,7 +126,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): @@ -153,7 +154,7 @@ class TaskAnnotation(TaskResource): def __init__(self, task, data=None): self.task = task self._load_data(data or dict()) - super(TaskAnnotation, self).__init__(task.warrior) + super(TaskAnnotation, self).__init__(task.backend) def remove(self): self.task.remove_annotation(self) @@ -166,6 +167,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__ @@ -207,7 +211,7 @@ class Task(TaskResource): pass @classmethod - def from_input(cls, input_file=sys.stdin, modify=None, warrior=None): + def from_input(cls, input_file=sys.stdin, modify=None, backend=None): """ Creates a Task object, directly from the stdin, by reading one line. If modify=True, two lines are used, first line interpreted as the @@ -228,12 +232,13 @@ class Task(TaskResource): modify = name.startswith('on-modify') if modify is None else modify # Create the TaskWarrior instance if none passed - if warrior is None: + if backend is None: + backends = importlib.import_module('tasklib.backends') hook_parent_dir = os.path.dirname(os.path.dirname(sys.argv[0])) - warrior = TaskWarrior(data_location=hook_parent_dir) + backend = backends.TaskWarrior(data_location=hook_parent_dir) # TaskWarrior instance is set to None - task = cls(warrior) + task = cls(backend) # Load the data from the input task._load_data(json.loads(input_file.readline().strip())) @@ -246,8 +251,8 @@ class Task(TaskResource): return task - def __init__(self, warrior, **kwargs): - super(Task, self).__init__(warrior) + def __init__(self, backend, **kwargs): + super(Task, self).__init__(backend) # Check that user is not able to set read-only value in __init__ for key in kwargs.keys(): @@ -277,6 +282,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']: @@ -423,21 +430,22 @@ class Task(TaskResource): else: self._load_data(new_data) + class TaskQuerySet(object): """ Represents a lazy lookup for a task objects. """ - def __init__(self, warrior=None, filter_obj=None): - self.warrior = warrior + def __init__(self, backend, filter_obj=None): + self.backend = backend self._result_cache = None - self.filter_obj = filter_obj or TaskWarriorFilter(warrior) + self.filter_obj = filter_obj or self.backend.filter_class(backend) def __deepcopy__(self, memo): """ 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 @@ -482,7 +490,7 @@ class TaskQuerySet(object): if klass is None: klass = self.__class__ filter_obj = self.filter_obj.clone() - c = klass(warrior=self.warrior, filter_obj=filter_obj) + c = klass(backend=self.backend, filter_obj=filter_obj) c.__dict__.update(kwargs) return c @@ -490,7 +498,7 @@ class TaskQuerySet(object): """ Fetch the tasks which match the current filters. """ - return self.warrior.filter_tasks(self.filter_obj) + return self.backend.filter_tasks(self.filter_obj) def all(self): """ @@ -504,6 +512,12 @@ 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 filter(self, *args, **kwargs): """ Returns a new TaskQuerySet with the given filters added.