Skip to content
Snippets Groups Projects
Forked from atlas / athena
143645 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Configured.py 7.24 KiB
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration

# File: 
# Author: 

## for messaging
from AthenaCommon.Logging import logging
#log = logging.getLogger( 'Configured' )

# do not trace within ObjKeyStore 
from AthenaCommon.Include import excludeTracePattern
excludeTracePattern.append("*/RecExConfig/Configured*")

import traceback

### base class for fully configured algorithm and public tool ======
class Configured( object ):
   _nNewed = 0  
   _nInitialized = 0
   _disabled = False
   _configured = False
   _existingOutput = False   
   _ignoreExistingDataObject= False # if ignore existing data object
   _ignoreConfigError=False # if ignore python configuration error
   _output = {}


   def __new__ ( cls, *args, **kwargs ):

      cls._nNewed +=1
      mlog = logging.getLogger( 'Configured::__new__:%s:' % cls.__name__.replace( ".", '_' ) )
      if cls._nNewed ==1:
         mlog.debug("new : First instance" )
         cls.__newobject = object.__new__( cls )
      else:
         mlog.debug("new : nNewed : %s => simple access." % cls._nNewed )            
      
    

      return cls.__newobject


# constructor with optional argument
# optional argument should only be used to hack around an existing
# configuration, hence only if corresponding global variables are set
   def __init__( self, disable=False, ignoreExistingDataObject=False, ignoreConfigError=False ):
      mlog = logging.getLogger( 'Configured::__init__:%s:' % self.__class__.__name__.replace( ".", '_' )  )
      self._nInitialized +=1
      if self._nInitialized ==1:
         mlog.debug(" : First instance=>configure" )

      else:
         mlog.debug("already initialized : => simple access." )
         return



      from RecExConfig.RecConfFlags import recConfFlags
         
      self._ignoreExistingDataObject=ignoreExistingDataObject and recConfFlags.AllowIgnoreExistingDataObject()
      self._ignoreConfigError=ignoreConfigError and recConfFlags.AllowIgnoreConfigError()
         

      if disable and recConfFlags.AllowDisable :
         self._disabled=True
         mlog.info(" : Disabling" )
         return

      # initialisation
      self._configured = self.preconfigure() 
      doConfigure=False
      if not self._configured:
         mlog.debug("preconfiguration indicates this alg should not run")    
      else:   
         configuredOK = self.configure()
         if not configuredOK:
            mlog.error("configuration failed")    
 
      self._configured= self._configured and configuredOK

      mlog.info ("%s/%s" % (["Not configured","Configured"][self.configured()],
                            ["Enabled", "DISABLED"][self.disabled()]))


   def preconfigure (self):
      mlog = logging.getLogger( 'Configured::preconfigure:%s:' % self.__class__.__name__.replace( ".", '_' )  )
      mlog.debug("Output= %s" % self.output() )

      if self.checkExistingOutput ():
         return False
      
      return True

   def configure (self):
      mlog = logging.getLogger( 'Configured::configure:%s:' % self.__class__.__name__.replace( ".", '_' )  )
      mlog.info("Configured::configure not reimplemented ")
      return True


   def configured (self):
      return self._configured

   def disabled (self):
      return self._disabled

   def usable (self):
      mlog = logging.getLogger( 'Configured::usable:%s:' % self.__class__.__name__.replace( ".", '_' )  )      
      mlog.debug ("configured:%s disabled:%s" % (self.configured(),self.disabled()))
      return self.existingOutput() or ( self.configured() and not self.disabled() )


   def ignoreExistingDataObject (self):
      return self._ignoreExistingDataObject

   def ignoreConfigError (self):
      return self._ignoreConfigError

   def output (self):
      return self._output

   def existingOutput (self):
      return self._existingOutput

   def checkExistingOutput (self):
      
# check wether output is already in objKeyStore.
# If yes, unless ignore explicitly, return true
# If multiple output, all type/key should be present

      from RecExConfig.ObjKeyStore import objKeyStore

      mlog = logging.getLogger( 'Configured::existingOutput:%s:' % self.__class__.__name__.replace( ".", '_' )  )
      oneMatch=False
      oneUnmatch=False
      for atype in self.output().keys():
         allkeys=self.output()[atype]
         if type(allkeys) != type([]): allkeys    = [allkeys]
         for akey in allkeys:
            if objKeyStore.isInInput(atype,akey):
               oneMatch=True
            else:
               mlog.info('one object not in output %s:%s' % (atype,akey))
               oneUnmatch=True            


      if oneMatch and not oneUnmatch:         
         if self.ignoreExistingDataObject():
            mlog.info("Output objects already available. Continue nevertheless")
         else:
            mlog.info("Output objects already available. Do nothing")
            self._existingOutput=True
            return True

      elif oneMatch and oneUnmatch:               
         mlog.info("Some, not all, output objects already available. Continue nevertheless")
         # mlog.info("Some, not all, output objects already available. Do nothing")
         # self._existingOutput=True
         # return True

      else:
         mlog.info("No output objects already available. Continue.")      
      self._existingOutput=False
      return False   
      

   # Helper to retrieve a Getter for an input to this object.
   # IGPATH is the name of the Getter class; should be a name
   # of the form "MODULE.NAME".  Returns the Getter object
   # or None.
   def getInputGetterClass (self, igpath):
        # Make a logger.
        clsname = self.__class__.__name__.replace( ".", '_' ) 
        mlog = logging.getLogger('%s:getInputGetter' % clsname)

        # Find the input getter.
        try:
            (ig_modname, ig_name) = igpath.rsplit ('.', 1)
            ig_mod = __import__ (ig_modname, globals(), locals(), [ig_name])
            ig_cls = getattr (ig_mod, ig_name)
        except:
            mlog.error("could not get handle to %s Quit" % igpath)
            print traceback.format_exc()
            return None
        return ig_cls
     
   # Helper to retrieve a Getter for an input to this object.
   # IGPATH is the name of the Getter class; should be a name
   # of the form "MODULE.NAME".  Returns the Getter object
   # or None.
   #
   # If the input is not a string, it is just returned directly.
   def getInputGetter (self, igpath):
        if type(igpath) != type(''):
           return igpath
        
        # Make a logger.
        clsname = self.__class__.__name__.replace( ".", '_' ) 
        mlog = logging.getLogger('%s:getInputGetter' % clsname)

        # Find the input getter.
        try:
            ig_cls = self.getInputGetterClass(igpath)
            if ig_cls == None: return None
            input_getter = ig_cls()
        except:
            mlog.error("could not get handle to %s Quit" % igpath)
            print traceback.format_exc()
            return None

        if not input_getter.usable():
            ig_name = ig_cls.__name__
            if not self.ignoreConfigError():
                mlog.error("%s unusable. Quit." % ig_name)
                return None
            else:
                mlog.error("%s unusable. Continue nevertheless" % ig_name)

        return input_getter