History for FeatureWeaving
??changed:
-
The "FeatureWeaving" Interface
To be a valid FeatureDef object, your class must define the following methods (and include the 'TW.Features.FeatureWeaving' Interface in its '__implements__' attribute). See the section on WeavingTime for the "big picture" of how these methods are used to assemble aspects into a component.
weaveFeature(self,name,item,maker,verticalContext)
Notification that a feature needs weaving.
* name -- the name of the feature to be woven
* item -- the object bound to 'name' in the current source aspect layer
* maker -- the ComponentMaker doing the weaving
* verticalContext -- a function which returns the name of its argument
in the source aspect layer, or the argument itself if it is not found.
This message is sent when a FeatureDef is first detected (or defaulted)
during weaving. If your FeatureDef wants to be called in every
subsequent layer when an attribute named 'name' is present, and at
"finishing" time, it should install itself in the feature registry
by executing::
maker.features[name] = self
If you do not do this, the weaveFeature() message will be the only one
your FeatureDef receives.
finishFeature(self,name,maker)
Last chance to affect the generated component.
* name -- the name of the feature
* maker -- the ComponentMaker doing the weaving
This message is sent during the "finishing" phase of component construction, to all !FeatureDefs which have registered themselves with the ComponentMaker.
localDependencies(self,name,maker)
Return the names of other features this feature depends on.
* name -- the name of the feature
* maker -- the ComponentMaker doing the weaving
Return: a sequence of names of features that must be finished before
this feature is finished.
This method is called by the ComponentMaker to build a dependency graph
during the "finishing" phase. Features are "finished" in order based on
their local dependencies (i.e., order between attributes of the same
class).
globalDependencies(self,name,maker)
Return dependencies on features in the next outer class.
* name -- the name of the feature
* maker -- the ComponentMaker doing the weaving
This method is used by certain features (notably the standard
ClassFeature) to calculate their localDependencies. It is not called
by !ComponentMakers directly. This method is required to exist so that
features which create an instance of a class that's being woven, can
force their containing class to be "finished" after the class that the
feature wishes to instantiate. For example::
class DiceService(Aspect):
class RandomValueFeature:
def __init__(self,lo,hi):
self.lo = lo
self.hi = hi
def next(self):
print "Rolling from",self.lo,"to",self.hi
return randint(self.lo,self.hi)
class DiceElement:
diceValue = FeatureExpression('RandomValueFeature(1,6)')
def roll(self):
return self.diceValue.next()
When the ComponentMaker asks the ClassFeature responsible for the
!DiceElement class what its localDependencies are, it will check the
globalDependencies() of its contained features. Meanwhile, the
FeatureExpression class has a globalDependencies() method that will
return the tuple '("RandomValueFeature",)'. Thus, the dependency
graph for the classes will reflect !DiceElement's dependency on
!RandomValueFeature, and they will be created in the right order at
WeavingTime.
XXX This would probably be a good place for a UML interaction diagram...