This might sound confusing, but in fact it solves a real problem and
saves quite a lot of code in many cases. For example:
class EnabledMixin(Model):
attrs(
_enabled=True,
_parent_enabled=True,
)
@compute(write_to='_enabled')
def enabled(self):
return self._parent_enabled and self._enabled
It also saves the programmer from some obscure errors, for example:
class Task1(Component):
attrs(start=1, length=2)
@compute(write_to='_end_write')
def end(self):
return self.start + self.length
@attr.writer
def _end_write(self, end):
self.start = end - self.length
t1 = Task1()
with ctrl.new_txn():
t1.end = 20
# _end_write didn't run yet, so it will see the next change too
t1.length = 10
# still didn't run -- it's a rule, so it will run later
assert t1.start == 1
assert t1.start == 10
assert t1.end == 20
assert t1.length == 10
if _end_write was not a rule, things wouldn't work out, we'd get
(t1.start, t1.end) == (18,28)
--
Best Regards,
Sergey Schetinin
http://s3bk.com/ -- S3 Backup
http://word-to-html.com/ -- Word to HTML Converter