def _load_task(self, row, parents_stack): task = models.Task(self.schedule) cells, unknown_cells = self._load_task_cells(row) task.index = row.row_number # task.slug is generated at the end of importing whole schedule # skip empty rows if not all([c in cells and cells[c] for c in COLUMN_TASK_NAME, COLUMN_START, COLUMN_FINISH]): # skip load, task doesn't contain all needed info return
def _parse_task_element(self, task, eTask): task.index = self.task_index self.task_index += 1 task.slug = eTask.get('id') task.name = eTask.get('name').strip() notes = eTask.xpath('note') if notes: task.note = notes[0].text.strip() task.priority = int(eTask.get('priority')) task.milestone = eTask.get('milestone') == '1' p_complete_attr = eTask.xpath('./taskScenario[@scenarioId=\'actual\']') p_complete = float(p_complete_attr[0].get('complete')) if p_complete < 0: p_complete = 0.0 task.p_complete = p_complete task.dStart = self._load_tjx_date(eTask, 'actual', 'start') or self._load_tjx_date( eTask, 'plan', 'start') task.dFinish = self._load_tjx_date(eTask, 'actual', 'end') or self._load_tjx_date( eTask, 'plan', 'end') if task.milestone: task.dFinish = task.dStart for eFlag in eTask.xpath('./flag'): task.flags.append(eFlag.text) link_el = eTask.xpath( 'customAttribute[@id="PTask"]/referenceAttribute') if link_el: task.link = link_el[0].get('url') # add flags from task to global used tags task._schedule.used_flags |= set(task.flags) min_date = task.dStart max_date = task.dFinish for eSubTask in eTask.xpath('./task'): item_task = models.Task(self.schedule, task.level + 1) t_min_date, t_max_date = self._parse_task_element( item_task, eSubTask) min_date = min(min_date, t_min_date) max_date = max(max_date, t_max_date) task.tasks.append(item_task) return min_date, max_date
def import_schedule(self): self.schedule = models.Schedule() tree = self._get_parsed_tree() el_proj = tree.xpath('/taskjuggler/project')[0] self.schedule.name = '%s %s' % (el_proj.get('name'), el_proj.get('version')) self.schedule.slug = el_proj.get('id') # import changelog/mtime from content of TJX self.schedule.changelog = self.get_handle_changelog() self.schedule.mtime = self.get_handle_mtime() min_date = datetime.datetime.max max_date = datetime.datetime.min for task in tree.xpath('/taskjuggler/taskList/task'): item_task = models.Task(self.schedule) self._parse_task_element(item_task, task) min_date = min(min_date, item_task.dStart) max_date = max(max_date, item_task.dFinish) self.schedule.tasks.append(item_task) if self.schedule.tasks: self.schedule.dStart = min_date self.schedule.dFinish = max_date self.schedule.name = self.schedule.tasks[0].name else: # try to load dates from project level tag = el_proj.xpath('start')[0].text start = datetime.datetime.fromtimestamp(float(tag)) if start: self.schedule.dStart = start tag = el_proj.xpath('end')[0].text end = datetime.datetime.fromtimestamp(float(tag)) if end: self.schedule.dFinish = end self.schedule.name = self.schedule.name.strip() return self.schedule
def task_load_tjx_node(self, task, eTask): task.index = int(eTask.xpath('Index')[0].text) task.slug = eTask.get('Id') task.name = eTask.xpath('Name')[0].text.strip() notes = eTask.xpath('Note') if notes: task.note = notes[0].text.strip() task.priority = int(eTask.xpath('Priority')[0].text) task.p_complete = float(eTask.xpath('complete')[0].text) task.dStart = self._load_tjx_date(eTask, 'actual', 'start') or self._load_tjx_date(eTask, 'plan', 'start') task.dFinish = self._load_tjx_date(eTask, 'actual', 'end') or self._load_tjx_date(eTask, 'plan', 'end') # sanity check - if only tart defined and beyond plan finish task.dFinish = max(task.dFinish, task.dStart) task.milestone = eTask.xpath('Type')[0].text == 'Milestone' for eFlag in eTask.xpath('./Flag'): task.flags.append(eFlag.text) task._schedule.used_flags |= set(task.flags) ptask_el = eTask.xpath('./custom[@id="PTask"]') if ptask_el: task.link = ptask_el[0].get('url') min_date = task.dStart max_date = task.dFinish for eSubTask in eTask.xpath('./SubTasks/Task'): task_item = models.Task(task._schedule, task.level + 1) t_min_date, t_max_date = self.task_load_tjx_node(task_item, eSubTask) min_date = min(min_date, t_min_date) max_date = max(max_date, t_max_date) task.tasks.append(task_item) return min_date, max_date
def _load_tasks_level(self, level, eTask_list): return_tasks = [] while eTask_list: eTask = eTask_list[0] task_level = int(eTask.xpath('OutlineLevel')[0].text) if task_level > level: # return tasks may be empty # since there could be no importable tasks yet if len(return_tasks): return_tasks[-1].tasks = self._load_tasks_level( task_level, eTask_list) else: # remove task from list eTask_list.pop(0) continue elif task_level < level: return return_tasks # process task task = models.Task(self.schedule, level=level) if self.task_load_msp_node(task, eTask): # update schedule start/end if self.schedule.dStart: self.schedule.dStart = min(self.schedule.dStart, task.dStart) else: self.schedule.dStart = task.dStart if self.schedule.dFinish: self.schedule.dFinish = max(self.schedule.dFinish, task.dFinish) else: self.schedule.dFinish = task.dFinish return_tasks.append(task) # remove task from list eTask_list.pop(0) return return_tasks
def import_schedule(self): if not self.__class__.is_valid_source(self.handle): raise TJXImportException('Invalid TJX source', source=self.handle) self.schedule = models.Schedule() tree = self._get_parsed_tree() self.schedule.name = '%s %s' % (tree.xpath('Name')[0].text.strip(), tree.xpath('Version')[0].text) slug = str(tree.xpath('@Id')[0]) if slug: self.schedule.slug = slug # look for same id as project, there might be more included root tasks eRoot_task = None eRoot_tasks = tree.xpath('Task[@Id = /Project/@Id]') if not len(eRoot_tasks): # try whatever single root task eRoot_tasks = tree.xpath('Task') root_tasks_count = len(eRoot_tasks) if root_tasks_count == 1: eRoot_task = eRoot_tasks[0] elif root_tasks_count == 0: log.warning('Empty schedule %s ' % (self.handle,)) else: eRoot_task = eRoot_tasks[0] if eRoot_task is not None: root_task_name = eRoot_task.xpath('Name') if root_task_name: self.schedule.name = root_task_name[0].text else: log.info('Can\'t find single root task in {} (found {} root ' 'tasks)'.format(self.handle, len(eRoot_tasks))) self.schedule.name = self.schedule.name.strip() # import changelog/mtime from content of TJX self.schedule.changelog = self.get_handle_changelog() self.schedule.mtime = self.get_handle_mtime() min_date = datetime.datetime.max max_date = datetime.datetime.min for eTask in eRoot_tasks: task = models.Task(self.schedule, level=1) t_min_date, t_max_date = self.task_load_tjx_node(task, eTask) min_date = min(min_date, t_min_date) max_date = max(max_date, t_max_date) self.schedule.tasks.append(task) if self.schedule.tasks: self.schedule.dStart = min_date self.schedule.dFinish = max_date else: # try to load dates from project level start = self._load_tjx_date(tree, 'start') if start: self.schedule.dStart = start end = self._load_tjx_date(tree, 'end') if end: self.schedule.dFinish = end return self.schedule
def import_schedule(self): self.schedule = models.Schedule() start_time = None options = ['--config=%s' % self.handle] server, user, password, workspace, project = rallySettings(options) rally = Rally(server, user, password, workspace=workspace, project=project) rally_iter = self.options['rally_iter'] self.schedule.name = rally_iter.strip() query_criteria = 'Iteration.Name = "%s"' % rally_iter response = rally.get('Iteration', fetch=True, query='Name = "%s"' % rally_iter) if response.errors: sys.stdout.write("\n".join(response.errors)) sys.exit(1) for iteration in response: print 'Iteration: %s (starts %s)' % (iteration.Name, iteration.StartDate) start_time = datetime.datetime.combine( datetime.datetime.strptime(iteration.StartDate[:10], '%Y-%m-%d'), datetime.time(8)) break response = rally.get('UserStory', fetch=True, query=query_criteria, order="Rank") if response.errors: sys.stdout.write("\n".join(response.errors)) sys.exit(1) index = 1 if not start_time: start_time = datetime.datetime.combine(datetime.date.today(), datetime.time(8)) max_end_time = start_time self.schedule.dStart = start_time for story in response: print story.Name t = models.Task(self.schedule, level=1) t.index = index index += 1 t.name = story.Name.strip() t.dStart = start_time max_st_end_time = start_time story.Tasks.sort(key=lambda x: x.TaskIndex) for task in story.Tasks: print '-- %s | %sh | %s' % (task.Name, task.Estimate, task.Owner.Name) t_in = models.Task(self.schedule, level=2) t_in.index = index index += 1 t_in.name = task.Name.strip() t_in.dStart = start_time t_in.dFinish = start_time + datetime.timedelta(hours=float(task.Estimate)) max_st_end_time = max(max_end_time, t_in.dFinish) # look for resource resource_id = None for r_id, resource in self.schedule.resources.items(): if resource == task.Owner.Name: resource_id = r_id break if not resource_id: resource_id = len(self.schedule.resources) + 1 self.schedule.resources[resource_id] = str(task.Owner.Name) t_in.resource = resource_id t.tasks.append(t_in) print '' t.dFinish = max_st_end_time max_end_time = max(max_end_time, t.dFinish) self.schedule.tasks.append(t) self.schedule.dFinish = max_end_time return self.schedule
def _prepare_inject_value(self): self.schedule = models.Schedule() self.task = models.Task(schedule=self.schedule)