dataclassio multitype fixes/tidying

This commit is contained in:
Eric 2024-02-01 12:35:00 -08:00
parent 3186ff6b50
commit dc6d29de22
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
8 changed files with 86 additions and 32 deletions

40
.efrocachemap generated
View File

@ -4060,26 +4060,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "4061f6114403c60ce1553d2b95c6fd7f", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "7169141b846e3c15160f3405bd1ed2ce",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "c73d4beea86082419fa0dee9cf8e93be", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "04869210f06ff8c00fb6d68a69f6b335",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "928c17c937e26d2fdc9edc8bc1e07659", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "e28eac17f30edddc35c483fbc4e69fc5",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "07a90a9ee49ccfcf4cb0fcbccd0e1a04", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "342aee2d1f2965caed811a72888cc7f1",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "aa4929306878a5e757be36bbd80cb3b3", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "c091240edeeeac378ffe86ce1421decc",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "6579bfe457770767a35ce69513433273", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "c959d3661ea83a2f9920da6d6d355fd9",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "0eb96f2dfd3798621dd35d3693e596f7", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "9015fb2718d6fc5a9a9bd95b0086bde6",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "21ff8796c4e459d4087a68d02b998576", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "dfcd11db04c0071b7e5032673c2dad43",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a69ade336e8d9574919debda154ca2ec", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "8a0ad295f62fc9cfa4a71d30038b0c20",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "ce625368b6392bc3d9c6f033b1255c6f", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "21f2f9aecbd0c60b8e125f206ebd44c2",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "0b606c6c6f4774dc9cfebfab347d6271", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "df5d59cf4b6da427b3e2bb4d1136cf32",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "56878ae9435c3b99a62319e016418dff", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "72f5ab8cd24ce31b8bbfe08ce691bf7b",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "461c5e567f8bf9726a1b7f5ced7e7418", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "11280b6cbec7a21574f0e8e29c379bea",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "c6a85daf172fee978c7deafb3b50fc21", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "766b8ad86046a92fa5fa25a0a7ad88ae",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "42121063ca6dc6a446a331b2ea4dc707", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "10ac2e99587552edfc3eb089ea69ede4",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "94a0a0bec30f85b0397fb1925ef54e33", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "8cd63147b79d8866af817d01dcc8f5eb",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "f9f983439f6b2a5cc92e2c8c575b66bb", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "061de20725a847ac6ed327d8c2e5b905",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ec5f0294584602e88e071eb336b671fd", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "6556a6e96f2a360a4006f2c2b7a5a1f1",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "6c49a9829024ff91e2d07dbaf2c75184", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "1324063eeaeda2c72f7e133984fa838b",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "f82d8ed05ca2fa9a3bef869e3ce6ac4b", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "3c6b96c3a63fc53819425f8872264aa8",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "8709ad96140d71760c2f493ee8bd7c43", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "8709ad96140d71760c2f493ee8bd7c43",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "ee829cd5488e9750570dc6f602d65589", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "ee829cd5488e9750570dc6f602d65589",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "8709ad96140d71760c2f493ee8bd7c43", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "8709ad96140d71760c2f493ee8bd7c43",

View File

@ -1,4 +1,4 @@
### 1.7.33 (build 21764, api 8, 2024-01-31) ### 1.7.33 (build 21766, api 8, 2024-02-01)
- Stress test input-devices are now a bit smarter; they won't press any buttons - Stress test input-devices are now a bit smarter; they won't press any buttons
while UIs are up (this could cause lots of chaos if it happened). while UIs are up (this could cause lots of chaos if it happened).
- Added a 'Show Demos When Idle' option in advanced settings. If enabled, the - Added a 'Show Demos When Idle' option in advanced settings. If enabled, the

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be # Build number and version of the ballistica binary we expect to be
# using. # using.
TARGET_BALLISTICA_BUILD = 21764 TARGET_BALLISTICA_BUILD = 21766
TARGET_BALLISTICA_VERSION = '1.7.33' TARGET_BALLISTICA_VERSION = '1.7.33'

View File

@ -14,7 +14,7 @@ Mac:
(brew install python3). (brew install python3).
Linux (x86_64): Linux (x86_64):
- Server binaries are currently compiled against Ubuntu 20 LTS. - Server binaries are currently compiled against Ubuntu 22 LTS.
Raspberry Pi: Raspberry Pi:
- The server binary was compiled on a Raspberry Pi 4 running Raspbian Buster. - The server binary was compiled on a Raspberry Pi 4 running Raspbian Buster.

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't modify them here. // These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21764; const int kEngineBuildNumber = 21766;
const char* kEngineVersion = "1.7.33"; const char* kEngineVersion = "1.7.33";
const int kEngineApiVersion = 8; const int kEngineApiVersion = 8;

View File

@ -5,6 +5,7 @@
from __future__ import annotations from __future__ import annotations
import copy
import datetime import datetime
from enum import Enum from enum import Enum
from dataclasses import field, dataclass from dataclasses import field, dataclass
@ -1159,6 +1160,7 @@ class MTTestClass2(MTTestBase):
def test_multi_type() -> None: def test_multi_type() -> None:
"""Test IOMultiType stuff.""" """Test IOMultiType stuff."""
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
# pylint: disable=too-many-statements
# Test converting single instances back and forth. # Test converting single instances back and forth.
val1: MTTestBase = MTTestClass1(ival=123) val1: MTTestBase = MTTestClass1(ival=123)
@ -1179,6 +1181,17 @@ def test_multi_type() -> None:
assert dataclass_from_dict(MTTestBase, outdict) == val1 assert dataclass_from_dict(MTTestBase, outdict) == val1
assert dataclass_from_dict(MTTestBase, outdict2) == val2 assert dataclass_from_dict(MTTestBase, outdict2) == val2
# Trying to load as a multi-type should fail if there is no type
# value present.
outdictmod = copy.deepcopy(outdict)
del outdictmod[tpname]
with pytest.raises(ValueError):
dataclass_from_dict(MTTestBase, outdictmod)
# However it should work when loading an exact type. This can be
# necessary to gracefully upgrade old data to multi-type form.
dataclass_from_dict(MTTestClass1, outdictmod)
# Now test our multi-type embedded in other classes. We should be # Now test our multi-type embedded in other classes. We should be
# able to throw a mix of things in there and have them deserialize # able to throw a mix of things in there and have them deserialize
# back the types we started with. # back the types we started with.
@ -1253,3 +1266,33 @@ def test_multi_type() -> None:
outdict = dataclass_to_dict(container5) outdict = dataclass_to_dict(container5)
container5b = dataclass_from_dict(_TestContainerClass5, outdict) container5b = dataclass_from_dict(_TestContainerClass5, outdict)
assert container5 == container5b assert container5 == container5b
# Optionals.
@ioprepped
@dataclass
class _TestContainerClass6:
obj: MTTestBase | None
container6 = _TestContainerClass6(obj=None)
outdict = dataclass_to_dict(container6)
container6b = dataclass_from_dict(_TestContainerClass6, outdict)
assert container6 == container6b
container6 = _TestContainerClass6(obj=MTTestClass2('fwr'))
outdict = dataclass_to_dict(container6)
container6b = dataclass_from_dict(_TestContainerClass6, outdict)
assert container6 == container6b
@ioprepped
@dataclass
class _TestContainerClass7:
obj: Annotated[
MTTestBase | None,
IOAttrs('o', soft_default=None),
]
container7 = _TestContainerClass7(obj=None)
outdict = dataclass_to_dict(container7)
container7b = dataclass_from_dict(_TestContainerClass7, {})
assert container7 == container7b

View File

@ -69,16 +69,21 @@ class IOMultiType(Generic[EnumT]):
This enables usage of high level base classes (for example This enables usage of high level base classes (for example
a 'Message' type) in dataclasses, with dataclassio automatically a 'Message' type) in dataclasses, with dataclassio automatically
serializing/deserializing subclass instances using provided serializing & deserializing subclass instances based on their
per-class type-ids. type.
See tests/test_efro/test_dataclassio.py for an example of this. Standard usage involves creating a class which inherits from this
one that acts as a 'registry', and then creating dataclass classes
inheriting from that registry class. Dataclassio will then do the
right thing when that registry class is used in type annotations.
See tests/test_efro/test_dataclassio.py for examples.
""" """
# Dataclasses inheriting from an IOMultiType will store a type-id # Dataclasses inheriting from an IOMultiType will store a type-id
# with this key in their serialized data. This value can be # with this key in their serialized data. This value can be
# overridden in IOMultiType subclasses in case of conflicts. # overridden in IOMultiType subclasses in case of conflicts.
ID_STORAGE_NAME = '_iotype' ID_STORAGE_NAME = '_dciotype'
@classmethod @classmethod
def get_type(cls, type_id: EnumT) -> type[Self]: def get_type(cls, type_id: EnumT) -> type[Self]:

View File

@ -64,9 +64,15 @@ class _Inputter:
outcls: type[Any] outcls: type[Any]
# If we're dealing with a multi-type class, figure out the # If we're dealing with a multi-type subclass which is NOT a
# top level type we're going to. # dataclass, we must rely on its stored type to figure out
if issubclass(self._cls, IOMultiType): # what type of dataclass we're going to. If we are a dataclass
# then we already know what type we're going to so we can
# survive without this, which is often necessary when reading
# old data that doesn't have a type id attr yet.
if issubclass(self._cls, IOMultiType) and not dataclasses.is_dataclass(
self._cls
):
type_id_val = values.get(self._cls.ID_STORAGE_NAME) type_id_val = values.get(self._cls.ID_STORAGE_NAME)
if type_id_val is None: if type_id_val is None:
raise ValueError( raise ValueError(
@ -265,7 +271,7 @@ class _Inputter:
args: dict[str, Any] = {} args: dict[str, Any] = {}
for rawkey, value in values.items(): for rawkey, value in values.items():
# Ignore _iotype or whatnot. # Ignore _dciotype or whatnot.
if type_id_store_name is not None and rawkey == type_id_store_name: if type_id_store_name is not None and rawkey == type_id_store_name:
continue continue