Skip to content
Snippets Groups Projects
Commit 69338c2f authored by Teng Jian Khoo's avatar Teng Jian Khoo Committed by Adam Edward Barton
Browse files

Define (in)equality operations for Configurable

parent 66365f88
No related branches found
No related tags found
No related merge requests found
......@@ -754,6 +754,58 @@ class Configurable( object ):
self._flags &= ~self._fIsPrinting
return rep
# hash method for set/dict operations
# first attempt, assuming need to recurse into child properties
# if too much overhead, could attempt to cache with python
# properties, but hard to propagate changes upwards to parents
def getFlattenedProperties(self):
self._flags |= self._fIsPrinting
properties = self.getValuedProperties()
propstr = ""
for key,val in sorted(properties.iteritems()):
if isinstance(val,GaudiHandles.PublicToolHandle) or isinstance(val,GaudiHandles.PrivateToolHandle):
propstr += val.getFullName()
elif isinstance(val,Configurable):
propstr += "({0}:{1})".format(key,val.getFlattenedProperties())
elif isinstance(val,GaudiHandles.PublicToolHandleArray) or isinstance(val,GaudiHandles.PrivateToolHandleArray):
for th in val:
# Handle ToolHandles that have just been set as strings(?)
if isinstance(th,Configurable):
propstr += "({0}:{1}".format(th.getFullName(), th.getFlattenedProperties())
else:
propstr += th.getFullName()
else:
propstr += "({0}:{1})".format(key,str(val))
self._flags &= ~self._fIsPrinting
return propstr
def getStrDescriptor(self):
descr = ""
if hasattr( self,"_name" ):
propstr = self.getFlattenedProperties()
descr = (self.getFullName(), propstr)
else: # Not yet initialised?
descr = self.getType()
return descr
# # (in)equality operators, based on hash
def __eq__(self,rhs):
# Check identity first
if self is rhs: return True
# Avoid comparing against None...
if not rhs: return False
# Class check
if not isinstance(rhs,Configurable): return False
# Type/Name check
if self.getFullName() != rhs.getFullName(): return False
# If identical types and names, then go the whole hog and test children
# Could be sped up by testing property by property...
return self.getStrDescriptor() == rhs.getStrDescriptor()
def __ne__(self,rhs):
return (not self.__eq__(rhs))
### base classes for individual Gaudi algorithms/services/algtools ===========
......
Mon Mar 5 17:12:34 EST 2018
WARNING: TCMALLOCDIR not defined, will use libc malloc
Wed Jan 9 15:46:08 CET 2019
Preloading tcmalloc_minimal.so
Py:Athena INFO including file "AthenaCommon/Preparation.py"
Py:Athena INFO using release [?-21.0.0] [i686-slc5-gcc43-dbg] [?/?] -- built on [?]
Py:Athena INFO using release [WorkDir-22.0.1] [x86_64-slc6-gcc62-opt] [master-Configurable-equality/85b8ca0400] -- built on [2018-12-14T2051]
Py:Athena INFO including file "AthenaCommon/Atlas.UnixStandardJob.py"
Py:Athena INFO executing ROOT6Setup
Py:Athena INFO including file "AthenaCommon/Execution.py"
Py:Athena INFO including file "AthenaCommon/ConfigurableUnitTests.py"
test1LoadAutoConfigurable (__main__.BasicConfigurableDbTestCase)
Test autoloading of a configurable (w/ getConfigurable) ... Py:ConfigurableDb INFO Read module info for 470 configurables from 2 genConfDb files
Test autoloading of a configurable (w/ getConfigurable) ... Py:ConfigurableDb INFO Read module info for 5461 configurables from 6 genConfDb files
Py:ConfigurableDb INFO No duplicates have been found: that's good !
ok
test2LoadAutoConfigurable (__main__.BasicConfigurableDbTestCase)
Test autoloading of a configurable (w/ CfgMgr) ... ok
test1MethodChecking (__main__.BasicConfigurableTestCase)
Test that needed methods are properly checked ... ok
test1EqualityIsReflexive (__main__.ConfigurableEqualityTestCase)
Test that x == x ... ok
test2EqualityIsSymmetric (__main__.ConfigurableEqualityTestCase)
Test that x == y and y == x ... ok
test3InequalityWithoutChildren (__main__.ConfigurableEqualityTestCase)
Test that configurables with different properties ... ok
test4InequalityWithChildren (__main__.ConfigurableEqualityTestCase)
Test that configurables with different properties ... ok
test1PicklePersistency (__main__.ConfigurablePersistencyTestCase)
Test r/w a job from/to a pickle file ... ok
test2ConfigurableShelveConfigs (__main__.ConfigurablePersistencyTestCase)
......@@ -22,6 +30,6 @@ test1ConstructorKeywords (__main__.KeywordHandlingTestCase)
Test proper handling of constructor keywords ... ok
----------------------------------------------------------------------
Ran 6 tests in 0.774s
Ran 10 tests in 2.720s
OK
......@@ -10,7 +10,6 @@ import unittest, sys
import AthenaCommon.Configurable as Configurable
import AthenaCommon.ConfigurableDb as ConfigurableDb
### data ---------------------------------------------------------------------
__version__ = '1.0.0'
__author__ = 'Wim Lavrijsen (WLavrijsen@lbl.gov)'
......@@ -371,6 +370,108 @@ class ConfigurablePersistencyTestCase( unittest.TestCase ):
return
### Equality comparisons of Configurable & friends =================================
from GaudiKernel.GaudiHandles import PrivateToolHandle, PrivateToolHandleArray
class DummyAlg( Configurable.ConfigurableAlgorithm ):
__slots__ = {
'DummyIntProp' : 0, # int
'DummyBoolProp' : True, # bool
'DummyFloatProp' : 3.141, # float
'DummyStringProp' : 'Mellon', # string
'DummyToolHProp' : PrivateToolHandle('DummyToolA/DummyTool1'), # GaudiHandle
'DummyToolHArrayProp' : PrivateToolHandleArray([]), # GaudiHandleArray
}
def __init__(self, name = Configurable.Configurable.DefaultName, **kwargs):
super(DummyAlg, self).__init__(name)
for n,v in kwargs.items():
setattr(self, n, v)
def getDlls( self ):
return 'AthenaCommon'
def getType( self ):
return 'DummyAlg'
pass # class DummyAlg
class DummyToolA( Configurable.ConfigurableAlgTool ):
__slots__ = {
'DummyIntProp' : 1, # int
'DummyBoolProp' : False, # bool
'DummyFloatProp' : 1.414, # float
'DummyStringProp' : 'Kawan', # string
'DummyToolHProp' : PrivateToolHandle('DummyToolB/DummyTool1'), # GaudiHandle
}
def __init__(self, name = Configurable.Configurable.DefaultName, **kwargs):
super(DummyToolA, self).__init__(name)
for n,v in kwargs.items():
setattr(self, n, v)
def getDlls( self ):
return 'AthenaCommon'
def getType( self ):
return 'DummyToolA'
pass # class DummyToolA
class DummyToolB( Configurable.ConfigurableAlgTool ):
__slots__ = {
'DummyIntProp' : 2, # int
'DummyBoolProp' : True, # bool
'DummyFloatProp' : 2.681, # float
'DummyStringProp' : 'Rakan', # string
}
def __init__(self, name = Configurable.Configurable.DefaultName, **kwargs):
super(DummyToolB, self).__init__(name)
for n,v in kwargs.items():
setattr(self, n, v)
def getDlls( self ):
return 'AthenaCommon'
def getType( self ):
return 'DummyToolB'
pass # class DummyToolB
class ConfigurableEqualityTestCase( unittest.TestCase ):
"""Verify behavior of Configurable equality comparisons"""
# In the pre-Run3 behaviour, the same instance was always returned.
def setUp(self):
Configurable.Configurable.configurableRun3Behavior = True
pass
def tearDown(self):
Configurable.Configurable.configurableRun3Behavior = False
pass
def test1EqualityIsReflexive( self ):
"""Test that x == x"""
myDummyAlg = DummyAlg("MyDummyAlg")
self.assertEqual( myDummyAlg, myDummyAlg )
def test2EqualityIsSymmetric( self ):
"""Test that x == y and y == x"""
myDummyAlg1 = DummyAlg("MyDummyAlg")
myDummyAlg2 = DummyAlg("MyDummyAlg")
# First and second instances should not be identical
self.assertFalse( myDummyAlg1 is myDummyAlg2 )
# However, they should be equal
self.assertEqual( myDummyAlg1, myDummyAlg2 )
self.assertEqual( myDummyAlg2, myDummyAlg1 )
def test3InequalityWithoutChildren( self ):
"""Test that configurables with different properties
compare non-equal without recursion into children"""
myDummyTool1 = DummyToolB("MyDummyToolB")
myDummyTool2 = DummyToolB("MyDummyToolB",DummyIntProp=-1)
self.assertTrue( myDummyTool1 != myDummyTool2 )
self.assertTrue( myDummyTool2 != myDummyTool1 )
def test4InequalityWithChildren( self ):
"""Test that configurables with different properties
compare non-equal with recursion into children"""
myDummyAlg1 = DummyAlg("MyDummyAlg")
myDummyAlg2 = DummyAlg("MyDummyAlg")
myDummyAlg2.DummyToolHProp = DummyToolB("MyDummyToolB")
self.assertTrue( myDummyAlg1 != myDummyAlg2 )
self.assertTrue( myDummyAlg2 != myDummyAlg1 )
## actual test run
if __name__ == '__main__':
loader = unittest.TestLoader()
......
......@@ -61,10 +61,9 @@ class ComponentAccumulator(object):
self._msg.info( "Event Algorithm Sequences" )
def printProperties(c, nestLevel = 0):
from AthenaCommon.Configurable import ConfigurableAlgTool
for propname, propval in c.getProperties().iteritems():
# Ignore unset or empty lists
if propval=='<no value>' or propval==[]:
for propname, propval in c.getValuedProperties().iteritems():
# Ignore empty lists
if propval==[]:
continue
# Printing EvtStore could be relevant for Views?
if propname in ["DetStore","EvtStore"]:
......
......@@ -66,6 +66,10 @@ def MainServicesThreadedCfg(cfgFlags):
if cfgFlags.Concurrency.NumThreads==0:
return MainServicesSerialCfg()
if cfgFlags.Concurrency.NumConcurrentEvents==0:
# In a threaded job this will mess you up because no events will be processed
raise Exception("Requested Concurrency.NumThreads>0 and Concurrency.NumConcurrentEvents==0, which will not process events!")
cfg = MainServicesSerialCfg("AthenaHiveEventLoopMgr")
# Migrated code from AtlasThreadedJob.py
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment