def test_get_info_for_broken_input(self): # check for non-JSON task_input, but then just ignore it instructor_task = self._create_success_entry() instructor_task.task_input = "{ bad" succeeded, message = get_task_completion_info(instructor_task) self.assertFalse(succeeded) self.assertEquals(message, "Status: rescored 2 of 3 (out of 5)")
def test_get_info_for_broken_output(self): # check for non-JSON task_output instructor_task = self._create_success_entry() instructor_task.task_output = "{ bad" succeeded, message = get_task_completion_info(instructor_task) self.assertFalse(succeeded) self.assertEquals(message, "No parsable status information available")
def test_get_info_for_empty_output(self): # check for JSON task_output with missing keys instructor_task = self._create_success_entry() instructor_task.task_output = "{}" succeeded, message = get_task_completion_info(instructor_task) self.assertFalse(succeeded) self.assertEquals(message, "No progress status information available")
def test_get_info_for_missing_output(self): # check for missing task_output instructor_task = self._create_success_entry() instructor_task.task_output = None succeeded, message = get_task_completion_info(instructor_task) self.assertFalse(succeeded) self.assertEquals(message, "No status information available")
def extract_task_features(task): """ Convert task to dict for json rendering. Expects tasks have the following features: * task_type (str, type of task) * task_input (dict, input(s) to the task) * task_id (str, celery id of the task) * requester (str, username who submitted the task) * task_state (str, state of task eg PROGRESS, COMPLETED) * created (datetime, when the task was completed) * task_output (optional) """ # Pull out information from the task features = [ 'task_type', 'task_input', 'task_id', 'requester', 'task_state' ] task_feature_dict = { feature: str(getattr(task, feature)) for feature in features } # Some information (created, duration, status, task message) require additional formatting task_feature_dict['created'] = task.created.isoformat() # Get duration info, if known duration_sec = 'unknown' if hasattr(task, 'task_output') and task.task_output is not None: try: task_output = json.loads(task.task_output) except ValueError: log.error( "Could not parse task output as valid json; task output: %s", task.task_output) else: if 'duration_ms' in task_output: duration_sec = int(task_output['duration_ms'] / 1000.0) task_feature_dict['duration_sec'] = duration_sec # Get progress status message & success information success, task_message = get_task_completion_info(task) status = _("Complete") if success else _("Incomplete") task_feature_dict['status'] = status task_feature_dict['task_message'] = task_message return task_feature_dict
def extract_task_features(task): """ Convert task to dict for json rendering. Expects tasks have the following features: * task_type (str, type of task) * task_input (dict, input(s) to the task) * task_id (str, celery id of the task) * requester (str, username who submitted the task) * task_state (str, state of task eg PROGRESS, COMPLETED) * created (datetime, when the task was completed) * task_output (optional) """ # Pull out information from the task features = ['task_type', 'task_input', 'task_id', 'requester', 'task_state'] task_feature_dict = {feature: str(getattr(task, feature)) for feature in features} # Some information (created, duration, status, task message) require additional formatting task_feature_dict['created'] = task.created.isoformat() # Get duration info, if known duration_sec = 'unknown' if hasattr(task, 'task_output') and task.task_output is not None: try: task_output = json.loads(task.task_output) except ValueError: log.error("Could not parse task output as valid json; task output: %s", task.task_output) else: if 'duration_ms' in task_output: duration_sec = int(task_output['duration_ms'] / 1000.0) task_feature_dict['duration_sec'] = duration_sec # Get progress status message & success information success, task_message = get_task_completion_info(task) status = _("Complete") if success else _("Incomplete") task_feature_dict['status'] = status task_feature_dict['task_message'] = task_message return task_feature_dict
def get_background_task_table(course_key, problem_url=None, student=None, task_type=None): """ Construct the "datatable" structure to represent background task history. Filters the background task history to the specified course and problem. If a student is provided, filters to only those tasks for which that student was specified. Returns a tuple of (msg, datatable), where the msg is a possible error message, and the datatable is the datatable to be used for display. """ history_entries = get_instructor_task_history(course_key, problem_url, student, task_type) datatable = {} msg = "" # first check to see if there is any history at all # (note that we don't have to check that the arguments are valid; it # just won't find any entries.) if (history_entries.count()) == 0: if problem_url is None: msg += '<font color="red">Failed to find any background tasks for course "{course}".</font>'.format( course=course_key.to_deprecated_string() ) elif student is not None: template = '<font color="red">' + _('Failed to find any background tasks for course "{course}", module "{problem}" and student "{student}".') + '</font>' msg += template.format(course=course_key.to_deprecated_string(), problem=problem_url, student=student.username) else: msg += '<font color="red">' + _('Failed to find any background tasks for course "{course}" and module "{problem}".').format( course=course_key.to_deprecated_string(), problem=problem_url ) + '</font>' else: datatable['header'] = ["Task Type", "Task Id", "Requester", "Submitted", "Duration (sec)", "Task State", "Task Status", "Task Output"] datatable['data'] = [] for instructor_task in history_entries: # get duration info, if known: duration_sec = 'unknown' if hasattr(instructor_task, 'task_output') and instructor_task.task_output is not None: task_output = json.loads(instructor_task.task_output) if 'duration_ms' in task_output: duration_sec = int(task_output['duration_ms'] / 1000.0) # get progress status message: success, task_message = get_task_completion_info(instructor_task) status = "Complete" if success else "Incomplete" # generate row for this task: row = [ str(instructor_task.task_type), str(instructor_task.task_id), str(instructor_task.requester), instructor_task.created.isoformat(' '), duration_sec, str(instructor_task.task_state), status, task_message ] datatable['data'].append(row) if problem_url is None: datatable['title'] = "{course_id}".format(course_id=course_key.to_deprecated_string()) elif student is not None: datatable['title'] = "{course_id} > {location} > {student}".format( course_id=course_key.to_deprecated_string(), location=problem_url, student=student.username ) else: datatable['title'] = "{course_id} > {location}".format( course_id=course_key.to_deprecated_string(), location=problem_url ) return msg, datatable
def test_get_info_for_queuing_task(self): # get status for a task that is still running: instructor_task = self._create_entry() succeeded, message = get_task_completion_info(instructor_task) self.assertFalse(succeeded) self.assertEquals(message, "No status information available")