The PEAK Developers' Center   Diff for "ComposingHierarchies" UserPreferences
 
HelpContents Search Diffs Info Edit Subscribe XML Print View
Ignore changes in the amount of whitespace

Differences between version dated 2003-07-15 15:18:29 and 2005-05-12 08:35:35 (spanning 9 versions)

Deletions are marked like this.
Additions are marked like this.

The purpose of this page is to give a quick overview of how to compose component hierarchies using the PEAK framework, using working code. I have inlined comments in the code example, so hopefully, it will be self explanatory.
 
== Code ==
Here's the code example that I came up with while working out how to compose hiearchies, and "aquire" objects from parent components in PEAK.
Here's the code example that I came up with while working out how to compose hierarchies, and "aquire" objects from parent components in PEAK. It requires the current CVS version of PEAK (0.5a3).
 
{{{
#!python
#file components1.py
from peak.api import *
from peak.interface import Interface, Attribute
 
SPAM_PROPERTY = PropertyName("simplecmpApp.spam")
COLOR_PROPERTY = PropertyName("simplecmpApp.color")
EGGS_PROPERTY = PropertyName("simplecmpApp.eggs")
 
 
#------------------------------------------------------------
class ISpam(Interface):
class ISpam(protocols.Interface):
    """Spam interface"""
    def spam():
        """provide spam"""
        
class Spam(binding.Component):
    protocols.advise(instancesProvide=[ISpam,],)
    protocols.advise(instancesProvide=[ISpam])
    def spam(self):
        return "spam"
 
#------------------------------------------------------------
class IEggs(Interface):
class IEggs(protocols.Interface):
    """Eggs interface"""
    def eggs():
        """provide eggs"""
 
class Eggs(binding.Component):
    protocols.advise(instancesProvide=[IEggs,],)
    protocols.advise(instancesProvide=[IEggs])
    def eggs(self):
        return "eggs"
 
class OtherEggs(binding.Component):
    protocols.advise(instancesProvide=[IEggs,],)
    protocols.advise(instancesProvide=[IEggs])
    def eggs(self):
        return "othereggs"
 

#------------------------------------------------------------
class GrandChildCmp(binding.Component):
    #acquired from SimpleCmp
    gcSpam = binding.bindToProperty("simplecmpApp.spam")
    gcColor = binding.bindToProperty("simplecmpApp.color")
    gcEggs = binding.bindToProperty("simplecmpApp.eggs")
    gcSpam = binding.Obtain(SPAM_PROPERTY)
    gcColor = binding.Obtain(COLOR_PROPERTY)
    gcEggs = binding.Obtain(EGGS_PROPERTY)
    #acquired from ChildCmp
    gcOtherEggs = binding.bindTo(IEggs)
    gcOtherEggs = binding.Obtain(IEggs)
    #acquired from SimpleCmp
    gcStr = binding.bindTo("sc_string")
    gcStr = binding.Obtain("sc_string")
    
class ChildCmp(binding.Component):
    #acquired from SimpleCmp
    cEggs = binding.bindTo(IEggs)
    cSpam = binding.bindTo(ISpam)
    cStr = binding.bindTo("sc_string")
    cSpam = binding.Obtain(ISpam)
    cStr = binding.Obtain("sc_string")
    #overrides IEggs provided by SimpleCmp
    __eggs = binding.New(OtherEggs, offerAs=[IEggs])
 
    cEggs = binding.Obtain(IEggs)
    __eggs = binding.Make(OtherEggs, offerAs=[IEggs])
    
    #make a GrandChild child of this component
    grandChild = binding.New(GrandChildCmp)
    grandChild = binding.Make(GrandChildCmp)
 
class SimpleCmp(binding.Component):
    #simple component variable. Child components can look up directly by name
    sc_string = "simple-c!"
    #__eggs and __spam are registered as Interfaces and properties
    #They can be bound either using binding.bindTo(<InterfaceName>)
    #or binding.bindToProperty(<property.name>)
    __eggs = binding.New(Eggs, offerAs=[IEggs, PropertyName("simplecmpApp.eggs")])
    __spam = binding.New(Spam, offerAs=[ISpam, PropertyName("simplecmpApp.spam")])
    #They can be bound either using binding.Obtain(<InterfaceName>)
    #or binding.Obtain(PropertyName(<property.name>))
    __eggs = binding.Make(Eggs, offerAs=[IEggs, EGGS_PROPERTY])
    __spam = binding.Make(Spam, offerAs=[ISpam, SPAM_PROPERTY])
    #__color is a Constant bound to a property
    __color = binding.Constant(value="red", offerAs=["simplecmpApp.color"])
    __color = binding.Make(lambda:"red", offerAs=[COLOR_PROPERTY])
    
    #make a ChildCmp child of this component
    child = binding.New(ChildCmp)
    child = binding.Make(ChildCmp)
    
#------------------------------------------------------------
if __name__ == "__main__":

 
 
    print "c.eggs: ",c.cEggs.eggs()
    print "c.eggs: ",c.cSpam.spam()
    print "c.spam: ",c.cSpam.spam()
    print "c.cStr: ",c.cStr
    print "gc.spam: ",gc.gcSpam.spam()
    print "gc.eggs: ",gc.gcEggs.eggs()

    print "gc.myColor: ",gc.gcColor
    print "gc.gcStr: ",gc.gcStr
    print "done"
 
}}}
 
 

{{{
[joel@banzai playground1]$ python components1.py
c.eggs: othereggs
c.eggs: spam
c.spam: spam
c.cStr: simple-c!
gc.spam: spam
gc.eggs: eggs

 
 
--Joel Boehland
 
= Discussion =
 
So, it seems to me:
 
{{{
#!python
class SimpleCmp(binding.Component):
    __eggs = binding.Make(Eggs, offerAs=[IEggs, EGGS_PROPERTY])
}}}
 
This means: "When you make a SimpleCmp, it has within it a variable __eggs. __eggs is an Eggs. When someone asks for the SimpleCmp's IEggs interface, patch it through to my internal __eggs. And when they ask for the SimpleCmp's EGGS_PROPERTY, also patch them through to my internal __eggs."
 
It also seems that: If a component has another component within it, that if the child component requests an interface, it firsts check ''locally'' for it, and if it's not found locally, it checks it's ''parent'' for it. And if not there, still higher up the chain (grandparent.)
 
Am I understanding right?
 
Next, I naturally wonder: "What for? What kinds of things do you get from this?" I'm not saying there isn't, I'm just not used to thinking this way. I'd like to get excited about it, by understanding what it can do for me.
 
-- LionKimbro [[DateTime(2005-04-17T13:58:41)]]
 
I think it is done to have a flexible InversionOfControl mechanism. That is the wiring between elements is made "magicaly". It's very flexible since you can change a piece with another without worrying to change the code of objects using it or an object doesn't have to know which object uses it.
 
-- AlexG [[DateTime(2005-05-12T14:30:00)]]

PythonPowered
ShowText of this page
EditText of this page
FindPage by browsing, title search , text search or an index
Or try one of these actions: AttachFile, DeletePage, LikePages, LocalSiteMap, SpellCheck