Source code for grader.asset_management

import os
import sys
import contextlib
from shutil import copy, rmtree
from tempfile import NamedTemporaryFile, mkdtemp, gettempdir


@contextlib.contextmanager
[docs]def tempModule(code, working_dir=None, encoding="utf8"): if working_dir is None: working_dir = gettempdir() file = NamedTemporaryFile( dir=working_dir, mode="wb", suffix=".py", delete=False ) file.write(code.encode(encoding)) file.close() try: yield file.name finally: os.remove(file.name)
[docs]class AssetFolder: def __init__(self, tester_path, solution_path, other_files=[], is_code=False, add_to_path=True): self.path = mkdtemp() if is_code: creator_function = self._write else: creator_function = self._copy self.tester_path = creator_function(tester_path) self.solution_path = creator_function(solution_path) if is_code: self.other_files = list(map(self.write_asset, other_files)) else: self.other_files = list(map(self._copy, other_files)) self.add_to_path = add_to_path if add_to_path: sys.path.append(self.path) self.original_cwd = os.getcwd() os.chdir(self.path) def _copy(self, file_path): # returns path if os.path.isdir(file_path): files = os.listdir(file_path) return [self._copy(os.path.join(file_path, name)) for name in files] return copy(file_path, self.path) def _write(self, code): file = NamedTemporaryFile( dir=self.path, mode="w", suffix=".py", delete=False ) file.write(code) file.close() return file.name
[docs] def write_asset(self, asset_info): path = os.path.join(self.path, os.path.basename(asset_info["filename"])) with open(path, "w") as f: f.write(asset_info["contents"]) return path
[docs] def remove(self): if self.add_to_path: sys.path.remove(self.path) os.chdir(self.original_cwd) if not os.path.exists(self.path): raise IOError("{} already doesn't exist".format(self.path)) rmtree(self.path)
[docs] def files_in_path(self): return os.listdir(self.path)
def __enter__(self): return self def __exit__(self, *args): self.remove() def __str__(self): return "<Assets: %s %s %s>" % (self.tester_path, self.solution_path, self.other_files)