Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 22 additions & 18 deletions worlds/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import importlib
import importlib.abc
import importlib.machinery
import importlib.util
import logging
import os
import sys
import warnings
import zipimport
import time
import dataclasses
import json
from typing import List
from pathlib import Path
from types import ModuleType
from typing import List, Sequence

from NetUtils import DataPackage
from Utils import local_path, user_path, Version, version_tuple, tuplize_version
Expand Down Expand Up @@ -53,21 +56,7 @@ def resolved_path(self) -> str:
def load(self) -> bool:
try:
start = time.perf_counter()
if self.is_zip:
importer = zipimport.zipimporter(self.resolved_path)
spec = importer.find_spec(os.path.basename(self.path).rsplit(".", 1)[0])
assert spec, f"{self.path} is not a loadable module"
mod = importlib.util.module_from_spec(spec)

mod.__package__ = f"worlds.{mod.__package__}"

mod.__name__ = f"worlds.{mod.__name__}"
sys.modules[mod.__name__] = mod
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message="__package__ != __spec__.parent")
importer.exec_module(mod)
else:
importlib.import_module(f".{self.path}", "worlds")
importlib.import_module(f".{Path(self.path).stem}", "worlds")
self.time_taken = time.perf_counter()-start
return True

Expand Down Expand Up @@ -112,7 +101,6 @@ def load(self) -> bool:
else:
world_source.load()


from .AutoWorld import AutoWorldRegister

for world_source in world_sources:
Expand Down Expand Up @@ -174,13 +162,29 @@ def fail_world(game_name: str, reason: str, add_as_failed_to_load: bool = True)
core_compatible.sort(
key=lambda element: element[1].world_version if element[1].world_version else Version(0, 0, 0),
reverse=True)

apworld_module_specs = {}
class APWorldModuleFinder(importlib.abc.MetaPathFinder):
def find_spec(
self, fullname: str, _path: Sequence[str] | None, _target: ModuleType = None
) -> importlib.machinery.ModuleSpec | None:
return apworld_module_specs.get(fullname)

sys.meta_path.insert(0, APWorldModuleFinder())

for apworld_source, apworld in core_compatible:
if apworld.game and apworld.game in AutoWorldRegister.world_types:
fail_world(apworld.game,
f"Did not load {apworld_source.path} "
f"as its game {apworld.game} is already loaded.",
add_as_failed_to_load=False)
else:
importer = zipimport.zipimporter(apworld_source.resolved_path)
world_name = Path(apworld.path).stem

spec = importer.find_spec(f"worlds.{world_name}")
apworld_module_specs[f"worlds.{world_name}"] = spec

apworld_source.load()
if apworld.game in AutoWorldRegister.world_types:
# world could fail to load at this point
Expand Down
Loading