[PEAK] References between models

Phillip J. Eby pje at telecommunity.com
Thu Nov 13 16:28:36 EST 2003


At 09:37 PM 11/13/03 +0100, Radek Kanovsky wrote:

>I can make custom _getConfigData() method but this method will be
>module specific and it will not know about application that loaded
>it.

That's right.  Features must bind their target type at class definition time.


>Only if I declare some usage rules for applications. For example,
>'__main__' must contain ??app_specific_config?? that _getConfigData()
>method interprets some way.

It's even harder than that - you simply can't get from a singleton to a 
non-singleton, without depending on global configuration.  This is why I 
don't recommend anybody try it.  :)


>Then I can adapt modules somehow but only if I have one application
>per process. And this is problem because there must be possibility to
>run more separate applications in one process. Thats why I suggested
>ElementTemplate mechanism that has full access to standard configuration
>system. Element class itself is not needed at class level in any
>component (I mean no classmethod or classAttr computes anything from
>Element class). Element class is used only by binding.Component
>*instances* that have access to configuration subsystem. So why not
>delay Element class construction somehow?

You could always use adaptation for this.  Define a protocol that means 
"Class customized for this application".  Then, define sticky adapters that 
convert a class to its application-specific version.

This is a very complex thing to do, though.  It amounts to using adaptation 
to implement AOP, and I've only done a little investigation into it.  At 
some point, I'd actually like to replace module inheritance with 
adaptation-based AOP, but I have no time to look into it right now.



>ElementTemplate can cause one problem. Such template can occure in more
>than one place: as defaultElement in EntityDM, as formElement in some
>WebForm component. It must be some mechanism that will guarantee that
>``dm.defaultElement is wf.formElement'', because WebForm component can
>lookup DM by Element class.
>
>This leads me to the idea of some Element registry/manager. Every
>application can have its own registry or it can obtain default provider
>for IElementRegistry. Registry should be responsible for ElementTemplate
>substitution and for registering created elements under PropertyNames.
>It can be configurable in such way that I can state:
>
>   # Default ``mylib.contact.model.Contact'' provider
>   mylib.contact.model:Contact
>       implements PropertyName("mylib.contact.model.Contact")
>       for PropertyName("*")
>
>   # Special ``mylib.contact.model.Contact'' provider for some
>   # dark part of this application.
>   otherlib.kontakt.model:Kontakt
>       implements PropertyName("mylib.contact.model.Contact")
>       for PropertyName("crackerlib.invoice.*")
>
>
>Then binding.Component can ask: give me "mylib.contact.model.Contact",
>I am "crackerlib.invoice.storage.InvoiceDM". And it gets
>"otherlib.kontakt.model:Kontakt". Invoice element template can obtain
>"mylib.contact.model.Contact" or "mylib.employer.model.Person" for
>its features Invoice.subject or Invoice.responsible respectively.

Ah, but *who* does it ask, and how does it know that?  Individual Element 
instances can talk to their DM, but the *class* doesn't have any pointers 
to any components.  What's more, it can't.  The class is a singleton, just 
like a module.  So if it *has* such a pointer, that means it's once again 
unable to support more than one application per process, right?

Here's the thing, though.  referencedType isn't really used for much.  As 
long as the referencedType has reasonable mdl_defaultValue, mdl_normalize, 
and a few other such methods, it doesn't have to be the "real" referenced type.

So, if you just need "class replacement", you could do so pretty 
easily.  Note that binding.getComponentPath() works on element classes, so 
you could take that and do something like:

classProperty = PropertyName('.'.join(binding.getComponentPath(Contact)[1:]))

And then look up the property in some namespace, and voila, you have a 
class replacement mechanism.





More information about the PEAK mailing list