[PEAK] Config like metadata

Phillip J. Eby pje at telecommunity.com
Tue Dec 14 10:14:27 EST 2004


At 11:19 AM 12/14/04 +0100, Radek Kanovsky wrote:

>Current limitations:
>
>     * metadata registry is global and is not thread-safe
>     * works only with new-style classes for now
>     * it would be better to raise exception when metadata is not found
>       instead of returning NOT_FOUND (if default is not given)

Note that if the metadata registry were a generic function, it would solve 
all of these issues and use simpler code.  Instead of registering with a 
(metadata_class,target_class,attrName) tuple, add a method to a generic 
function with those parameters.  For a default rule, don't specify the 
target class.  For a wildcard rule, don't specify the attribute name.

Anyway, it would then immediately work for classic classes, and it would 
raise an exception (NoApplicableMethods) if the item was not found.  You 
would not need any of the search loops.  Since your MetaRule class has a 
'__call__' method, you can use MetaRule instances as methods of the generic 
function.  It would be something like:

     import dispatch
     from dispatch import strategy

     [dispatch.generic()]
     def get_metadata(kind, target_class, attrName):
         """Get metadata of 'kind' for target_class and attribute name"""


     class Metadata(object):

         def __init__(self,rule):
             if isinstance(rule,MetaRule):
                 self.rule = rule
             else:
                 self.rule = lambda kind,target_class,attrName: rule

         def register(self, subj, attrName=None):
             sig = strategy.Signature(
                 target_class = IsSubclass(subj),
                 kind = IsSubclass(self.__class__)
             )
             if attrName != '*':
                 sig &= strategy.Signature(
                     attrName=strategy.Inequality('==',attrName)
                 )
             get_metadata.addMethod(sig, self.rule)

         #... keep the old setDefault method, too

         [dispatch.as(classmethod)]
         def of(cls, subj, attrName=None, default=NOT_GIVEN):
             try:
                 return get_metadata(cls, subj, attrName)
             except dispatch.NoApplicableMethods:
                 if default is not NOT_GIVEN:
                     return default
                 raise

There you go.  You should be able to ditch the _metadata_registry class.

Btw, it's best not to import stuff from modules like 
peak.binding.attributes directly.  PEAK itself has to in order to avoid 
import circularity and early loading of APIs, but user code should always 
import from the API.




More information about the PEAK mailing list