def set_due_date(self, new_duedate): """Defines the task's due date.""" def __get_defined_parent_list(task): """Recursively fetch a list of parents that have a defined due date which is not fuzzy""" parent_list = [] for par_id in task.parents: par = self.req.get_task(par_id) if par.get_due_date().is_fuzzy(): parent_list += __get_defined_parent_list(par) else: parent_list.append(par) return parent_list def __get_defined_child_list(task): """Recursively fetch a list of children that have a defined due date which is not fuzzy""" child_list = [] for child_id in task.children: child = self.req.get_task(child_id) if child.get_due_date().is_fuzzy(): child_list += __get_defined_child_list(child) else: child_list.append(child) return child_list old_due_date = self.due_date new_duedate_obj = Date(new_duedate) # caching the conversion self.due_date = new_duedate_obj # If the new date is fuzzy or undefined, we don't update related tasks if not new_duedate_obj.is_fuzzy(): # if the task's start date happens later than the # new due date, we update it (except for fuzzy dates) if not self.get_start_date().is_fuzzy() and \ self.get_start_date() > new_duedate_obj: self.set_start_date(new_duedate) # if some ancestors' due dates happen before the task's new # due date, we update them (except for fuzzy dates) for par in __get_defined_parent_list(self): if par.get_due_date() < new_duedate_obj: par.set_due_date(new_duedate) # we must apply the constraints to the defined & non-fuzzy children # as well for sub in __get_defined_child_list(self): sub_duedate = sub.get_due_date() # if the child's due date happens later than the task's: we # update it to the task's new due date if sub_duedate > new_duedate_obj: sub.set_due_date(new_duedate) # if the child's start date happens later than # the task's new due date, we update it # (except for fuzzy start dates) sub_startdate = sub.get_start_date() if not sub_startdate.is_fuzzy() and \ sub_startdate > new_duedate_obj: sub.set_start_date(new_duedate) # If the date changed, we notify the change for the children since the # constraints might have changed if old_due_date != new_duedate_obj: self.recursive_sync()
def date_due(self, value: Date) -> None: self._date_due = value if not value or value.is_fuzzy(): return for child in self.children: if (child.date_due and not child.date_due.is_fuzzy() and child.date_due > value): child.date_due = value if (self.parent and self.parent.date_due and self.parent.date_due.is_fuzzy() and self.parent.date_due < value): self.parent.date_due = value
def convert_task(task: et.Element, ds: datastore) -> Optional[et.Element]: """Convert old task XML into the new format.""" tid = task.attrib['id'] real_task = ds.task_factory(tid) if task is None: return # Get the old task properties # TIDs were stored as UUID, but sometimes they were not present tid = task.get('uuid') or real_task.get_uuid() or tid_cache[tid] status = task.get('status') title = task.find('title').text content = task.find('content') try: done_date = task.find('donedate').text except AttributeError: done_date = None try: due_date = task.find('duedate').text except AttributeError: due_date = None try: modified = task.find('modified').text except AttributeError: modified = None try: added = task.find('added').text except AttributeError: added = None try: start = task.find('startdate').text except AttributeError: start = None # Build the new task new_task = et.Element('task') new_task.set('status', status) new_task.set('id', tid) new_title = et.SubElement(new_task, 'title') new_title.text = title tags = et.SubElement(new_task, 'tags') for tag_name in task.get('tags').split(','): if tag_name: tag_id = tags_cache[tag_name] task_tag = et.SubElement(tags, 'tag') task_tag.text = tag_id dates = et.SubElement(new_task, 'dates') new_added = et.SubElement(dates, 'added') new_modified = et.SubElement(dates, 'modified') if added: added = str(Date(added)) else: added = date.today().isoformat() new_added.text = added if modified: modified = modified[:10] modified = str(Date(modified)) else: modified = date.today().isoformat() new_modified.text = modified if done_date: new_done = et.SubElement(dates, 'done') new_done.text = str(Date(done_date)) if start: start = Date(start) if start.is_fuzzy(): new_start = et.SubElement(dates, 'fuzzyStart') else: new_start = et.SubElement(dates, 'start') new_start.text = str(start) if due_date: due_date = Date(due_date) if due_date.is_fuzzy(): new_due = et.SubElement(dates, 'fuzzyDue') else: new_due = et.SubElement(dates, 'due') new_due.text = str(due_date) recurring = et.SubElement(new_task, 'recurring') recurring.set('enabled', 'false') subtasks = et.SubElement(new_task, 'subtasks') for sub in task.findall('subtask'): new_sub = et.SubElement(subtasks, 'sub') new_sub.text = tid_cache[sub.text] new_content = et.SubElement(new_task, 'content') if content is not None: new_content.text = et.CDATA(convert_content(content.text)) else: new_content.text = et.CDATA('') return new_task