import json import sys import warnings from pathlib import Path from typing import Iterable, Union, TYPE_CHECKING if TYPE_CHECKING: from multiprocessing.managers import ListProxy # noqa __all__ = [ "generate_local", ] def _generate_local_inner(games: Iterable[str], dest: Union[Path, str], results: "ListProxy[Union[Path, BaseException]]") -> None: original_argv = sys.argv warnings.simplefilter("ignore") try: from tempfile import TemporaryDirectory if not isinstance(dest, Path): dest = Path(dest) with TemporaryDirectory() as players_dir: with TemporaryDirectory() as output_dir: import Generate import Main for n, game in enumerate(games, 1): player_path = Path(players_dir) / f"{n}.yaml" with open(player_path, "w", encoding="utf-8") as f: f.write(json.dumps({ "name": f"Player{n}", "game": game, game: {"hard_mode": "true"}, "description": f"generate_local slot {n} ('Player{n}'): {game}", })) # this is basically copied from test/programs/test_generate.py # uses a reproducible seed that is different for each set of games sys.argv = [sys.argv[0], "--seed", str(hash(tuple(games))), "--player_files_path", players_dir, "--outputpath", output_dir] Main.main(*Generate.main()) output_files = list(Path(output_dir).glob('*.zip')) assert len(output_files) == 1 final_file = dest / output_files[0].name output_files[0].rename(final_file) results.append(final_file) except BaseException as e: results.append(e) raise e finally: sys.argv = original_argv def generate_local(games: Iterable[str], dest: Union[Path, str]) -> Path: from multiprocessing import Manager, Process, set_start_method try: set_start_method("spawn") except RuntimeError: pass manager = Manager() results: "ListProxy[Union[Path, Exception]]" = manager.list() p = Process(target=_generate_local_inner, args=(games, dest, results)) p.start() p.join() result = results[0] if isinstance(result, BaseException): raise Exception("Could not generate multiworld") from result return result