Hi, Phillip
That plan looks highly sensible and good. I'm available for feedback/
help (especially with the rearchitecture branch changes) if need be.
--Grant
On 8 Apr, 2008, at 19:47, Phillip J. Eby wrote:
So, at this point, I have a mostly-baked implementation of the new
Trellis API, minus laziness and connect/disconnect support. It's
working side by side with the old API, but I haven't checked it in
yet.
Here's what I'm planning to do, more or less in order:
* add laziness and verify that 'compute' rules do not write anything
* add deprecation warnings for the old API
* check in the changed code
* port the Chandler "rearchitecture" branch code to use the new API
* write a porting guide for others to use
* update the Trellis tutorial to reflect the changes
* issue an interim release (0.7a1?) and encourage everyone to move
to the new API (since code using the old API will be spewing warnings)
* add connect/disconnect support
* drop support for the old API
* issue a new release (0.7a2?) with connector support and without
the old API
* Start experimenting with using the new connector stuff for
functional GUI integration, and resume experimenting with SQLAlchemy
integration.
Basically, this means that fairly soon you will start getting
deprecation warnings if you're working from an SVN version of
Trellis, and until I get a porting guide together, you're going to
have to look to the changes I've made in SVN as a guide. Here's a
quick-and-dirty reference for your convenience:
variable(initially=NO_VALUE, resetting_to=NO_VALUE):
* value(X) -> variable(initially=X)
* receiver(X) -> variable(resetting_to=X)
variable.attributes(**):
* values(**) -> variable.attributes(**)
variable.attributes.resetting_to(**):
* receivers(**) -> variable.attributes.resetting_to(**)
perform(rule=None, optional=False):
* observer(X) -> perform(X)
* @observer X -> @perform X
* @optional @observer X -> @perform(optional=True) X
Those are the easy translations, because they're 1:1. For existing
uses of 'rule', 'discrete', and 'optional', it's a bit tougher,
because they will become either 'compute' or 'maintain', depending
on the context.
If you have a rule with no side-effects, you should use 'compute',
and if your rule has side-effects, you should use 'maintain':
compute(rule=None, initially=NO_VALUE, resetting_to=NO_VALUE,
writable=False):
maintain(rule=None, initially=NO_VALUE, resetting_to=NO_VALUE,
optional=False):
'compute' rules are always optional (i.e., not activated until
needed), and 'maintain' rules are always writable (i.e., the
attribute can be set). Both APIs can use 'initially' or
'resetting_to' in order to set an initial value or make the rule
discrete (i.e., automatically resetting after a change).
If you don't pass in a rule, the API acts as a decorator, and can be
used as in these examples:
@trellis.compute
def some_rule(self):
...
@trellis.maintain(initially=42):
def another_rule(self):
...
some_attr = trellis.compute(lambda self: {})
etc.
'compute' rules will be lazily recomputed, in that they will not be
re-run unless some other rule is actively subscribed to its output.
(Attempting to read the rule's value will trigger recalculation if
the value is out of date, however.) This, combined with the lazy
initialization of compute rules, means that compute rules will be of
generally lower overhead than 'maintain' rules, which must always be
re-run when a dependency changes (because the rule might have side-
effects).
To replace the 'rules()' API, there will be two new variations:
compute.attributes(**)
maintain.attributes(**)
Note also that in the past, you could combine rules() and values()
definitions for the same attribute, but that will not be possible
with the new API. A given attribute now has to be defined in
exactly one place. If you were previously defining both a rule and
value for an attribute, you will need to either use
maintain(initially=val), or compute(initially=val, writable=True) to
define the rule.
Inheritance of attribute metadata has also changed; instead of
querying metadata registries, you can simply refer to
'SomeBaseClass.some_attr.rule' to retrieve the rule for 'some_attr'
in SomeBaseClass'.
At this point, this is a very early draft, and it's possible that
during the remaining porting of the tests and the Chandler rearch
branch I'll want to tweak these APIs in some way. This is just a
snapshot based on what I have in my local checkout right now.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Open Source Applications Foundation "chandler-dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/chandler-dev
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Open Source Applications Foundation "chandler-dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/chandler-dev