Last active
October 26, 2018 17:27
-
-
Save luca-penasa/89e3ad12ca80d597e0cf14a0a0cff06c to your computer and use it in GitHub Desktop.
variables_proof_concept
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 enum import Enum | |
| import attr | |
| class VarType(Enum): | |
| VAR = "var" | |
| REF = "ref" | |
| from copy import copy | |
| def ref_to_ref_obj_attr_name(varname): | |
| return varname + "_referenced_obj" | |
| def get_nested_attribute(obj, path): | |
| toget = path.split(".") | |
| cur_obj = obj | |
| for att in toget[:-1]: | |
| try: | |
| cur_obj=getattr(cur_obj, att) | |
| except: | |
| raise (ValueError(f"cannot fing required arg {att}")) | |
| return getattr(cur_obj, toget[-1]) | |
| def set_nested_attribute(obj, path, value): | |
| toget = path.split(".") | |
| cur_obj = obj | |
| for att in toget[:-1]: | |
| print(f"getting {att}") | |
| try: | |
| cur_obj=getattr(cur_obj, att) | |
| except: | |
| raise (ValueError(f"cannot fing required arg {att}")) | |
| print(f"setting {att} of {cur_obj} to {value}") | |
| setattr(cur_obj, toget[-1], value) | |
| def make_property_for_var_ref(var): | |
| def set_from_store(self, value): | |
| attname = ref_to_ref_obj_attr_name(var.name) | |
| ref_obj = getattr(self, attname) | |
| if not ref_obj: | |
| raise(KeyError("you are trying to write to a reference variable, but the instance is missing")) | |
| set_nested_attribute(ref_obj, var.metadata["attribute"], value) | |
| def get_from_store(self): | |
| attname = ref_to_ref_obj_attr_name(var.name) | |
| ref_obj = getattr(self, attname) | |
| if not ref_obj: | |
| raise(KeyError("you are trying to read from a reference variable, but the instance is missing")) | |
| return get_nested_attribute(ref_obj, var.metadata["attribute"]) | |
| prop = property (fget=get_from_store, fset=set_from_store, doc=var.metadata["doc"]) | |
| return prop | |
| def attrify(cls): | |
| cc = attr.attrs(cls, slots=False) | |
| for var in cc.__attrs_attrs__: | |
| if var.metadata["var_type"] == VarType.REF: | |
| varname = var.name | |
| newatt = ref_to_ref_obj_attr_name(varname) | |
| setattr(cc, newatt, None) | |
| # if it is a reference we build an ad-hoc accessor trhough property | |
| # if not we could use the store if we really need to. | |
| prop = make_property_for_var_ref(var) | |
| setattr(cc, var.name, prop) | |
| return cc | |
| def provide(doc="", default=None): | |
| metadata = {"var_type": VarType.VAR, | |
| "doc" : doc} | |
| return attr.ib(init=True, default=default, metadata=metadata) | |
| def reference(parent_cls, attr_name, doc="imported from..."): | |
| metadata = {"var_type": VarType.REF, | |
| "parent_cls" : parent_cls, | |
| "attribute": attr_name, | |
| "doc":doc} | |
| return attr.ib(init=False, metadata=metadata) | |
| @attrify | |
| class ClassOne(object): | |
| avar1 = provide(default=24, doc="variable n1" ) | |
| avar2 = provide(default=14, doc="variable n2" ) | |
| @attrify | |
| class ClassTwo(object): | |
| number1 = provide(default=24.23, doc="variable named t") | |
| number2 = provide(default=ClassOne(), doc="variable named z") | |
| @attrify | |
| class ClassThree(object): | |
| avar1 = reference(ClassTwo, "number2.avar2") | |
| number1 = reference(ClassTwo, "number1") | |
| tw = ClassTwo(9) | |
| c = ClassThree() | |
| # this must be made from the Model instance. to set the right instance | |
| c.avar1_referenced_obj = tw # the class should also check wheter this is of the right type | |
| c.number1_referenced_obj = tw | |
| tw.number1 = 2093 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment