Skip to content

Instantly share code, notes, and snippets.

@Halicea
Last active August 29, 2015 14:10
Show Gist options
  • Save Halicea/4946ba5a271073db4c5b to your computer and use it in GitHub Desktop.
Save Halicea/4946ba5a271073db4c5b to your computer and use it in GitHub Desktop.
from __future__ import print_function
from atom.catom import DefaultValue
from atom.api import (Atom, Signal, Instance, ForwardInstance, Bool, Value,
List, Str, set_default)
from .core import X4CDefinition, X4CObject, ROOT_DEFINITION
from .types import Type
class Formula(Atom):
_exp = Str(default='')
interpreter = Value()
eval_method = Value()
@property
def exp(self):
return self._exp
@exp.setter
def exp(self, value):
self._exp = value
self.eval_method = lambda context: self.interpreter.eval(
value,
context=context)
def eval(self, context):
return self.eval_method(context)
class Property(X4CObject):
_value = Value()
_formula = Instance(Formula)
@property
def IsFormula(self):
return self._value.startswith('=') # self._formula is not None
definition = ForwardInstance(lambda: PropertyDefinition)
def __init__(self, definition):
super(Property, self).__init__(definition)
m_value = self.get_member('_value')
m_value.set_default_value_mode(DefaultValue.CallObject,
lambda: self.definition.default)
def __getstate__(self):
state = super(Property, self).__getstate__()
if 'changed' in state:
del state['changed']
if '_value' in state:
del state['_value']
state['value'] = self.definition.type.format(self._value, 'getstate')
return state
def __setstate__(self, state, repo):
for name, member in self.members().items():
if isinstance(member, Signal) or name.startswith("_"):
continue
try:
if name in state:
setattr(self, name, state[name])
except TypeError:
pass
if 'value' in state:
self.value = state['value']
def __getattr__(self, name):
if name in self.definition.type.actions:
return getattr(self.definition.type, name)
else:
raise AttributeError("Action not found")
@property
def actions(self):
return self.definition.type.actions
@property
def value(self):
raw_value = self._value
if self._value is None:
raw_value = self.definition.default
if self.IsFormula:
raw_value = self._formula.eval(self.context)
else:
raw_value = self._value
return self.definition.type.format(raw_value)
@value.setter
def value(self, value):
# if value.startswith('='):
# _formula.build(value)
if self.validate(value):
# FIXME: use formulas too
self._value = self.definition.type.setter(value)
self.changed(self, value)
else:
raise ValueError("Invalid value '{}'".format(value))
def __repr__(self):
return '$pr{}:{}'.format(self.definition.name, self.value)
def __str__(self):
return self.__repr__()
class PropertyDefinition(X4CDefinition):
# FIXME: support value & unit
parent = set_default(ROOT_DEFINITION)
defines_class = set_default(Property)
default = Value()
is_formula = Bool(False)
type = Instance(Type)
constraints = List()
def __init__(self, name, x4c_type=Type, *args, **kwargs):
super(PropertyDefinition, self).__init__(name, **kwargs)
m_default = self.get_member('default')
m_default.set_default_value_mode(DefaultValue.CallObject,
lambda: self.type.default)
try:
if callable(x4c_type):
self.type = x4c_type()
else:
self.type = x4c_type
except Exception:
raise ValueError("Invalid x4c_type")
def __setstate__(self, slots, repo):
super(PropertyDefinition, self).__setstate__(slots, repo)
self.default = slots['default']
self.is_formula = slots['is_formula']
self.type = repo.get(slots['type'])
self.constraints = repo.get_all(slots['constraints'])
def clone(self, name):
return PropertyDefinition(name=name, x4c_type=self.type, parent=self)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment