[PEAK] References between models
Phillip J. Eby
pje at telecommunity.com
Thu Nov 13 12:09:38 EST 2003
At 05:14 PM 11/13/03 +0100, Radek Kanovsky wrote:
>Hi all,
>
>I am not sure how to solve this problem. There is following directory
>structure:
>
> mylib/: __init__.py
> mylib/contact/: __init__.py model.py storage.py ...
> mylib/invoice/: __init__.py model.py storage.py ...
> mylib/service/: __init__.py model.py storage.py ...
> ....
>
>`contact', `invoice', `service', etc. are components that contains
>Element definitions (model.py) and corresponding data managers
>(storage.py). Every component implements one aspect or problem
>and application is simply built (often) by assembling components
>together. But it is obvious that invoices must belong to some
>subject so there is reference to mylib.contact.model.Contact from
>mylib.invoice.model.Invoice:
>
> mylib/invoice/model.py:
>
> class Invoice (model.Element) :
> ...
> class contact (model.Attribute) :
> referencedType = mylib.contact.model.Contact
> ...
>
>And that is exactly what I don't like very much. There are for example
>15 components that have reference to mylib.contact.model.Contact. If
>there is need for replacing default mylib.contact.model.Contact with
>something slightly different, I need to repair 15 Elements in particular
>application only for this simple purpose.
>
>I am not sure where to aim my investigation. Elements don't support
>properties lookup and have restricted component lookup because they
>have no IConfigurationRoot among parents. What I am thinking of now is
>something as ElementTemplate with some substitution capabilities.
>Not finished yet, just idea:
Why not use constants, e.g.:
CONTACT = 'mylib/contact/model/Contact'
class Invoice...
...
class contact...
referencedType = CONTACT
If the problem is actually that you need to have variations of your
package(s) that replace certain classes, then using module inheritance (see
the API docs for peak.config.modules) may be the solution.
>Is this reasonable? Is there some other solution for such situations?
There's an easier way to do what you did. Note that configuration lookups
go by way of a '_getConfigData' method on a component. So, in your 'mylib'
package module, you could add:
protocols.advise(moduleProvides = [config.IConfigSource])
def _getConfigData(forObj,key):
# do something based on key, and return a value or NOT_FOUND
And once you've done this, you can use PropertyName() instances to link to
other elements.
This is sort of a hack, because peak.model.features checks for
isinstance(referencedType,str) and then does a lookup. I should change
this to instead adapt to an 'ITypeReference' interface, so that any
IConfigKey (such as interfaces, property names, etc.) can potentially be
used to access a type. But, that should be backward-compatible with the
hacky approach.
Note that one way you could implement your _getConfigData method is as follows:
protocols.advise(moduleProvides = [config.IConfigSource])
map = config.PropertyMap()
config.loadConfigFile(map, config.fileNearModule(__name__,'peak.ini'))
_getConfigData = map._getConfigData
del map
Now, you'll have a package-level configuration based on 'peak.ini' in the
package directory.
To everybody else: DON'T DO THIS UNLESS YOU UNDERSTAND THE
LIMITATIONS. This is *not* really configuration, despite what it looks
like. There's no real "configuration" because everything is a
constant. Obviously, whatever file you load is going to be a
constant. You might think, "well I could get something from the
environment, or...". Stop right there. Now you're *bypassing* the
configuration system, which is based on component context, not on globals.
Modules cannot have meaningful configuration because modules are
singletons. There is only one, so how can it be "configured"? It is what
it is, so it cannot be configured differently for different uses. This is
exactly why modules do not have a configuration root in PEAK, or by default
have any configuration mechanism. If you need to do something special like
what Radek is trying to do, you can use these hacks to have some
configuration, but it is ultimately a hack.
More information about the PEAK
mailing list