Core: Allow PlandoItems to be pickled (#5335)
* Add Options.PlandoItem * Remove worlds.generic.PlandoItem handling * Add plando pickling test * Revert old PlandoItem cleanup * Deprecate old PlandoItem * Change to warning message * Use deprecated decorator
This commit is contained in:
2
Utils.py
2
Utils.py
@@ -477,7 +477,7 @@ class RestrictedUnpickler(pickle.Unpickler):
|
|||||||
mod = importlib.import_module(module)
|
mod = importlib.import_module(module)
|
||||||
obj = getattr(mod, name)
|
obj = getattr(mod, name)
|
||||||
if issubclass(obj, (self.options_module.Option, self.options_module.PlandoConnection,
|
if issubclass(obj, (self.options_module.Option, self.options_module.PlandoConnection,
|
||||||
self.options_module.PlandoText)):
|
self.options_module.PlandoItem, self.options_module.PlandoText)):
|
||||||
return obj
|
return obj
|
||||||
# Forbid everything else.
|
# Forbid everything else.
|
||||||
raise pickle.UnpicklingError(f"global '{module}.{name}' is forbidden")
|
raise pickle.UnpicklingError(f"global '{module}.{name}' is forbidden")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from BaseClasses import PlandoOptions
|
from BaseClasses import PlandoOptions
|
||||||
from Options import ItemLinks, Choice
|
from Options import Choice, ItemLinks, PlandoConnections, PlandoItems, PlandoTexts
|
||||||
from Utils import restricted_dumps
|
from Utils import restricted_dumps
|
||||||
from worlds.AutoWorld import AutoWorldRegister
|
from worlds.AutoWorld import AutoWorldRegister
|
||||||
|
|
||||||
@@ -72,8 +72,8 @@ class TestOptions(unittest.TestCase):
|
|||||||
for link in item_links.values():
|
for link in item_links.values():
|
||||||
self.assertEqual(link.value[0], item_link_group[0])
|
self.assertEqual(link.value[0], item_link_group[0])
|
||||||
|
|
||||||
def test_pickle_dumps(self):
|
def test_pickle_dumps_default(self):
|
||||||
"""Test options can be pickled into database for WebHost generation"""
|
"""Test that default option values can be pickled into database for WebHost generation"""
|
||||||
for gamename, world_type in AutoWorldRegister.world_types.items():
|
for gamename, world_type in AutoWorldRegister.world_types.items():
|
||||||
if not world_type.hidden:
|
if not world_type.hidden:
|
||||||
for option_key, option in world_type.options_dataclass.type_hints.items():
|
for option_key, option in world_type.options_dataclass.type_hints.items():
|
||||||
@@ -81,3 +81,23 @@ class TestOptions(unittest.TestCase):
|
|||||||
restricted_dumps(option.from_any(option.default))
|
restricted_dumps(option.from_any(option.default))
|
||||||
if issubclass(option, Choice) and option.default in option.name_lookup:
|
if issubclass(option, Choice) and option.default in option.name_lookup:
|
||||||
restricted_dumps(option.from_text(option.name_lookup[option.default]))
|
restricted_dumps(option.from_text(option.name_lookup[option.default]))
|
||||||
|
|
||||||
|
def test_pickle_dumps_plando(self):
|
||||||
|
"""Test that plando options using containers of a custom type can be pickled"""
|
||||||
|
# The base PlandoConnections class can't be instantiated directly, create a subclass and then cast it
|
||||||
|
class TestPlandoConnections(PlandoConnections):
|
||||||
|
entrances = {"An Entrance"}
|
||||||
|
exits = {"An Exit"}
|
||||||
|
plando_connection_value = PlandoConnections(
|
||||||
|
TestPlandoConnections.from_any([{"entrance": "An Entrance", "exit": "An Exit"}])
|
||||||
|
)
|
||||||
|
|
||||||
|
plando_values = {
|
||||||
|
"PlandoConnections": plando_connection_value,
|
||||||
|
"PlandoItems": PlandoItems.from_any([{"item": "Something", "location": "Somewhere"}]),
|
||||||
|
"PlandoTexts": PlandoTexts.from_any([{"text": "Some text.", "at": "text_box"}]),
|
||||||
|
}
|
||||||
|
|
||||||
|
for option_key, value in plando_values.items():
|
||||||
|
with self.subTest(option=option_key):
|
||||||
|
restricted_dumps(value)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from typing import NamedTuple, Union
|
from typing import NamedTuple, Union
|
||||||
|
from typing_extensions import deprecated
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from BaseClasses import Item, Tutorial, ItemClassification
|
from BaseClasses import Item, Tutorial, ItemClassification
|
||||||
@@ -49,7 +50,8 @@ class GenericWorld(World):
|
|||||||
return Item(name, ItemClassification.filler, -1, self.player)
|
return Item(name, ItemClassification.filler, -1, self.player)
|
||||||
raise InvalidItemError(name)
|
raise InvalidItemError(name)
|
||||||
|
|
||||||
|
@deprecated("worlds.generic.PlandoItem is deprecated and will be removed in the next version. "
|
||||||
|
"Use Options.PlandoItem(s) instead.")
|
||||||
class PlandoItem(NamedTuple):
|
class PlandoItem(NamedTuple):
|
||||||
item: str
|
item: str
|
||||||
location: str
|
location: str
|
||||||
|
|||||||
Reference in New Issue
Block a user