def render_leaderboard_complete(self, student_item_dict): """ Render the leaderboard complete state. Args: student_item_dict (dict): The student item Returns: template_path (string), tuple of context (dict) """ # Retrieve top scores from the submissions API # Since this uses the read-replica and caches the results, # there will be some delay in the request latency. scores = sub_api.get_top_submissions(student_item_dict['course_id'], student_item_dict['item_id'], student_item_dict['item_type'], self.leaderboard_show) for score in scores: score['files'] = [] if 'file_keys' in score['content']: for key in score['content']['file_keys']: url = '' try: url = file_upload_api.get_download_url(key) except FileUploadError: pass if url: score['files'].append(url) elif 'file_key' in score['content']: score['files'].append( file_upload_api.get_download_url( score['content']['file_key'])) if 'text' in score['content'] or 'parts' in score['content']: submission = {'answer': score.pop('content')} score['submission'] = create_submission_dict( submission, self.prompts) elif isinstance(score['content'], basestring): pass # Currently, we do not handle non-text submissions. else: score['submission'] = "" score.pop('content', None) context = { 'topscores': scores, 'allow_latex': self.allow_latex, 'file_upload_type': self.file_upload_type, 'xblock_id': self.get_xblock_id() } return 'openassessmentblock/leaderboard/oa_leaderboard_show.html', context
def test_non_text_submission(self, xblock): # Create a mock bucket conn = boto.connect_s3() conn.create_bucket('mybucket') # Create a non-text submission (the submission dict doesn't contain 'text') api.get_download_url('s3key') self._create_submissions_and_scores(xblock, [('s3key', 1)], submission_key='file_key') # Expect that we default to an empty string for content self._assert_scores(xblock, [ {'score': 1, 'files': [], 'submission': ''} ])
def test_image_and_text_submission_multiple_files(self, xblock): """ Tests that leaderboard works as expected when multiple files are uploaded """ file_keys = ['foo', 'bar'] file_descriptions = ['{}-description'.format(file_key) for file_key in file_keys] file_names = ['{}-file_name'.format(file_key) for file_key in file_keys] conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') for file_key in file_keys: key = Key(bucket, 'submissions_attachments/{}'.format(file_key)) key.set_contents_from_string("How d'ya do?") files_url_and_description = [ (api.get_download_url(file_key), file_descriptions[idx], file_names[idx], False) for idx, file_key in enumerate(file_keys) ] # Create a image and text submission submission = prepare_submission_for_serialization(('test answer 1 part 1', 'test answer 1 part 2')) submission[u'file_keys'] = file_keys submission[u'files_descriptions'] = file_descriptions submission[u'files_name'] = file_names self._create_submissions_and_scores(xblock, [ (submission, 1) ]) # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [ {'score': 1, 'files': files_url_and_description, 'submission': create_submission_dict( {'answer': submission}, xblock.prompts )} ])
def test_remove_all_uploaded_files(self, xblock): """ Test remove all user files """ conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket) key.key = "submissions_attachments/test_student/test_course/" + xblock.scope_ids.usage_id key.set_contents_from_string("How d'ya do?") xblock.xmodule_runtime = Mock( course_id='test_course', anonymous_student_id='test_student', ) download_url = api.get_download_url("test_student/test_course/" + xblock.scope_ids.usage_id) resp = self.request(xblock, 'download_url', json.dumps(dict()), response_format='json') self.assertTrue(resp['success']) self.assertEqual(download_url, resp['url']) resp = self.request(xblock, 'remove_all_uploaded_files', json.dumps(dict()), response_format='json') self.assertTrue(resp['success']) self.assertEqual(resp['removed_num'], 1) resp = self.request(xblock, 'download_url', json.dumps(dict()), response_format='json') self.assertTrue(resp['success']) self.assertEqual(u'', resp['url'])
def _download_file_by_key(cls, key): download_url = urljoin(settings.LMS_ROOT_URL, get_download_url(key)) response = requests.get(download_url) response.raise_for_status() return response.content
def test_image_and_text_submission_multiple_files(self, xblock): """ Tests that leaderboard works as expected when multiple files are uploaded """ file_keys = ['foo', 'bar'] file_descriptions = ['{}-description'.format(file_key) for file_key in file_keys] conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') for file_key in file_keys: key = Key(bucket, 'submissions_attachments/{}'.format(file_key)) key.set_contents_from_string("How d'ya do?") files_url_and_description = [ (api.get_download_url(file_key), file_descriptions[idx]) for idx, file_key in enumerate(file_keys) ] # Create a image and text submission submission = prepare_submission_for_serialization(('test answer 1 part 1', 'test answer 1 part 2')) submission[u'file_keys'] = file_keys submission[u'files_descriptions'] = file_descriptions self._create_submissions_and_scores(xblock, [ (submission, 1) ]) self.maxDiff = None # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [ {'score': 1, 'files': files_url_and_description, 'submission': create_submission_dict( {'answer': submission}, xblock.prompts )} ])
def test_image_and_text_submission(self, xblock): """ Tests that text and image submission works as expected """ # Create a file and get the download URL conn = boto3.client("s3") conn.create_bucket(Bucket='mybucket') conn.put_object( Bucket="mybucket", Key="submissions_attachments/foo", Body=b"How d'ya do?", ) file_download_url = [{ 'download_url': api.get_download_url('foo'), 'description': '', 'name': '', 'show_delete_button': False }] # Create a image and text submission submission = prepare_submission_for_serialization( ('test answer 1 part 1', 'test answer 1 part 2')) submission[u'file_key'] = 'foo' self._create_submissions_and_scores(xblock, [(submission, 1)]) # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [{ 'score': 1, 'files': file_download_url, 'submission': create_submission_dict({'answer': submission}, xblock.prompts) }])
def test_image_and_text_submission(self, xblock): """ Tests that text and image submission works as expected """ # Create a file and get the download URL conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket, 'submissions_attachments/foo') key.set_contents_from_string("How d'ya do?") file_download_url = [(api.get_download_url('foo'), '')] # Create a image and text submission submission = prepare_submission_for_serialization( ('test answer 1 part 1', 'test answer 1 part 2')) submission[u'file_key'] = 'foo' self._create_submissions_and_scores(xblock, [(submission, 1)]) self.maxDiff = None # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [{ 'score': 1, 'files': file_download_url, 'submission': create_submission_dict({'answer': submission}, xblock.prompts) }])
def render_leaderboard_complete(self, student_item_dict): """ Render the leaderboard complete state. Args: student_item_dict (dict): The student item Returns: template_path (string), tuple of context (dict) """ # Retrieve top scores from the submissions API # Since this uses the read-replica and caches the results, # there will be some delay in the request latency. scores = sub_api.get_top_submissions(student_item_dict['course_id'], student_item_dict['item_id'], student_item_dict['item_type'], self.leaderboard_show) for score in scores: if 'file_key' in score['content']: score['file'] = file_upload_api.get_download_url( score['content']['file_key']) if 'text' in score['content']: score['content'] = score['content']['text'] elif isinstance(score['content'], basestring): pass # Currently, we do not handle non-text submissions. else: score['content'] = "" context = {'topscores': scores} return ('openassessmentblock/leaderboard/oa_leaderboard_show.html', context)
def render_leaderboard_complete(self, student_item_dict): """ Render the leaderboard complete state. Args: student_item_dict (dict): The student item Returns: template_path (string), tuple of context (dict) """ # Retrieve top scores from the submissions API # Since this uses the read-replica and caches the results, # there will be some delay in the request latency. scores = sub_api.get_top_submissions( student_item_dict['course_id'], student_item_dict['item_id'], student_item_dict['item_type'], self.leaderboard_show ) for score in scores: if 'file_key' in score['content']: score['file'] = file_upload_api.get_download_url(score['content']['file_key']) if 'text' in score['content']: score['content'] = score['content']['text'] elif isinstance(score['content'], basestring): pass # Currently, we do not handle non-text submissions. else: score['content'] = "" context = { 'topscores': scores, 'allow_latex': self.allow_latex, } return ('openassessmentblock/leaderboard/oa_leaderboard_show.html', context)
def test_image_and_text_submission(self, xblock): """ Tests that text and image submission works as expected """ # Create a file and get the download URL conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket, 'submissions_attachments/foo') key.set_contents_from_string("How d'ya do?") file_download_url = [(api.get_download_url('foo'), '')] # Create a image and text submission submission = prepare_submission_for_serialization(('test answer 1 part 1', 'test answer 1 part 2')) submission[u'file_key'] = 'foo' self._create_submissions_and_scores(xblock, [ (submission, 1) ]) self.maxDiff = None # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [ {'score': 1, 'files': file_download_url, 'submission': create_submission_dict( {'answer': submission}, xblock.prompts )} ])
def test_remove_all_uploaded_files(self, xblock): """ Test remove all user files """ conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket) key.key = "submissions_attachments/test_student/test_course/" + xblock.scope_ids.usage_id key.set_contents_from_string("How d'ya do?") xblock.xmodule_runtime = Mock( course_id='test_course', anonymous_student_id='test_student', ) download_url = api.get_download_url("test_student/test_course/" + xblock.scope_ids.usage_id) resp = self.request(xblock, 'download_url', json.dumps(dict()), response_format='json') self.assertTrue(resp['success']) self.assertTrue(resp['url'].startswith(download_url)) resp = self.request(xblock, 'remove_all_uploaded_files', json.dumps(dict()), response_format='json') self.assertTrue(resp['success']) self.assertEqual(resp['removed_num'], 1) resp = self.request(xblock, 'download_url', json.dumps(dict()), response_format='json') self.assertTrue(resp['success']) self.assertEqual(u'', resp['url'])
def test_get_download_url(self): conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket) key.key = "submissions_attachments/foo" key.set_contents_from_string("How d'ya do?") downloadUrl = api.get_download_url("foo") self.assertIn("https://mybucket.s3.amazonaws.com/submissions_attachments/foo", downloadUrl)
def test_get_download_url(self): conn = boto3.client("s3") conn.create_bucket(Bucket="mybucket") conn.put_object(Bucket="mybucket", Key="submissions_attachments/foo", Body=b"How d'ya do?") downloadUrl = api.get_download_url("foo") self.assertIn("/submissions_attachments/foo", downloadUrl)
def test_get_download_url(self): conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket) key.key = "submissions_attachments/foo" key.set_contents_from_string("How d'ya do?") downloadUrl = api.get_download_url("foo") self.assertIn("/submissions_attachments/foo", downloadUrl)
def create_submission(self, student_item_dict, student_sub_data, files_descriptions=None): # Import is placed here to avoid model import at project startup. from submissions import api # Store the student's response text in a JSON-encodable dict # so that later we can add additional response fields. files_descriptions = files_descriptions if files_descriptions else [] student_sub_dict = prepare_submission_for_serialization( student_sub_data) if self.file_upload_type: student_sub_dict['file_keys'] = [] student_sub_dict['files_descriptions'] = [] for i in range(self.MAX_FILES_COUNT): key_to_save = '' file_description = '' item_key = self._get_student_item_key(i) try: url = file_upload_api.get_download_url(item_key) if url: key_to_save = item_key try: file_description = files_descriptions[i] except IndexError: pass except FileUploadError: logger.exception( u"FileUploadError for student_item: {student_item_dict}" u" and submission data: {student_sub_data} with file" "descriptions {files_descriptions}".format( student_item_dict=student_item_dict, student_sub_data=student_sub_data, files_descriptions=files_descriptions)) if key_to_save: student_sub_dict['file_keys'].append(key_to_save) student_sub_dict['files_descriptions'].append( file_description) else: break submission = api.create_submission(student_item_dict, student_sub_dict) self.create_workflow(submission["uuid"]) self.submission_uuid = submission["uuid"] # Emit analytics event... self.runtime.publish( self, "openassessmentblock.create_submission", { "submission_uuid": submission["uuid"], "attempt_number": submission["attempt_number"], "created_at": submission["created_at"], "submitted_at": submission["submitted_at"], "answer": submission["answer"], }) return submission
def _get_download_url(self): """ Internal function for retrieving the download url. """ try: return file_upload_api.get_download_url(self._get_student_item_key()) except FileUploadError: logger.exception("Error retrieving download URL.") return ''
def _get_url_by_file_key(self, key): """ Return download url for some particular file key. """ url = '' try: if key: url = file_upload_api.get_download_url(key) except FileUploadError: logger.exception("Unable to generate download url for file key {}".format(key)) return url
def test_non_text_submission(self, xblock): # Create a mock bucket conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') # Create a non-text submission (the submission dict doesn't contain 'text') file_download_url = api.get_download_url('s3key') self._create_submissions_and_scores(xblock, [('s3key', 1)], submission_key='file_key') # Expect that we default to an empty string for content self._assert_scores(xblock, [ {'score': 1, 'files': [], 'submission': ''} ])
def _get_download_url(self, file_num=0): """ Internal function for retrieving the download url. """ try: return file_upload_api.get_download_url( self._get_student_item_key(file_num)) except FileUploadError as exc: logger.exception( u"FileUploadError: Download URL retrieval for filenum {num} failed with {error}" .format(error=exc, num=file_num)) return ''
def create_submission(self, student_item_dict, student_sub_data, files_descriptions=None): # Import is placed here to avoid model import at project startup. from submissions import api # Store the student's response text in a JSON-encodable dict # so that later we can add additional response fields. files_descriptions = files_descriptions if files_descriptions else [] student_sub_dict = prepare_submission_for_serialization(student_sub_data) if self.file_upload_type: student_sub_dict['file_keys'] = [] student_sub_dict['files_descriptions'] = [] for i in range(self.MAX_FILES_COUNT): key_to_save = '' file_description = '' item_key = self._get_student_item_key(i) try: url = file_upload_api.get_download_url(item_key) if url: key_to_save = item_key try: file_description = files_descriptions[i] except IndexError: pass except FileUploadError: pass if key_to_save: student_sub_dict['file_keys'].append(key_to_save) student_sub_dict['files_descriptions'].append(file_description) else: break submission = api.create_submission(student_item_dict, student_sub_dict) self.create_workflow(submission["uuid"]) self.submission_uuid = submission["uuid"] # Emit analytics event... self.runtime.publish( self, "openassessmentblock.create_submission", { "submission_uuid": submission["uuid"], "attempt_number": submission["attempt_number"], "created_at": submission["created_at"], "submitted_at": submission["submitted_at"], "answer": submission["answer"], } ) return submission
def _get_url_by_file_key(self, key): """ Return download url for some particular file key. """ url = '' try: if key: url = file_upload_api.get_download_url(key) except FileUploadError as exc: logger.exception( u"FileUploadError: Download url for file key {key} failed with error {error}" .format(key=key, error=exc)) return url
def test_image_and_text_submission(self, xblock): # Create a file and get the download URL conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket) key.key = "submissions_attachments/foo" key.set_contents_from_string("How d'ya do?") downloadUrl = api.get_download_url("foo") # Create a image and text submission self._create_submissions_and_scores(xblock, [({"text": "test answer", "file_key": "foo"}, 1)], submission_key=None) # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [ {"content": "test answer", "score": 1, "file": downloadUrl} ])
def _get_file_download_url(self, file_key): """ Internal function for retrieving the download url at which the file that corresponds to the file_key can be downloaded. Arguments: file_key (string): Corresponding file key. Returns: file_download_url (string) or empty string in case of error. """ try: file_download_url = file_upload_api.get_download_url(file_key) except FileUploadError: file_download_url = '' return file_download_url
def test_image_and_text_submission_multiple_files(self, xblock): """ Tests that leaderboard works as expected when multiple files are uploaded """ file_keys = ['foo', 'bar'] file_descriptions = [ '{}-description'.format(file_key) for file_key in file_keys ] files_names = [ '{}-file_name'.format(file_key) for file_key in file_keys ] conn = boto3.client("s3") conn.create_bucket(Bucket="mybucket") for file_key in file_keys: conn.put_object( Bucket="mybucket", Key="submissions_attachments/{}".format(file_key), Body=b"How d'ya do?", ) files_url_and_description = [{ 'download_url': api.get_download_url(file_key), 'description': file_descriptions[idx], 'name': files_names[idx], 'show_delete_button': False } for idx, file_key in enumerate(file_keys)] # Create a image and text submission submission = prepare_submission_for_serialization( ('test answer 1 part 1', 'test answer 1 part 2')) submission['file_keys'] = file_keys submission['files_descriptions'] = file_descriptions submission['files_names'] = files_names submission['files_sizes'] = [] self._create_submissions_and_scores(xblock, [(submission, 1)]) # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [{ 'score': 1, 'files': files_url_and_description, 'submission': create_submission_dict({'answer': submission}, xblock.prompts) }])
def _get_url_by_file_key(cls, key): """ Return download url for some particular file key. """ url = '' try: if key: url = file_upload_api.get_download_url(key) except FileUploadError as exc: logger.exception( "FileUploadError: Download url for file key %s failed with error %s", key, exc, exc_info=True) return url
def get_all_upload_urls_for_user(self, username_or_email): """ For a particular ORA block, get the download URLs for all the files uploaded and still present. Used for an extreme edge case, where the stored files indices are out of sync with the uploaded files, this is a last resort to get the download URLs of all the files that have been uploaded by a learner in an ORA block(and haven't been deleted from the storage). Starting from 0 index to maximum file upload count possible, this checks if a file exists against every index. If present, add the info, else repeat it for the next indices. Arguments: username_or_email(str): username or email of the learner whose files' information is to be obtained. Returns: List of 3-valued tuples, with first value being file URL and other two values as empty string. The other 2 values have to be appended to work properly in the template. """ file_uploads = [] student_item_dict = self.get_student_item_dict_from_username_or_email(username_or_email) for index in range(self.MAX_FILES_COUNT): file_key = file_upload_api.get_student_file_key(student_item_dict, index) download_url = '' try: download_url = file_upload_api.get_download_url(file_key) except FileUploadError: pass if download_url: logger.info( "Download URL exists for key %s in block %s for user %s", file_key, username_or_email, str(self.location) ) file_uploads.append( file_upload_api.FileDescriptor( download_url=download_url, description='', name='', show_delete_button=False )._asdict() ) else: continue return file_uploads
def test_download_url(self, xblock): """ Test generate correct download URL with existing file. should create a file and get the download URL """ conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket) key.key = "submissions_attachments/test_student/test_course/" + xblock.scope_ids.usage_id key.set_contents_from_string("How d'ya do?") download_url = api.get_download_url("test_student/test_course/" + xblock.scope_ids.usage_id) xblock.xmodule_runtime = Mock( course_id='test_course', anonymous_student_id='test_student', ) resp = self.request(xblock, 'download_url', json.dumps(dict()), response_format='json') self.assertTrue(resp['success']) self.assertEqual(download_url, resp['url'])
def _get_file_download_url(self, file_key): """ Internal function for retrieving the download url at which the file that corresponds to the file_key can be downloaded. Arguments: file_key (string): Corresponding file key. Returns: file_download_url (string) or empty string in case of error. """ try: file_download_url = file_upload_api.get_download_url(file_key) except FileUploadError as exc: logger.exception( u'FileUploadError: URL retrieval failed for key {file_key} with error {error}' .format(file_key=file_key, error=exc)) file_download_url = '' return file_download_url
def test_image_and_text_submission(self, xblock): # Create a file and get the download URL conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket) key.key = "submissions_attachments/foo" key.set_contents_from_string("How d'ya do?") downloadUrl = api.get_download_url("foo") # Create a image and text submission self._create_submissions_and_scores(xblock, [({ "text": "test answer", "file_key": "foo" }, 1)], submission_key=None) # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [{ "content": "test answer", "score": 1, "file": downloadUrl }])
def test_image_and_text_submission(self, xblock): # Create a file and get the download URL conn = boto.connect_s3() bucket = conn.create_bucket('mybucket') key = Key(bucket) key.key = "submissions_attachments/foo" key.set_contents_from_string("How d'ya do?") downloadUrl = api.get_download_url("foo") # Create a image and text submission submission = prepare_submission_for_serialization(("test answer 1 part 1", "test answer 1 part 2")) submission[u"file_key"] = "foo" self._create_submissions_and_scores(xblock, [ (submission, 1) ]) self.maxDiff = None # Expect that we retrieve both the text and the download URL for the file self._assert_scores(xblock, [ {"file": downloadUrl, "score": 1, "submission": create_submission_dict( {"answer": submission}, xblock.prompts )} ])
def get_download_url_from_submission(self, submission): """ Returns a download URL for retrieving content within a submission. Args: submission (dict): Dictionary containing an answer and a file_key. The file_key is used to try and retrieve a download url with related content Returns: A URL to related content. If there is no content related to this key, or if there is no key for the submission, returns an empty string. """ url = "" key = submission['answer'].get('file_key', '') try: if key: url = file_upload_api.get_download_url(key) except FileUploadError: logger.exception("Unable to generate download url for file key {}".format(key)) return url
def render_leaderboard_complete(self, student_item_dict): """ Render the leaderboard complete state. Args: student_item_dict (dict): The student item Returns: template_path (string), tuple of context (dict) """ # Retrieve top scores from the submissions API # Since this uses the read-replica and caches the results, # there will be some delay in the request latency. scores = sub_api.get_top_submissions( student_item_dict["course_id"], student_item_dict["item_id"], student_item_dict["item_type"], self.leaderboard_show, ) for score in scores: if "file_key" in score["content"]: score["file"] = file_upload_api.get_download_url(score["content"]["file_key"]) if "text" in score["content"] or "parts" in score["content"]: submission = {"answer": score.pop("content")} score["submission"] = create_submission_dict(submission, self.prompts) elif isinstance(score["content"], basestring): pass # Currently, we do not handle non-text submissions. else: score["submission"] = "" score.pop("content", None) context = {"topscores": scores, "allow_latex": self.allow_latex} return "openassessmentblock/leaderboard/oa_leaderboard_show.html", context
def get_student_info_path_and_context(self, student_username): """ Get the proper path and context for rendering the the student info section of the staff debug panel. Args: student_username (unicode): The username of the student to report. """ submission_uuid = None submission = None assessment_steps = self.assessment_steps anonymous_user_id = None submissions = None student_item = None if student_username: anonymous_user_id = self.get_anonymous_user_id(student_username, self.course_id) student_item = self.get_student_item_dict(anonymous_user_id=anonymous_user_id) if anonymous_user_id: # If there is a submission available for the requested student, present # it. If not, there will be no other information to collect. submissions = submission_api.get_submissions(student_item, 1) if submissions: submission_uuid = submissions[0]['uuid'] submission = submissions[0] if 'file_key' in submission.get('answer', {}): file_key = submission['answer']['file_key'] try: submission['image_url'] = file_api.get_download_url(file_key) except file_api.FileUploadError: # Log the error, but do not prevent the rest of the student info # from being displayed. msg = ( u"Could not retrieve image URL for staff debug page. " u"The student username is '{student_username}', and the file key is {file_key}" ).format(student_username=student_username, file_key=file_key) logger.exception(msg) example_based_assessment = None self_assessment = None peer_assessments = [] submitted_assessments = [] if "peer-assessment" in assessment_steps: peer_assessments = peer_api.get_assessments(submission_uuid) submitted_assessments = peer_api.get_submitted_assessments(submission_uuid, scored_only=False) if "self-assessment" in assessment_steps: self_assessment = self_api.get_assessment(submission_uuid) if "example-based-assessment" in assessment_steps: example_based_assessment = ai_api.get_latest_assessment(submission_uuid) workflow_cancellation = workflow_api.get_assessment_workflow_cancellation(submission_uuid) if workflow_cancellation: workflow_cancellation['cancelled_by'] = self.get_username(workflow_cancellation['cancelled_by_id']) context = { 'submission': submission, 'workflow_cancellation': workflow_cancellation, 'peer_assessments': peer_assessments, 'submitted_assessments': submitted_assessments, 'self_assessment': self_assessment, 'example_based_assessment': example_based_assessment, 'rubric_criteria': copy.deepcopy(self.rubric_criteria_with_labels), } if peer_assessments or self_assessment or example_based_assessment: max_scores = peer_api.get_rubric_max_scores(submission_uuid) for criterion in context["rubric_criteria"]: criterion["total_value"] = max_scores[criterion["name"]] path = 'openassessmentblock/staff_debug/student_info.html' return path, context
def test_get_download_url_error(self, mock_s3): with raises(exceptions.FileUploadInternalError): mock_s3.side_effect = Exception("Oh noes") api.get_download_url("foo")
def test_get_download_url_error(self, mock_s3): mock_s3.side_effect = Exception("Oh noes") api.get_download_url("foo")
def get_student_info_path_and_context(self, student_id): """ Get the proper path and context for rendering the the student info section of the staff debug panel. Args: student_id (unicode): The ID of the student to report. """ submission_uuid = None submission = None assessment_steps = self.assessment_steps student_item = self.get_student_item_dict() scores = {} problem_closed = None if student_id: student_item['student_id'] = student_id # If there is a submission available for the requested student, present # it. If not, there will be no other information to collect. submissions = submission_api.get_submissions(student_item, 1) if submissions: submission_uuid = submissions[0]['uuid'] submission = submissions[0] if 'file_key' in submission.get('answer', {}): file_key = submission['answer']['file_key'] try: submission['image_url'] = file_api.get_download_url(file_key) except file_api.FileUploadError: # Log the error, but do not prevent the rest of the student info # from being displayed. msg = ( u"Could not retrieve image URL for staff debug page. " u"The student ID is '{student_id}', and the file key is {file_key}" ).format(student_id=student_id, file_key=file_key) logger.exception(msg) example_based_assessment = None self_assessment = None peer_assessments = [] submitted_assessments = [] if "peer-assessment" in assessment_steps: peer_assessments = peer_api.get_assessments(submission_uuid) submitted_assessments = peer_api.get_submitted_assessments(submission_uuid, scored_only=False) # Get the data we need for instructor override of the student's score rubric_dict = create_rubric_dict(self.prompt, self.rubric_criteria_with_labels) scores = peer_api.get_data_for_override_score( submission_uuid, student_item, rubric_dict, ) problem_closed, dummy0, dummy1, dummy2 = self.is_closed(step='peer-assessment', course_staff=False) if "self-assessment" in assessment_steps: self_assessment = self_api.get_assessment(submission_uuid) if "example-based-assessment" in assessment_steps: example_based_assessment = ai_api.get_latest_assessment(submission_uuid) context = { 'submission': submission, 'peer_assessments': peer_assessments, 'submitted_assessments': submitted_assessments, 'self_assessment': self_assessment, 'example_based_assessment': example_based_assessment, 'rubric_criteria': copy.deepcopy(self.rubric_criteria_with_labels), 'scores': scores, 'problem_closed': problem_closed, } if peer_assessments or self_assessment or example_based_assessment: max_scores = peer_api.get_rubric_max_scores(submission_uuid) for criterion in context["rubric_criteria"]: criterion["total_value"] = max_scores[criterion["name"]] path = 'openassessmentblock/staff_debug/student_info.html' return path, context
def get_file_url(answer): if answer.get('file_key'): return ora_file_upload_api.get_download_url(answer['file_key']) return None
def get_student_info_path_and_context(self, student_id): """ Get the proper path and context for rendering the the student info section of the staff debug panel. Args: student_id (unicode): The ID of the student to report. """ submission_uuid = None submission = None assessment_steps = self.assessment_steps if student_id: student_item = self.get_student_item_dict() student_item['student_id'] = student_id # If there is a submission available for the requested student, present # it. If not, there will be no other information to collect. submissions = submission_api.get_submissions(student_item, 1) if submissions: submission_uuid = submissions[0]['uuid'] submission = submissions[0] if 'file_key' in submission.get('answer', {}): file_key = submission['answer']['file_key'] try: submission['image_url'] = file_api.get_download_url( file_key) except file_api.FileUploadError: # Log the error, but do not prevent the rest of the student info # from being displayed. msg = ( u"Could not retrieve image URL for staff debug page. " u"The student ID is '{student_id}', and the file key is {file_key}" ).format(student_id=student_id, file_key=file_key) logger.exception(msg) example_based_assessment = None self_assessment = None peer_assessments = [] submitted_assessments = [] if "peer-assessment" in assessment_steps: peer_assessments = peer_api.get_assessments(submission_uuid) submitted_assessments = peer_api.get_submitted_assessments( submission_uuid, scored_only=False) if "self-assessment" in assessment_steps: self_assessment = self_api.get_assessment(submission_uuid) if "example-based-assessment" in assessment_steps: example_based_assessment = ai_api.get_latest_assessment( submission_uuid) context = { 'submission': submission, 'peer_assessments': peer_assessments, 'submitted_assessments': submitted_assessments, 'self_assessment': self_assessment, 'example_based_assessment': example_based_assessment, 'rubric_criteria': copy.deepcopy(self.rubric_criteria_with_labels), } if peer_assessments or self_assessment or example_based_assessment: max_scores = peer_api.get_rubric_max_scores(submission_uuid) for criterion in context["rubric_criteria"]: criterion["total_value"] = max_scores[criterion["name"]] path = 'openassessmentblock/staff_debug/student_info.html' return path, context