x/make_submission.py

95 lines
3.1 KiB
Python
Raw Permalink Normal View History

2024-05-20 15:21:04 +00:00
#!/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]} <config>')
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)