Skip to content

Commit

Permalink
add ipynb mimetype; check that json loads
Browse files Browse the repository at this point in the history
  • Loading branch information
lukeolson authored and inducer committed Jul 30, 2024
1 parent 52a2ccb commit 1296ce9
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
29 changes: 23 additions & 6 deletions course/page/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"""


from mimetypes import add_type, guess_extension

import django.forms as forms
from crispy_forms.layout import Field, Layout
from django.utils.translation import gettext as _, gettext_lazy
Expand All @@ -39,6 +41,9 @@
from relate.utils import StyledForm, string_concat


add_type("application/x-ipynb+json", ".ipynb")


# {{{ upload question

class FileUploadForm(StyledForm):
Expand Down Expand Up @@ -76,9 +81,22 @@ def clean_uploaded_file(self):
% {"allowedsize": filesizeformat(self.max_file_size),
"uploadedsize": filesizeformat(uploaded_file.size)})

if self.mime_types is not None and self.mime_types == ["application/pdf"]:
if uploaded_file.read()[:4] != b"%PDF":
raise forms.ValidationError(_("Uploaded file is not a PDF."))
if self.mime_types is not None:
if self.mime_types == ["application/pdf"]:
if uploaded_file.read()[:4] != b"%PDF":
raise forms.ValidationError(_("Uploaded file is not a PDF."))
elif self.mime_types == ["application/x-ipynb+json"]:
try:
# make sure it is loadable json
import json
data = json.load(uploaded_file)

# check for a notebook format of at least 4
if int(data["nbformat"]) < 4:
raise ValueError(_("Invalid notebook format."))
except Exception:
raise forms.ValidationError(_("Uploaded file is not a "
"Jupyter notebook."))

return uploaded_file

Expand Down Expand Up @@ -132,6 +150,7 @@ class FileUploadQuestion(PageBaseWithTitle, PageBaseWithValue,
* ``application/pdf`` (will check for a PDF header)
* ``text/plain`` (no check performed)
* ``application/octet-stream`` (no check performed)
* ``application/x-ipynb+json`` (will check for JSON and nbformat>=4)
.. attribute:: maximum_megabytes
Expand All @@ -156,6 +175,7 @@ class FileUploadQuestion(PageBaseWithTitle, PageBaseWithValue,
"application/pdf",
"text/plain",
"application/octet-stream",
"application/x-ipynb+json",
]

def __init__(self, vctx, location, page_desc):
Expand Down Expand Up @@ -205,7 +225,6 @@ def body(self, page_context, page_data):
return markup_to_html(page_context, self.page_desc.prompt)

def get_submission_filename_pattern(self, page_context, mime_type):
from mimetypes import guess_extension
if mime_type is not None:
ext = guess_extension(mime_type)
else:
Expand Down Expand Up @@ -295,8 +314,6 @@ def normalized_bytes_answer(self, page_context, page_data, answer_data):
return None

subm_data, subm_mime = self.get_content_from_answer_data(answer_data)

from mimetypes import guess_extension
ext = guess_extension(subm_mime)

if ext is None:
Expand Down
1 change: 1 addition & 0 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@ def test_content_type(self):
("images/django-logo.png", "image/png"),
("images/classroom.jpeg", "image/jpeg"),
("pdfs/sample.pdf", "application/pdf"),
("ipynbs/Ipynb_example.ipynb", "application/x-ipynb+json"),
)
for repo_file, content_type in tup:
with self.subTest(repo_file=repo_file):
Expand Down

0 comments on commit 1296ce9

Please sign in to comment.