[TransWarp] peak.binding questions

Ulrich Eck ueck at net-labs.de
Wed Jun 4 15:18:39 EDT 2003

thanks for your response.

I'll have to dive into zconfig first, i've looked at
the event-driven example but haven't really got it yet.
zconfig seems to be the long-term solution for what i
really want. in the mean time i'll follow your suggestions.

i'll be off for holiday for two weeks (6.6-23.6)
and i'm fairly busy the last few days .. so i'll 
probably report my experiences after my holiday.


Am Mit, 2003-06-04 um 20.09 schrieb Phillip J. Eby:
> At 06:55 PM 6/4/03 +0200, Ulrich Eck wrote:
> >Hi Phillip,
> >
> >while i have done lots of coding with peak during the last weeks
> >the following problem occured regularly and i don't know
> >how to "peak"ish solve it:
> >
> >- I have different Implementations of something (e.g.
> >   platform-dependent) i specify them in my package-ini:
> >
> >[some.property]
> >variantA = importString('some.path.to:A')
> >variantB = importString('some.path.to:B')
> >
> >- then i have some Component where i want to use *one*
> >   of those variants. i also specify the choice in some
> >   user-conf(ini) file:
> >
> >[main.config]
> >wichVariant = 'variantA'
> >
> >the user-conf file should be as easy as possible e.g. no
> >cryptic config.getProperty(propertyMap ........)
> The .ini format isn't intended for end-users; if complexity is an issue you 
> should be using ZConfig.
> ZConfig lets you create a very user-friendly configuration format.  In 
> essence, it's a friendly serialization of components.  Here's a possible 
> format:
> LdapURL       ldap://user:auth@server/base
> WhichVariant  variantA
> In the schema, you define a "data type" reference to a function that 
> converts an object with the above-named instance variables into your "real" 
> component.  Each field in a ZConfig file can define its own data type 
> converter as well.
> While this is a good bit more work to set up than an .ini format, it is far 
> more suitable for end users.
> >within the component i end up with once methods that do the
> >property lookups and create the instance by hand.
> >
> >is there an easier way to do this?
> Again, the answer is ZConfig.  What you'd do in a ZConfig schema for this 
> is define an "abstract section type" that essentially defines an interface 
> the "variant" components must support.  Then you define "concrete section 
> types" that "implement" the interface, and finally you define in a parent 
> schema the requirement for a section that implements the section type.
> Let's say you have an application with a top-level schema that contains 
> "LdapURL" and "WhichVariant" as its required items.  You create an abstract 
> section type, "Variant", and two concrete section types, VariantA and 
> VariantB.  In the concrete section types, you define the configuration 
> fields that each type needs (since A might have different fields than 
> B).  Each of the concrete section types will also have a different data 
> type: Variant A will specify 'some.path.to.A' and variant B will specify 
> 'some.path.to.B'.  (If they are binding.Components, you will probably 
> specify 'some.path.to.A.fromZConfig', etc.)
> In the top level schema, you will define a required section 'whichVariant', 
> that is to be of type 'Variant'.  Then, a user will do one of these two things:
> # Option 1
> LdapURL       ldap://user:auth@server/base
> <VariantA>
> # Variant-A specific parameters, if any
> </VariantA>
> OR
> # Option 2
> LdapURL       ldap://user:auth@server/base
> <VariantB>
> # Variant-B specific parameters, if any
> </VariantB>
> When the ZConfig file is processed, and the variant section is processed, 
> ZConfig will know what class to instantiate.  The resulting object will be 
> placed in the top-level "section" object, which will then be passed to the 
> top-level constructor.  If your top-level schema datatype is 
> 'some.path.to.MyApp.fromZConfig', then it will use a component constructor 
> that does a 'suggestParentComponent' to the variant component.
> So, what you end up with is an app object with all its configuration 
> components nicely specified, and they can be any object you've set up to be 
> available via the schema.  And, if you run 'peak zconfig.schema:myAppSchema 
> someZConfigFile', PEAK will launch your app for you as well.  If you have a 
> sitewide PEAK_CONFIG file, you can also add your schema URL to the 
> 'peak.running.shortcuts' property namespace, and be able to use a shortcut 
> like 'peak myapp configfile'.
> >same applies when i wanna configure some e.g. LDAPConnection:
> >
> >i want to specify it in a config-file:
> >
> >[main.config]
> >ldapurl = 'ldap://user:auth@server/base'
> >
> >but i cannot say:
> >
> >class MyDBComponent(binding.Base):
> >
> >     connection = \
> >          binding.bindTo(config.getProperty('main.config.ldapurl'))
> If you can make the URL a LinkRef, then:
>      binding.bindTo("config:main.config.ldapurl/")
> will do what you want.
> >if these situations could be solved without writing once-methods
> >my could would look much better.
> Ah.  Well, that's a different question than the one I've been 
> answering.  :)  ZConfig doesn't get rid of all of your indirection needs, 
> I'm afraid.  Typically, I use lambdas for simple things like this.  e.g.:
>      connection = binding.Once(lambda s,d,a: s.lookupComponent(s.ldapURL))
> You have made me realize, however, that a missing piece of functionality in 
> PEAK's current ZConfig support is the ability to resolve a naming system 
> name as part of assembling an app from a ZConfig file.  The problem is that 
> since ZConfig assembly is bottom-up, at the time ZConfig processes a 
> "name", the object parent doesn't exist yet.
> I'll have to give this one some thought.  One idea that comes to mind is 
> having 'lookupComponent()' follow 'naming.LinkRef' objects found as 
> attributes.  Then, any URL fields in a ZConfig schema could be defined with 
> a datatype of 'naming.LinkRef'.  Another thought is to create a special 
> LinkRef-like type that replaces itself with the lookup at assembly 
> time.  But that seems ugly.
> Of course, right now the framework allows you to override the 'fromZConfig' 
> method to do preprocessing like this.  I mostly intend to "wait and see" 
> what kind of overrides I end up commonly needing to do, before trying to 
> add more ZConfig hooks.  Still, having a way to do this for names would 
> probably be good.
> All in all, maybe the simplest thing to do is to have a 'bindIndirectlyVia' 
> function or something of that sort, e.g.:
> def bindIndirectlyVia(fromPath, *args, **kw):
>      return binding.Once(
>          lambda s,d,a: s.lookupComponent(s.lookupComponent(fromPath)),
>          *args, **kw
>      )
> Now, 'fromPath' could be a PropertyName, an attribute name, or even a URL, 
> and the result returned from would be used for the second lookup.  For use 
> with ZConfig, I would do something like:
>      connectionURL = binding.requireBinding('URL to connect to')
>      connection    = binding.bindIndirectlyVia('connectionURL')
> And then set up the ZConfig schema to set 'connectionURL' from the URL in 
> the configuration file.
> Notice that you can use this function yourself right now, without waiting 
> for me to add it, however.  :)  Perhaps you can let me know how using it 
> works out for you, so I can see if this is the "right thing to do" for 
> PEAK.  :)
> It probably needs two things to be "right", actually.  1. A clearer 
> name.  2. Experience with its use to see if one maybe needs to pass 
> additional arguments into either of the lookupComponent() calls.

Ulrich Eck
net-labs Systemhaus GmbH
Ebersberger Str. 46
85570 Markt Schwaben - Germany

eMail: ueck <at> net-labs.de
phone: +49 8121 4747 10
fax:   +49 8121 4747 77

More information about the PEAK mailing list