Created
April 1, 2022 18:31
-
-
Save strikaco/fd235c5cbb872ee599671cb2cb80af46 to your computer and use it in GitHub Desktop.
Python - Component dataclasses as class properties
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from dataclasses import dataclass, field, fields, replace, asdict | |
| _MISSING = object() | |
| @dataclass | |
| class Component(object): | |
| """ | |
| Collection of attributes. | |
| """ | |
| _key: str = field(default=None, hash=False, repr=False, compare=False) | |
| _entity:object = field(default=None, hash=False, repr=False, compare=False) | |
| autosave:bool = field(default=False, hash=False, repr=False, compare=False) | |
| def __set_name__(self, owner, name): | |
| self._key = name | |
| def __get__(self, instance, owner): | |
| # Try getting existing component object | |
| obj = getattr(instance.ndb, self._key, _MISSING) | |
| if obj and isinstance(obj, self.__class__): | |
| return obj | |
| # Try getting data from db | |
| data = getattr(instance.db, self._key, {}) | |
| # Create and save new object to ndb | |
| obj = replace(self, _entity=instance, **data) | |
| setattr(instance.ndb, self._key, obj) | |
| return obj | |
| def __setattr__(self, key, value): | |
| super().__setattr__(key, value) | |
| if self.autosave: self.save() | |
| def save(self): | |
| base_fields = tuple(f.name for f in fields(Component)) | |
| data = {k:v for k,v in asdict(self).items() if k not in base_fields} | |
| setattr(self._entity.db, self._key, data) | |
| @dataclass | |
| class Geometry(Component): | |
| height:float = 0.0 | |
| width:float = 0.0 | |
| depth:float = 0.0 | |
| class DB(object): pass | |
| class Object(object): | |
| geom = Geometry(depth=16) | |
| def __init__(self): | |
| self.db = DB() | |
| self.ndb = DB() | |
| o = Object() | |
| o.geom.height = 5.0 | |
| print(o, o.geom, o.geom.height) | |
| o.geom.save() | |
| print(o.db.geom) | |
| o3 = Object() | |
| print(o3.geom) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment