Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: mfe file actions with legacy refactor #2059

Merged
merged 20 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions openassessment/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from submissions import api as sub_api
from submissions.errors import SubmissionNotFoundError
from openassessment.fileupload.exceptions import FileUploadInternalError
from openassessment.runtime_imports.classes import import_block_structure_transformers, import_external_id
from openassessment.runtime_imports.functions import get_course_blocks, modulestore
from openassessment.assessment.api import peer as peer_api
Expand Down Expand Up @@ -1315,11 +1316,12 @@ class SubmissionFileUpload:

DEFAULT_DESCRIPTION = _("No description provided.")

def __init__(self, key, name=None, description=None, size=0):
def __init__(self, key, name=None, description=None, size=0, url=None):
self.key = key
self.name = name if name is not None else SubmissionFileUpload.generate_name_from_key(key)
self.description = description if description is not None else SubmissionFileUpload.DEFAULT_DESCRIPTION
self.size = size
self.url = url

@staticmethod
def generate_name_from_key(key):
Expand Down Expand Up @@ -1367,7 +1369,7 @@ def get_text_responses(self):
"""
raise NotImplementedError()

def get_file_uploads(self, missing_blank=False):
def get_file_uploads(self, missing_blank=False, generate_urls=False):
"""
Get the list of FileUploads for this submission
"""
Expand All @@ -1393,7 +1395,7 @@ def get_text_responses(self):
self.text_responses = [part.get('text') for part in self.raw_answer.get('parts', [])]
return self.text_responses

def get_file_uploads(self, missing_blank=False):
def get_file_uploads(self, missing_blank=False, generate_urls=False):
return []


Expand Down Expand Up @@ -1510,7 +1512,20 @@ def _index_safe_get(self, i, target_list, default=None):
except IndexError:
return default

def get_file_uploads(self, missing_blank=False):
def _safe_get_download_url(self, key):
""" Helper to get a download URL """
try:
return get_download_url(key)
except FileUploadInternalError as exc:
logger.exception(
"FileUploadError: Download url for file key %s failed with error %s",
key,
exc,
exc_info=True
)
return None

def get_file_uploads(self, missing_blank=False, generate_urls=False):
"""
Parse and cache file upload responses from the raw_answer
"""
Expand All @@ -1530,8 +1545,14 @@ def get_file_uploads(self, missing_blank=False):
name = self._index_safe_get(i, file_names, default_missing_value)
description = self._index_safe_get(i, file_descriptions, default_missing_value)
size = self._index_safe_get(i, file_sizes, 0)

file_upload = SubmissionFileUpload(key, name=name, description=description, size=size)
url = None if not generate_urls else self._safe_get_download_url(key)
file_upload = SubmissionFileUpload(
key,
name=name,
description=description,
size=size,
url=url
)
files.append(file_upload)
self.file_uploads = files
return self.file_uploads
2 changes: 1 addition & 1 deletion openassessment/staffgrader/serializers/assessments.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class SubmissionDetailFileSerilaizer(serializers.Serializer):
"""
Serialized info about a single file
"""
download_url = serializers.URLField()
download_url = serializers.URLField(source="url")
description = serializers.CharField()
name = serializers.CharField()
size = serializers.IntegerField()
Expand Down
2 changes: 1 addition & 1 deletion openassessment/staffgrader/staff_grader_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ def get_submission_info(self, submission_uuid, _, suffix=''): # pylint: disable
return {
'files': [
SubmissionDetailFileSerilaizer(file_data).data
for file_data in self.get_download_urls_from_submission(submission)
for file_data in answer.get_file_uploads(generate_urls=True)
],
'text': answer.get_text_responses()
}
Expand Down
9 changes: 4 additions & 5 deletions openassessment/staffgrader/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ def setUp(self):
self.maxDiff = None

@contextmanager
def _mock_get_url_by_file_key(self, xblock):
""" Mock the submission_mixin._get_url_by_file_key method since it relies on the backend. """
with patch.object(xblock.__class__, '_get_url_by_file_key') as mocked_get:
mocked_get.side_effect = lambda file_key: f"www.file_url.com/{file_key}"
yield mocked_get
def _mock_get_download_url(self):
with patch('openassessment.data.get_download_url') as mock_get_url:
mock_get_url.side_effect = lambda file_key: f"www.file_url.com/{file_key}"
yield mock_get_url

@contextmanager
def _mock_get_submission(self, **kwargs):
Expand Down
21 changes: 16 additions & 5 deletions openassessment/staffgrader/tests/test_get_submission_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ def _mock_parse_submission_raw_answer(self, **kwargs):
) as mock_parse:
yield mock_parse

def _mock_get_download_urls_from_submission(self, xblock, **kwargs):
@contextmanager
def _mock_get_download_urls(self, **kwargs):
""" Helper method to mock the get_download_urls_from_submission method """
xblock.get_download_urls_from_submission = Mock(**kwargs)
with patch("openassessment.data.get_download_url", **kwargs) as mock_get_download_url:
yield mock_get_download_url

@scenario('data/simple_self_staff_scenario.xml', user_id='Bob')
def test_get_submission_error(self, xblock):
Expand Down Expand Up @@ -77,6 +79,14 @@ def test_get_submission_info(self, xblock):
"This is my answer for <i>Prompt Two</i>",
"This is my response for <a href='www.edx.org'>Prompt Three</a>"
]
file_uploads = [
{
"url": 'A', "description": 'B', "name": 'C', "size": 100
},
{
"url": '1', "description": '2', "name": '3', "size": 300
},
]
file_responses = [
{
"download_url": 'A', "description": 'B', "name": 'C', "size": 100
Expand All @@ -90,11 +100,12 @@ def test_get_submission_info(self, xblock):
mock_submission = Mock()
mock_answer = Mock()
mock_answer.get_text_responses.return_value = text_responses
mock_answer.get_file_uploads.return_value = file_uploads
self.set_staff_user(xblock, 'Bob')
with self._mock_get_submission(return_value=mock_submission):
with self._mock_parse_submission_raw_answer(return_value=mock_answer):
self._mock_get_download_urls_from_submission(xblock, return_value=file_responses)
response = self.request(xblock, {'submission_uuid': submission_uuid})
with self._mock_get_download_urls():
response = self.request(xblock, {'submission_uuid': submission_uuid})

self.assert_response(
response,
Expand Down Expand Up @@ -123,7 +134,7 @@ def test_get_submission_info__integration(self, xblock):
submission, _ = self._create_student_and_submission(student_id, test_answer)

self.set_staff_user(xblock, 'Bob')
with self._mock_get_url_by_file_key(xblock):
with self._mock_get_download_url():
response = self.request(xblock, {'submission_uuid': submission['uuid']})

expected_submission_info = {
Expand Down
16 changes: 16 additions & 0 deletions openassessment/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from openassessment.assessment.models import (Assessment, AssessmentFeedback, AssessmentFeedbackOption, AssessmentPart,
Criterion, CriterionOption, Rubric, StaffWorkflow, TeamStaffWorkflow)
from openassessment.assessment.models.base import SharedFileUpload

User = get_user_model()

Expand Down Expand Up @@ -165,3 +166,18 @@ class Meta:
is_superuser = False
last_login = datetime.datetime(2012, 1, 1, tzinfo=UTC)
date_joined = datetime.datetime(2011, 1, 1, tzinfo=UTC)


class SharedFileUploadFactory(DjangoModelFactory):
""" Create SharedFileUploads for testing """
class Meta:
model = SharedFileUpload

team_id = factory.Sequence(lambda n: f'default_team_{n}')
course_id = factory.Sequence(lambda n: f'default_course_{n}')
item_id = factory.Sequence(lambda n: f'default_item_{n}')
owner_id = None
file_key = factory.Sequence(lambda n: f'shared_file_key_{n}')
description = factory.Sequence(lambda n: f'shared_file_desc_{n}')
size = factory.Sequence(lambda n: 10 + int(n))
name = factory.Sequence(lambda n: f'shared_file_name_{n}')
4 changes: 2 additions & 2 deletions openassessment/xblock/apis/ora_config_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ def get_team_submission_uuid_from_individual_submission_uuid(self, individual_su
def does_team_have_submission(self, team_id):
return self._block.does_team_have_submission(team_id)

def get_team_info(self):
return self._block.get_team_info()
def get_team_info(self, staff_or_preview_data=True):
return self._block.get_team_info(staff_or_preview_data)

def get_student_item_dict(self, anonymous_user_id=None):
return self._block.get_student_item_dict(anonymous_user_id)
Expand Down
36 changes: 36 additions & 0 deletions openassessment/xblock/apis/submissions/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,39 @@ class NoTeamToCreateSubmissionForError(Exception):

class EmptySubmissionError(Exception):
pass


class DraftSaveException(Exception):
pass


class SubmissionValidationException(Exception):
pass


class AnswerTooLongException(Exception):
pass


class SubmitInternalError(Exception):
pass


class StudioPreviewException(Exception):
pass


class MultipleSubmissionsException(Exception):
pass


class DeleteNotAllowed(Exception):
pass


class OnlyOneFileAllowedException(Exception):
pass


class UnsupportedFileTypeException(Exception):
pass
11 changes: 11 additions & 0 deletions openassessment/xblock/apis/submissions/file_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,14 @@ def get_all_upload_urls_for_user(self, username_or_email):

def get_allowed_file_types_or_preset(self):
return self._block.get_allowed_file_types_or_preset

def has_any_file_in_upload_space(self):
# Here we check if there are existing file uploads by checking for
# an existing download url for any of the upload slots.
# Note that we can't use self.saved_files_descriptions because that
# is populated before files are actually uploaded
for potential_file_index in range(self.max_allowed_uploads):
file_url = self.get_download_url(potential_file_index)
if file_url:
return True
return False
Loading
Loading