#!/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)