Coder Social home page Coder Social logo

`cattrs` support about python-tcod-ecs HOT 4 OPEN

hexdecimal avatar hexdecimal commented on June 16, 2024
`cattrs` support

from python-tcod-ecs.

Comments (4)

HexDecimal avatar HexDecimal commented on June 16, 2024

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.

slavfox avatar slavfox commented on June 16, 2024

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.

HexDecimal avatar HexDecimal commented on June 16, 2024

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.

HexDecimal avatar HexDecimal commented on June 16, 2024

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 photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.