diff --git a/cms/grading/languagemanager.py b/cms/grading/languagemanager.py index 097dc0adc2..9bc8c917d5 100644 --- a/cms/grading/languagemanager.py +++ b/cms/grading/languagemanager.py @@ -18,10 +18,10 @@ """Provide utilities to work with programming language classes.""" +import logging from cms import plugin_list from cms.grading.language import Language - __all__ = [ "LANGUAGES", "HEADER_EXTS", "SOURCE_EXTS", "OBJECT_EXTS", @@ -29,6 +29,9 @@ ] +logger = logging.getLogger(__name__) + + LANGUAGES: list[Language] = list() _BY_NAME: dict[str, Language] = dict() HEADER_EXTS: set[str] = set() @@ -50,6 +53,25 @@ def get_language(name: str) -> Language: return _BY_NAME[name] +def safe_get_lang_filename(lang: str | None, filename: str) -> str: + """Get the filename of a file in a specific programming language, + avoiding errors if the language isn't recognized. + + lang: name of the programming language + filename: filename template (containing .%l) + return: filename with the template replaced. + """ + if lang is None: + return filename + try: + language = get_language(lang) + source_ext = language.source_extension + except KeyError: + logger.warning(f"Found invalid language {lang}!") + source_ext = ".invalid_language" + return filename.replace(".%l", source_ext) + + def filename_to_language(filename: str, available_languages: list[Language] | None=None) -> Language | None: """Return one of the languages inferred from the given filename. diff --git a/cms/server/admin/handlers/submission.py b/cms/server/admin/handlers/submission.py index 2a062c7802..cd528cff1b 100644 --- a/cms/server/admin/handlers/submission.py +++ b/cms/server/admin/handlers/submission.py @@ -31,7 +31,7 @@ import difflib from cms.db import Dataset, File, Submission -from cms.grading.languagemanager import get_language +from cms.grading.languagemanager import safe_get_lang_filename from cmscommon.datetime import make_datetime from .base import BaseHandler, FileHandler, require_permission @@ -80,10 +80,7 @@ def get(self, file_id): sub_file = self.safe_get_item(File, file_id) submission = sub_file.submission - real_filename = sub_file.filename - if submission.language is not None: - real_filename = real_filename.replace( - ".%l", get_language(submission.language).source_extension) + real_filename = safe_get_lang_filename(submission.language, sub_file.filename) digest = sub_file.digest self.sql_session.close() @@ -130,10 +127,9 @@ def get(self, old_id, new_id): for fname in files_to_compare: if ".%l" in fname: if sub_old.language == sub_new.language and sub_old.language is not None: - ext = get_language(sub_old.language).source_extension + real_fname = safe_get_lang_filename(sub_old.language, fname) else: - ext = ".txt" - real_fname = fname.replace(".%l", ext) + real_fname = fname.replace(".%l", ".txt") else: real_fname = fname diff --git a/cms/server/admin/handlers/usertest.py b/cms/server/admin/handlers/usertest.py index 9a6cdfdd54..25328ed049 100644 --- a/cms/server/admin/handlers/usertest.py +++ b/cms/server/admin/handlers/usertest.py @@ -21,7 +21,7 @@ """ from cms.db import Dataset, UserTestFile, UserTest -from cms.grading.languagemanager import get_language +from cms.grading.languagemanager import safe_get_lang_filename from .base import BaseHandler, FileHandler, require_permission @@ -60,10 +60,7 @@ def get(self, file_id): user_test_file = self.safe_get_item(UserTestFile, file_id) user_test = user_test_file.user_test - real_filename = user_test_file.filename - if user_test.language is not None: - real_filename = real_filename.replace( - ".%l", get_language(user_test.language).source_extension) + real_filename = safe_get_lang_filename(user_test.language, user_test_file.filename) digest = user_test_file.digest self.sql_session.close() diff --git a/cms/server/admin/templates/fragments/user_test_row.html b/cms/server/admin/templates/fragments/user_test_row.html index e3d24146a5..b4fac30e7f 100644 --- a/cms/server/admin/templates/fragments/user_test_row.html +++ b/cms/server/admin/templates/fragments/user_test_row.html @@ -52,7 +52,7 @@