views/data: fix get_valid_files

Before #2197, `get_valid_files` returned a `List[str]`. Then it returned
an `Option[List[str]]`, because we wanted to flag invalid zips. This
caused issues with iterating, and is a pretty terrible design.

Instead, we just re-raise the BadZipfile, and handle it in the two
places this function is used.
This commit is contained in:
Keenan Gugeler 2024-01-09 00:27:53 -05:00 committed by Roger Fu
parent 1bacacb83e
commit 9c513c2453

View File

@ -2,6 +2,7 @@ import json
import mimetypes
import os
from itertools import chain
from typing import List
from zipfile import BadZipfile, ZipFile
from django.conf import settings
@ -169,7 +170,7 @@ class ProblemDataView(TitleMixin, ProblemManagerMixin):
return ProblemCaseFormSet(data=self.request.POST if post else None, prefix='cases', valid_files=files,
queryset=ProblemTestCase.objects.filter(dataset_id=self.object.pk).order_by('order'))
def get_valid_files(self, data, post=False):
def get_valid_files(self, data, post=False) -> List[str]:
try:
if post and 'problem-data-zipfile-clear' in self.request.POST:
return []
@ -178,26 +179,35 @@ class ProblemDataView(TitleMixin, ProblemManagerMixin):
elif data.zipfile:
return ZipFile(data.zipfile.path).namelist()
except BadZipfile:
return None
raise
return []
def get_context_data(self, **kwargs):
context = super(ProblemDataView, self).get_context_data(**kwargs)
valid_files = []
if 'data_form' not in context:
context['data_form'] = self.get_data_form()
valid_files = context['valid_files'] = self.get_valid_files(context['data_form'].instance)
context['cases_formset'] = self.get_case_formset(valid_files)
if context['valid_files']:
context['valid_files_json'] = mark_safe(json.dumps(context['valid_files']))
context['valid_files'] = set(context['valid_files'])
try:
valid_files = self.get_valid_files(context['data_form'].instance)
except BadZipfile:
pass
context['valid_files'] = set(valid_files)
context['valid_files_json'] = mark_safe(json.dumps(valid_files))
context['cases_formset'] = self.get_case_formset(valid_files)
context['all_case_forms'] = chain(context['cases_formset'], [context['cases_formset'].empty_form])
return context
def post(self, request, *args, **kwargs):
self.object = problem = self.get_object()
data_form = self.get_data_form(post=True)
valid_files = self.get_valid_files(data_form.instance, post=True)
data_form.zip_valid = valid_files is not None
try:
valid_files = self.get_valid_files(data_form.instance, post=True)
data_form.zip_valid = True
except BadZipfile:
valid_files = []
data_form.zip_valid = False
cases_formset = self.get_case_formset(valid_files, post=True)
if data_form.is_valid() and cases_formset.is_valid():
data = data_form.save()