Source code for sio3pack.django.common.handler

import json
from typing import Any

from django.core.files import File
from django.db import transaction

from sio3pack.django.common.models import (
    SIO3Package,
    SIO3PackMainModelSolution,
    SIO3PackModelSolution,
    SIO3PackNameTranslation,
    SIO3PackStatement,
    SIO3PackTest,
    SIO3PackWorkflow,
)
from sio3pack.exceptions import PackageAlreadyExists
from sio3pack.files import LocalFile
from sio3pack.files.remote_file import RemoteFile
from sio3pack.test import Test
from sio3pack.workflow import Workflow


[docs] class DjangoHandler: """ Base class for handling Django models. Allows to save the package to the database and retrieve its data. :param Package package: The package to handle. :param int problem_id: The problem ID. """ def __init__(self, package: "Package", problem_id: int): """ Initialize the handler with the package and problem ID. :param Package package: The package to handle. :param int problem_id: The problem ID. """ self.package = package self.problem_id = problem_id try: self.db_package = SIO3Package.objects.get(problem_id=self.problem_id) except SIO3Package.DoesNotExist: self.db_package = None
[docs] @transaction.atomic def save_to_db(self): """ Save the package to the database. :raises PackageAlreadyExists: If a package with the same problem ID already exists. """ if SIO3Package.objects.filter(problem_id=self.problem_id).exists(): raise PackageAlreadyExists(self.problem_id) self.db_package = SIO3Package.objects.create( problem_id=self.problem_id, short_name=self.package.short_name, full_name=self.package.full_name, ) self._save_translated_titles() self._save_model_solutions() self._save_main_model_solution() self._save_problem_statements() self._save_tests() self._save_workflows()
def _save_translated_titles(self): """ Save the translated titles to the database. """ for lang, title in self.package.lang_titles.items(): SIO3PackNameTranslation.objects.create( package=self.db_package, language=lang, name=title, ) def _save_main_model_solution(self): """ Save the main model solution to the database. """ instance = SIO3PackMainModelSolution( package=self.db_package, ) instance.source_file.save( self.package.main_model_solution.filename, File(open(self.package.main_model_solution.path, "rb")) ) instance.save() def _save_model_solutions(self): for order, solution in enumerate(self.package.model_solutions): instance = SIO3PackModelSolution( package=self.db_package, name=solution.filename, order_key=order, ) instance.source_file.save(solution.filename, File(open(solution.path, "rb"))) instance.save() def _save_problem_statements(self): def _add_statement(language: str, statement: LocalFile): instance = SIO3PackStatement( package=self.db_package, language=language, ) instance.content.save(statement.filename, File(open(statement.path, "rb"))) if self.package.get_statement(): _add_statement("", self.package.get_statement()) for lang, statement in self.package.lang_statements.items(): _add_statement(lang, statement) def _save_tests(self): for test in self.package.tests: instance = SIO3PackTest( package=self.db_package, name=test.test_name, test_id=test.test_id, group=test.group, ) if test.in_file: instance.input_file.save(test.in_file.filename, File(open(test.in_file.path, "rb"))) if test.out_file: instance.output_file.save(test.out_file.filename, File(open(test.out_file.path, "rb"))) instance.save() def _save_workflows(self): for name, wf in self.package.workflow_manager.all().items(): instance = SIO3PackWorkflow( package=self.db_package, name=name, workflow_raw=json.dumps(wf.to_json()), ) instance.save()
[docs] def get_executable_path(self, program: File | str) -> str | None: """ Get the executable path for the given program. :param File | str program: The program to get the path for. :return: The executable path or None if not found. """ if isinstance(program, File): return program.path + ".e" elif isinstance(program, str): return program + ".e"
@property def short_name(self) -> str: """ Short name of the problem. """ return self.db_package.short_name @property def full_name(self) -> str: """ Full name of the problem. """ return self.db_package.full_name @property def lang_titles(self) -> dict[str, str]: """ A dictionary of problem titles, where keys are language codes and values are titles. """ return {t.language: t.name for t in self.db_package.name_translations.all()} @property def model_solutions(self) -> list[dict[str, Any]]: """ A list of model solutions, where each element is a dictionary containing a :class:`RemoteFile` object. """ return [{"file": RemoteFile(s.source_file)} for s in self.db_package.model_solutions.all()] @property def main_model_solution(self) -> RemoteFile: """ The main model solution as a :class:`RemoteFile`. """ return RemoteFile(self.db_package.main_model_solution.source_file) @property def lang_statements(self) -> dict[str, RemoteFile]: """ A dictionary of problem statements, where keys are language codes and values are files. """ return {s.language: RemoteFile(s.content) for s in self.db_package.statements.all()} @property def tests(self) -> list[Test]: """ A list of tests, where each element is a dictionary containing """ return [ Test( test_id=t.test_id, test_name=t.name, group=t.group, in_file=RemoteFile(t.input_file) if t.input_file else None, out_file=RemoteFile(t.output_file) if t.output_file else None, ) for t in self.db_package.tests.all() ] @property def workflows(self) -> dict[str, Workflow]: """ A dictionary of workflows, where keys are workflow names and values are :class:`Workflow` objects. """ return {w.name: w.workflow for w in self.db_package.workflows.all()}