Skip to content

Instantly share code, notes, and snippets.

@luca-penasa
Last active October 26, 2018 17:27
Show Gist options
  • Save luca-penasa/89e3ad12ca80d597e0cf14a0a0cff06c to your computer and use it in GitHub Desktop.
Save luca-penasa/89e3ad12ca80d597e0cf14a0a0cff06c to your computer and use it in GitHub Desktop.
variables_proof_concept
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