Comments (4)
The more I look into it the less likely it seems I'll be able to register the ECS World
with cattrs
. At the very least I'll need to pass the converter into the serialization function otherwise the converter configuration is lost.
For components I could probably do something like this for their types and data:
import importlib
from typing import Any
import cattrs
def unstructure_generic(obj: object, converter: cattrs.Converter) -> dict[str, Any]:
"""Unstructure any type or instance to a qualified path and its data."""
if isinstance(obj, type):
return {"module": obj.__module__, "type": obj.__name__}
return {
"module": obj.__class__.__module__,
"type": obj.__class__.__name__,
"data": converter.unstructure(obj, obj.__class__),
}
def structure_generic(blob: dict[str, Any], converter: cattrs.Converter) -> Any:
"""Structure a previously unstructured generic object."""
out_type: type[Any] = getattr(importlib.import_module(blob["module"]), blob["type"])
if "data" not in blob:
return out_type
return converter.structure(blob["data"], out_type)
This should work for everything except object()
from python-tcod-ecs.
Dropping a reminder to myself and a notice that I plan to take a look at this tomorrow, will need to look deeper into tcod-ecs
to figure out how to handle this
from python-tcod-ecs.
So cattrs
only works with simple callable objects, but both the converter and any extra state can be tracked by making a new class and registering that classes methods with cattrs.
class _ECSConverter:
... # Weak references to known Worlds and plain object are tracked by this class
def unstructure_uid(self, obj: object) -> dict[Any, str]:
"""Unstructure an object used as an ID, tracking seen objects."""
def structure_uid(self, blob: dict[Any, str]) -> Any:
"""Structure an object used as an ID, can return the same object if it is duplicate."""
def unstructure_entity(self, entity: Entity) -> dict[Any, str]:
"""Unstructure a (world, uid) pair."""
def structure_entity(self, blob: dict[Any, str]) -> Entity:
"""Structure a (world, uid) pair."""
def unstructure_world(self, world: World) -> dict[Any, str]:
"""Unstructure a World instance."""
def structure_world(self, blob: dict[Any, str]) -> World:
"""Structure an object used as an ID, can return the same object if it is duplicate."""
def handle_tcod_ecs(converter: cattrs.Converter) -> None:
"""Configure a cattrs converter to support ECS instances."""
ecs_converter = _ECSConverter(converter) # Bind to converter
converter.register_unstructure_hook(World, ecs_converter.unstructure_world)
converter.register_structure_hook(World, ecs_converter.structure_world)
converter.register_unstructure_hook(Entity, ecs_converter.unstructure_entity)
converter.register_structure_hook(Entity, ecs_converter.structure_entity)
converter.register_unstructure_hook(Any, ecs_converter.unstructure_uid)
converter.register_structure_hook(Any, ecs_converter.structure_uid)
I think this solves the issue of how to handle when a world or uid is encountered multiple times.
from python-tcod-ecs.
My attempt to write a cattrs converter with #5 is officially a failure. It works, saves and loads without issues and handles cycles and whatever I throw at it, but the resulting format is huge mess that I don't want to support. It might be good for me to look at how other tools serialize this kind of system.
I vastly underestimated the complexity of unstructuring dictionaries with complex keys. Python does not like the keys being unstructured into unhashable dictionaries and even if I used frozendict some formats might not be able to handle serializing such keys.
cattrs
doesn't seem to have good support for cycles in general and adding such support is possible but very awkward. It isn't that kind of tool. I'm not sure of the best way to resolve this. The main issue other than cycles is that the world instance becomes a black box for all of the types it contains. You mentioned registering types which seems like the only real way to resolve that, though I still don't like that idea and it doesn't handle cycles.
I might try this again some time after I've become a lot more familiar with cattrs.
from python-tcod-ecs.
Related Issues (10)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from python-tcod-ecs.