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

Reply via email to