diff --git a/make_submission.py b/make_submission.py new file mode 100644 index 0000000..eba1647 --- /dev/null +++ b/make_submission.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 + +import json +import os +import shutil +import sys +from typing import Optional +from typing_extensions import Self +import zipfile + +class Output: + def make_directory(self, name: str) -> Self: + pass + + def include_file(self, source_path: str, dest_path: str): + pass + + def create_zip(self, name: str) -> Self: + pass + + def done(self): + pass + +class ZipOutput(Output): + def __init__(self, zf: zipfile.ZipFile, inner_prefix: Optional[str] = None): + self._zf = zf + self._inner_prefix = inner_prefix + + def make_directory(self, name: str) -> Self: + print(f'Making directory `{name}` in `{self._inner_prefix}` inside zip file') + return ZipOutput(self._zf, name if self._inner_prefix is None else os.path.join(self._inner_prefix, name)) + + def include_file(self, source_path: str, dest_path: str): + if self._inner_prefix is not None: + dest_path = os.path.join(self._inner_prefix, dest_path) + print(f'Adding file to zip: `{source_path}` as `{dest_path}`') + self._zf.write(source_path, dest_path) + + def create_zip(self, name: str): + raise RuntimeError('cannot currently create a zip within a zip') + + def done(self): + self._zf.close() + +class DirectoryOutput(Output): + def __init__(self, target_dir: str) -> None: + self._target_dir = target_dir + if not os.path.exists(target_dir): + os.makedirs(target_dir) + + def make_directory(self, name: str) -> Self: + return DirectoryOutput(os.path.join(self._target_dir, name)) + + def include_file(self, source_path: str, dest_path: str): + shutil.copy2(source_path, os.path.join(self._target_dir, dest_path)) + + def create_zip(self, name: str) -> Self: + return ZipOutput(zipfile.ZipFile(os.path.join(self._target_dir, name), 'w')) + +def create_object(output: Output, obj: dict[str, any]): + if 'type' not in obj: + raise KeyError(f'`type` not found in `{obj}`') + if 'name' not in obj: + raise KeyError(f'`name` not found in `{obj}`') + ty = obj['type'] + name = obj['name'] + if ty == 'zip' or ty == 'directory': + if 'content' not in obj: + raise KeyError(f'`content` not found in `{obj}`') + sub_output = output.create_zip(name) if ty == 'zip' else output.make_directory(name) + for item in obj['content']: + create_object(sub_output, item) + elif ty == 'file': + if 'source' not in obj: + raise KeyError(f'`source` not found in `{obj}`') + source = obj['source'] + output.include_file(source, name) + else: + raise ValueError(f'Unknown type: `{ty}`') + +def main(args: list[str]): + if len(args) < 2: + print(f'Usage: {sys.argv[0]} ') + exit(1) + + with open(sys.argv[1]) as f: + config = json.load(f) + + print('Generating...') + create_object(DirectoryOutput('target/'), config) + print('Done!') + +if __name__ == '__main__': + main(sys.argv)