Skip to content

Commit

Permalink
Merge pull request #57 from coddingtonbear/only_change_if_changes_exi…
Browse files Browse the repository at this point in the history
…st_when_using_modern_task

Only attempt to change fields known to have changed if using new journal...
  • Loading branch information
coddingtonbear committed Apr 15, 2014
2 parents 7bf7dd5 + dfd5931 commit 78eef2a
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 23 deletions.
9 changes: 9 additions & 0 deletions taskw/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,15 @@ def serialized(self):
serialized[k] = self._serialize(k, v)
return serialized

def serialized_changes(self, keep=False):
serialized = {}
for k, v in six.iteritems(self.get_changes(keep=keep)):
# Here, `v` is a 2-tuple of the field's original value
# and the field's new value.
_, to = v
serialized[k] = self._serialize(k, to)
return serialized

def __getitem__(self, key):
try:
return super(Task, self).__getitem__(key)
Expand Down
70 changes: 47 additions & 23 deletions taskw/warrior.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,12 +706,19 @@ def task_done(self, **kw):
def task_update(self, task):
if 'uuid' not in task:
raise KeyError('Task must have a UUID.')
# 'Legacy' causes us to handle this task as if it were an
# old-style task -- just a standard dictionary
legacy = True

if isinstance(task, Task):
# Let's pre-serialize taskw.task.Task instances
task = task.serialized()
task_uuid = six.text_type(task['uuid'])
task = task.serialized_changes(keep=True)
legacy = False
else:
task_uuid = task['uuid']

id, original_task = self.get_task(uuid=task['uuid'])
id, original_task = self.get_task(uuid=task_uuid)

if 'id' in task:
del task['id']
Expand All @@ -721,35 +728,52 @@ def task_update(self, task):
task_to_modify.pop('uuid', None)
task_to_modify.pop('id', None)

# Check if there are annotations, if so, look if they are
# in the existing task, otherwise annotate the task to add them.
ttm_annotations = taskw.utils.annotation_list_to_comparison_map(
self._extract_annotations_from_task(task_to_modify)
)
original_annotations = taskw.utils.annotation_list_to_comparison_map(
self._extract_annotations_from_task(original_task)
)
# Only handle annotation differences if this is an old-style
# task, or if the task itself says annotations have changed.
annotations_to_delete = set()
annotations_to_create = set()
if legacy or 'annotations' in task_to_modify:
# Check if there are annotations, if so, look if they are
# in the existing task, otherwise annotate the task to add them.
ttm_annotations = taskw.utils.annotation_list_to_comparison_map(
self._extract_annotations_from_task(task_to_modify)
)
original_annotations = (
taskw.utils.annotation_list_to_comparison_map(
self._extract_annotations_from_task(original_task)
)
)

new_annotations = set(ttm_annotations.keys())
existing_annotations = set(original_annotations.keys())
new_annotations = set(ttm_annotations.keys())
existing_annotations = set(original_annotations.keys())

annotations_to_delete = existing_annotations - new_annotations
annotations_to_create = new_annotations - existing_annotations
annotations_to_delete = existing_annotations - new_annotations
annotations_to_create = new_annotations - existing_annotations

if 'annotations' in task_to_modify:
del task_to_modify['annotations']
if 'annotations' in task_to_modify:
del task_to_modify['annotations']

modification = taskw.utils.encode_task_experimental(task_to_modify)
self._execute(task['uuid'], 'modify', modification)
# Only try to modify the task if there are changes to post here
# (changes *might* just be in annotations).
if modification.strip():
self._execute(task_uuid, 'modify', modification)

# If there are no existing annotations, add the new ones
ttm_annotations.update(original_annotations)
for annotation_key in annotations_to_create:
self.task_annotate(original_task, ttm_annotations[annotation_key])
for annotation_key in annotations_to_delete:
self.task_denotate(original_task, ttm_annotations[annotation_key])
if legacy or annotations_to_delete or annotations_to_create:
ttm_annotations.update(original_annotations)
for annotation_key in annotations_to_create:
self.task_annotate(
original_task,
ttm_annotations[annotation_key]
)
for annotation_key in annotations_to_delete:
self.task_denotate(
original_task,
ttm_annotations[annotation_key]
)

return self.get_task(uuid=original_task['uuid'])
return self.get_task(uuid=task_uuid)

def task_delete(self, **kw):
""" Marks a task as deleted. """
Expand Down

0 comments on commit 78eef2a

Please sign in to comment.