| # Gaudi Framework, version v20r4
Generated: 8 Jan 2009

# ConfigurableMeta.py

Go to the documentation of this file.

    00001 # File: AthenaCommon/python/ConfigurableMeta.py
    00002 # Author: Wim Lavrijsen (WLavrijsen@lbl.gov)
    00003
    00004 import GaudiKernel.PropertyProxy as PropertyProxy
    00005
    00006
    00007 ### data
    00008 __version__ = '1.0.1'
    00009 __author__  = 'Wim Lavrijsen (WLavrijsen@lbl.gov)'
    00010
    00011 __all__ = [ 'ConfigurableMeta' ]
    00012
    00013 ### this metaclass installs PropertyProxy descriptors for Gaudi properties
    00014 class ConfigurableMeta( type ):
    00015    """The setting of Gaudi component properties needs to be deferred and
    00016       history of who set what where needs to be collected. This is done
    00017       by using PropertyProxy descriptors rather than the default ones."""
    00018
    00019    def __new__( self, name, bases, dct ):
    00020     # enfore use of classmethod for getType() and setDefaults()
    00021       if 'getType' in dct and not isinstance( dct[ 'getType' ], classmethod ):
    00022          dct[ 'getType' ] = classmethod( dct[ 'getType' ] )
    00023
    00024       if 'setDefaults' in dct and not isinstance( dct[ 'setDefaults' ], classmethod ):
    00025          dct[ 'setDefaults' ] = classmethod( dct[ 'setDefaults' ] )
    00026
    00027     # collect what are properties (basically, any public name; C++ variables
    00028     # shouldn't start with an '_' because of portability constraints, hence
    00029     # it is safe to assume that any such vars are python private ones)
    00030       newclass = type.__new__( self, name, bases, dct )
    00031
    00032     # cache references of instances by name for duplicate removal
    00033       newclass.configurables = {}
    00034
    00035     # loop over slots, which are all assumed to be properties, create proxies, defaults
    00036       properties = {}
    00037       slots = dct.get( '__slots__' )
    00038       if slots:
    00039          props = [ x for x in slots if x[0] != '_' ]
    00040          propDict = dct.get('_propertyDocDct')
    00041          for prop in props:
    00042             docString = propDict and propDict.get(prop)
    00043             if type(slots) == dict:
    00044                default = slots[prop]
    00045             else:
    00046                default = None
    00047             proxy = PropertyProxy.PropertyProxyFactory( getattr( newclass, prop ), docString, default )
    00048
    00049             properties[ prop ] = proxy
    00050             setattr( newclass, prop, proxy )
    00051
    00052     # complete set of properties includes those from base classes
    00053       for base in bases:
    00054          try:
    00055             bprops = base._properties.copy()
    00056             bprops.update( properties )
    00057             properties = bprops
    00058          except AttributeError:
    00059             pass
    00060
    00061       newclass._properties = properties
    00062
    00063       return newclass
    00064
    00065    def __call__( cls, *args, **kwargs ):
    00066       """To Gaudi, any object with the same type/name is the same object. Hence,
    00067          this is mimicked in the configuration: instantiating a new Configurable
    00068          of a type with the same name will return the same instance."""
    00069
    00070     # Get the instance: `singleton' logic needs to be in __new__, not here,
    00071     # for compatibililty with pickling.)
    00072       cfg = cls.__new__( cls, *args, **kwargs )
    00073
    00074     # Initialize the object, if not done already.
    00075       if not hasattr(cfg, '_initok') or not cfg._initok:
    00076          cls.__init__( cfg, *args, **kwargs )
    00077
    00078       return cfg