def handle(self, *args, **options): """ Run the command. """ if not args: raise CommandError("Course ID must be specified to fetch data") course_id = args[0] if options['file_name']: file_name = options['file_name'] else: file_name = ("%s-ora2.csv" % course_id).replace("/", "-") if options['output_dir']: csv_file = open(os.path.join(options['output_dir'], file_name), 'wb') else: csv_file = self.stdout writer = csv.writer(csv_file, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) header, rows = OraAggregateData.collect_ora2_data(course_id) writer.writerow(header) for row in rows: writer.writerow(_encode_row(row))
def handle(self, *args, **options): """ Run the command. """ if not options['course_id']: raise CommandError("Course ID must be specified to fetch data") course_id = options['course_id'] if options['file_name']: file_name = options['file_name'] else: file_name = ("%s-ora2.csv" % course_id).replace("/", "-") if options['output_dir']: csv_file = open(os.path.join(options['output_dir'], file_name), 'wb') else: csv_file = self.stdout writer = csv.writer(csv_file, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) header, rows = OraAggregateData.collect_ora2_data(course_id) writer.writerow(header) for row in rows: writer.writerow(_encode_row(row))
def test_collect_ora2_data_with_special_characters(self, answer): """ Scenario: Verify the data collection for ORA2 works with special or non-ascii characters. Given the submission object Then update its answer with a non-ascii value And the submission is saved When the ORA2 data for the submissions is obtained Then the data's answer will be same as json dumped answer """ submission = sub_api._get_submission_model(self.submission['uuid']) # pylint: disable=protected-access submission.answer = answer submission.save() _, rows = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(json.dumps(answer, ensure_ascii=False), rows[1][4])
def test_collect_ora2_data_with_special_characters(self, answer): """ Scenario: Verify the data collection for ORA2 works with special or non-ascii characters. Given the submission object Then update its answer with a non-ascii value And the submission is saved When the ORA2 data for the submissions is obtained Then the data's answer will be same as json dumped answer """ submission = sub_api._get_submission_model(self.submission['uuid']) # pylint: disable=protected-access submission.answer = answer submission.save() with patch( 'openassessment.data.OraAggregateData._map_anonymized_ids_to_usernames' ) as map_mock: map_mock.return_value = USERNAME_MAPPING _, rows = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(json.dumps(answer, ensure_ascii=False), rows[1][7])
def upload_ora2_data( _xmodule_instance_args, _entry_id, course_id, _task_input, action_name ): """ Collect ora2 responses and upload them to S3 as a CSV """ start_date = datetime.now(UTC) start_time = time() num_attempted = 1 num_total = 1 fmt = u'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}' task_info_string = fmt.format( task_id=_xmodule_instance_args.get('task_id') if _xmodule_instance_args is not None else None, entry_id=_entry_id, course_id=course_id, task_input=_task_input ) TASK_LOG.info(u'%s, Task type: %s, Starting task execution', task_info_string, action_name) task_progress = TaskProgress(action_name, num_total, start_time) task_progress.attempted = num_attempted curr_step = {'step': "Collecting responses"} TASK_LOG.info( u'%s, Task type: %s, Current step: %s for all submissions', task_info_string, action_name, curr_step, ) task_progress.update_task_state(extra_meta=curr_step) try: header, datarows = OraAggregateData.collect_ora2_data(course_id) rows = [header] + [row for row in datarows] # Update progress to failed regardless of error type except Exception: # pylint: disable=broad-except TASK_LOG.exception('Failed to get ORA data.') task_progress.failed = 1 curr_step = {'step': "Error while collecting data"} task_progress.update_task_state(extra_meta=curr_step) return UPDATE_STATUS_FAILED task_progress.succeeded = 1 curr_step = {'step': "Uploading CSV"} TASK_LOG.info( u'%s, Task type: %s, Current step: %s', task_info_string, action_name, curr_step, ) task_progress.update_task_state(extra_meta=curr_step) upload_csv_to_report_store(rows, 'ORA_data', course_id, start_date) curr_step = {'step': 'Finalizing ORA data report'} task_progress.update_task_state(extra_meta=curr_step) TASK_LOG.info(u'%s, Task type: %s, Upload complete.', task_info_string, action_name) return UPDATE_STATUS_SUCCEEDED
def test_collect_ora2_data(self): headers, data = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(headers, [ 'Submission ID', 'Item ID', 'Anonymized Student ID', 'Date/Time Response Submitted', 'Response', 'Assessment Details', 'Assessment Scores', 'Date/Time Final Score Given', 'Final Score Points Earned', 'Final Score Points Possible', 'Feedback Statements Selected', 'Feedback on Peer Assessments' ]) self.assertEqual(data[0], [ self.scorer_submission['uuid'], self.scorer_submission['student_item'], SCORER_ID, self.scorer_submission['submitted_at'], self.scorer_submission['answer'], u'', u'', u'', u'', u'', u'', u'', ]) self.assertEqual(data[1], [ self.submission['uuid'], self.submission['student_item'], STUDENT_ID, self.submission['submitted_at'], self.submission['answer'], u"Assessment #{id}\n-- scored_at: {scored_at}\n-- type: PE\n".format( id=self.assessment['id'], scored_at=self.assessment['scored_at'], ) + u"-- scorer_id: {scorer}\n-- overall_feedback: {feedback}\n".format( scorer=self.assessment['scorer_id'], feedback=self.assessment['feedback'] ), u"Assessment #{id}\n-- {label}: {option_label} ({points})\n".format( id=self.assessment['id'], label=self.assessment['parts'][1]['criterion']['label'], option_label=self.assessment['parts'][1]['criterion']['options'][0]['label'], points=self.assessment['parts'][1]['criterion']['options'][0]['points'], ) + u"-- {label}: {option_label} ({points})\n-- feedback: {feedback}\n".format( label=self.assessment['parts'][0]['criterion']['label'], option_label=self.assessment['parts'][0]['criterion']['options'][1]['label'], points=self.assessment['parts'][0]['criterion']['options'][1]['points'], feedback=self.assessment['parts'][0]['feedback'], ), self.score['created_at'], self.score['points_earned'], self.score['points_possible'], FEEDBACK_OPTIONS['options'][0] + '\n' + FEEDBACK_OPTIONS['options'][1]+'\n', FEEDBACK_TEXT, ])
def test_collect_ora2_data_when_usernames_disabled(self): """ Tests that ``OraAggregateData.collect_ora2_data`` generated report without usernames when `ENABLE_ORA_USERNAMES_ON_DATA_EXPORT` settings toggle equals ``False``. """ with patch.dict('django.conf.settings.FEATURES', {'ENABLE_ORA_USERNAMES_ON_DATA_EXPORT': False}): headers, data = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(headers, [ 'Submission ID', 'Location', 'Problem Name', 'Item ID', 'Anonymized Student ID', 'Date/Time Response Submitted', 'Response', 'Assessment Details', 'Assessment Scores', 'Date/Time Final Score Given', 'Final Score Points Earned', 'Final Score Points Possible', 'Feedback Statements Selected', 'Feedback on Peer Assessments' ]) self.assertEqual(data[0], [ self.scorer_submission['uuid'], ITEM_ID, ITEM_DISPLAY_NAME, self.scorer_submission['student_item'], SCORER_ID, self.scorer_submission['submitted_at'], json.dumps(self.scorer_submission['answer']), u'', u'', u'', u'', u'', u'', u'', ]) self.assertEqual(data[1], [ self.submission['uuid'], ITEM_ID, ITEM_DISPLAY_NAME, self.submission['student_item'], STUDENT_ID, self.submission['submitted_at'], json.dumps(self.submission['answer']), u"Assessment #{id}\n-- scored_at: {scored_at}\n-- type: PE\n". format( id=self.assessment['id'], scored_at=self.assessment['scored_at'], ) + u"-- scorer_id: {scorer_id}\n-- overall_feedback: {feedback}\n" .format(scorer_id=self.assessment['scorer_id'], feedback=self.assessment['feedback']), u"Assessment #{id}\n-- {label}: {option_label} ({points})\n". format( id=self.assessment['id'], label=self.assessment['parts'][0]['criterion']['label'], option_label=self.assessment['parts'][0]['criterion'] ['options'][0]['label'], points=self.assessment['parts'][0]['criterion']['options'][0] ['points'], ) + u"-- {label}: {option_label} ({points})\n-- feedback: {feedback}\n" .format( label=self.assessment['parts'][1]['criterion']['label'], option_label=self.assessment['parts'][1]['criterion'] ['options'][1]['label'], points=self.assessment['parts'][1]['criterion']['options'][1] ['points'], feedback=self.assessment['parts'][1]['feedback'], ), self.score['created_at'], self.score['points_earned'], self.score['points_possible'], FEEDBACK_OPTIONS['options'][0] + '\n' + FEEDBACK_OPTIONS['options'][1] + '\n', FEEDBACK_TEXT, ])
def test_collect_ora2_data(self): with patch( 'openassessment.data.OraAggregateData._map_anonymized_ids_to_usernames' ) as map_mock: map_mock.return_value = USERNAME_MAPPING headers, data = OraAggregateData.collect_ora2_data(COURSE_ID) self.assertEqual(headers, [ 'Submission ID', 'Location', 'Problem Name', 'Item ID', 'Username', 'Anonymized Student ID', 'Date/Time Response Submitted', 'Response', 'Assessment Details', 'Assessment Scores', 'Date/Time Final Score Given', 'Final Score Points Earned', 'Final Score Points Possible', 'Feedback Statements Selected', 'Feedback on Peer Assessments' ]) self.assertEqual(data[0], [ self.scorer_submission['uuid'], ITEM_ID, ITEM_DISPLAY_NAME, self.scorer_submission['student_item'], SCORER_USERNAME, SCORER_ID, self.scorer_submission['submitted_at'], json.dumps(self.scorer_submission['answer']), u'', u'', u'', u'', u'', u'', u'', ]) self.assertEqual(data[1], [ self.submission['uuid'], ITEM_ID, ITEM_DISPLAY_NAME, self.submission['student_item'], STUDENT_USERNAME, STUDENT_ID, self.submission['submitted_at'], json.dumps(self.submission['answer']), u"Assessment #{id}\n-- scored_at: {scored_at}\n-- type: PE\n". format( id=self.assessment['id'], scored_at=self.assessment['scored_at'], ) + u"-- scorer_username: {scorer_username}\n".format( scorer_username=USERNAME_MAPPING[self.assessment['scorer_id']]) + u"-- scorer_id: {scorer_id}\n-- overall_feedback: {feedback}\n". format(scorer_id=self.assessment['scorer_id'], feedback=self.assessment['feedback']), u"Assessment #{id}\n-- {label}: {option_label} ({points})\n". format( id=self.assessment['id'], label=self.assessment['parts'][0]['criterion']['label'], option_label=self.assessment['parts'][0]['criterion'] ['options'][0]['label'], points=self.assessment['parts'][0]['criterion']['options'][0] ['points'], ) + u"-- {label}: {option_label} ({points})\n-- feedback: {feedback}\n" .format( label=self.assessment['parts'][1]['criterion']['label'], option_label=self.assessment['parts'][1]['criterion'] ['options'][1]['label'], points=self.assessment['parts'][1]['criterion']['options'][1] ['points'], feedback=self.assessment['parts'][1]['feedback'], ), self.score['created_at'], self.score['points_earned'], self.score['points_possible'], FEEDBACK_OPTIONS['options'][0] + '\n' + FEEDBACK_OPTIONS['options'][1] + '\n', FEEDBACK_TEXT, ])