[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.
Ulrich
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