18 """Standalone Analysis Service Configuration
20 This class is used to describe the configuration of an analysis service
21 (a C++ class inheriting from asg::AsgService) in Python. It behaves
22 similar to an Athena configurable, but is implemented in a much simpler
25 An example of using it in configuring an EventLoop job could look like:
29 from AsgServices.AsgServiceConfig import AsgServiceConfig
30 service = AsgServiceConfig( "asg::UnitTestService1/TestService",
32 service.string_property = "Foo"
33 job.servicesAdd( service )
35 Note that the python code doesn't know what properties can actually be set
36 on any given C++ service. Any mistake made in the Python configuration
37 (apart from syntax errors) is only discovered while initialising the
46 """Constructor for an service configuration object
49 typeAndName -- The type/instance name of the service
51 Note that you can pass (initial) properties to the constructor like:
53 service = AsgServiceConfig( "asg::UnitTestService1/TestService",
59 super( AsgServiceConfig, self ).
__init__()
60 self.setTypeAndName( typeAndName )
66 for key, value
in kwargs.items():
68 self.
_props[ key ] = copy.deepcopy( value )
74 """Get the instance name of the service
76 This is for compatibility with the getName() function of Athena
83 """Get the type name of the service
85 This is for compatibility with the getType() function of Athena
92 """Get a previously set property value from the configuration
94 This function allows us to retrieve the value of a property that was
95 already set for the service, to possibly use it in some configuration
96 decisions in the Python code itself.
99 name -- The name of the property
103 if not name
in self.
_props:
104 raise AttributeError(
'Property \'%s\' was not set on \'%s/%s\'' %
105 ( name, self.type(), self.name() ) )
108 return self.
_props[ name ]
111 """Set an service property on an existing configuration object
113 This function allows us to set/override properties on an service
114 configuration object. Allowing for the following syntax:
117 service.IntProperty = 66
118 service.FloatProperty = 3.141592
119 service.StringProperty = "Foo"
122 key -- The key/name of the property
123 value -- The value to set for the property
128 return super( AsgServiceConfig, self ).
__setattr__( key, value )
131 super( AsgServiceConfig,
133 self.
_props[ key ] = copy.deepcopy( value )
137 """Check for equality with another object
139 The implementation of this is very simple. We only check that the type
140 and the name of the services would match.
144 if not isinstance( other, AsgServiceConfig ):
148 return ( ( self.type() == other.type() )
and
149 ( self.name() == other.name() ) )
152 """Check for an inequality with another object
154 This is just defined to make the '!=' operator of Python behave
155 consistently with the '==' operator for such objects.
157 return not self.
__eq__( other )
160 """Print the service configuration in a user friendly way
162 This is just to help with debugging configurations, allowing
163 the user to get a nice printout of their job configuration.
166 name =
'Service %s/%s' % ( self.type(), self.name() )
167 result = AsgServiceConfig._printHeader( name )
170 if isinstance( value, str ):
171 printedValue =
"'%s'" % value
175 result +=
"|- %s: %s\n" % ( key,
indentBy( printedValue,
"| " ) )
177 result += AsgServiceConfig._printFooter( name )
181 """Create a private tool for the service
183 This function is used in 'standalone' mode to declare a private tool
184 for the service, or a private tool for an already declared private
188 config.addPrivateTool( 'tool1', 'ToolType1' )
189 config.addPrivateTool( 'tool1.tool2', 'ToolType2' )
192 name -- The full name of the private tool
193 type -- The C++ type of the private tool
201 toolNames = name.split(
'.' )
205 for tname
in toolNames[ 0 : -1 ]:
206 component = getattr( component, tname )
210 if hasattr( component, toolNames[ -1 ] ):
211 raise RuntimeError(
"Tool with name '%s' already exists" % name )
219 self.createPrivateTool( name, type ).
ignore()
225 """Produce a nice header when printing the configuration
227 This function is used for printing the header of both services
231 indentString -- String used as indentation
232 title -- The title of the service/tool
235 preLength = AsgServiceConfig.printHeaderPre
236 postLength = AsgServiceConfig.printHeaderWidth - 3 - preLength - \
238 return '/%s %s %s' % ( preLength *
'*', title, postLength *
'*' )
242 """Produce a nice footer when printing the configuration
244 This function is used for printing the footer of both services
248 indentString -- String used as indentation
249 title -- The title of the service/tool
252 preLength = AsgServiceConfig.printHeaderPre
253 postLength = AsgServiceConfig.printHeaderWidth - 12 - preLength - \
255 return '\\%s (End of %s) %s' % ( preLength *
'-', title,
262 """Standalone Private Tool Configuration
264 This class is used to mimic the behaviour of Athena tool configurable
265 classes. To be able to set the properties of private tools used by
266 dual-use services in a way that's valid for both Athena and EventLoop.
270 """Constructor for an private tool configuration object
281 """Get a previously set property value from the configuration
283 This function allows us to retrieve the value of a tool property that
284 was already set for an service's private tool, to possibly use it in
285 some configuration decisions in the Python code itself.
288 name -- The name of the property
292 if not name
in self.
_props:
293 raise AttributeError(
'Property "%s" was not set on "%s/%s.%s"' %
298 return self.
_props[ name ]
301 """Set a tool property on an existing configuration object
303 This function allows us to set/override properties on a private tool
304 of an service configuration object. Allowing for the following syntax:
307 service.Tool.IntProperty = 66
308 service.Tool.FloatProperty = 3.141592
309 service.Tool.StringProperty = "Foo"
312 key -- The key/name of the property
313 value -- The value to set for the property
318 return super( PrivateToolConfig, self ).
__setattr__( key, value )
321 fullName = self.
_prefix +
"." + key
324 self.
_service.setPropertyFromString( fullName,
326 self.
_props[ key ] = copy.deepcopy( value )
330 """Print the private tool configuration in a user friendly way
332 This is just to help with debugging configurations, allowing
333 the user to get a nice printout of their job configuration.
336 name =
'Private Tool %s/%s' % ( self.
_type, self.
_prefix )
338 result += AsgServiceConfig._printHeader( name )
341 if isinstance( value, str ):
342 printedValue =
"'%s'" % value
346 result +=
"|- %s: %s\n" % ( key,
indentBy( printedValue,
"| " ) )
348 result += AsgServiceConfig._printFooter( name )
355 """Helper function producing a string property value"""
357 stringValue =
str( value )
358 if isinstance( value, bool ):
359 stringValue =
str(
int( value ) )
365 """Helper function used in the configuration printout"""
367 stringValue =
str( propValue )
369 for stringLine
in stringValue.split(
'\n' ):
371 result +=
"\n" + indent
389 self.assertEqual( config1.type(),
"TypeName" )
390 self.assertEqual( config1.name(),
"TypeName" )
392 self.assertEqual( config2.type(),
"NS::SomeType" )
393 self.assertEqual( config2.name(),
"NS::SomeType" )
400 self.assertEqual( config1.type(),
"TypeName" )
401 self.assertEqual( config1.name(),
"InstanceName" )
403 self.assertEqual( config2.type(),
"NS::SomeType" )
404 self.assertEqual( config2.name(),
"Instance" )
417 self.
config.Prop1 =
"Value1"
418 self.
config.Prop2 = [
"Value2" ]
419 self.assertEqual( self.
config.Prop1,
"Value1" )
420 self.assertEqual( self.
config.Prop2, [
"Value2" ] )
421 self.assertNotEqual( self.
config.Prop1,
"Foo" )
422 self.assertNotEqual( self.
config.Prop2,
"Value2" )
427 with self.assertRaises( AttributeError ):
443 self.
config.Tool1.Prop1 =
"Value1"
444 self.
config.Tool1.Prop2 = [ 1, 2, 3 ]
445 self.assertEqual( self.
config.Tool1.Prop1,
"Value1" )
446 self.assertEqual( self.
config.Tool1.Prop2, [ 1, 2, 3 ] )
453 self.
config.Tool1.Tool2.Prop3 =
"Foo"
454 self.
config.Tool1.Tool2.Prop4 = [
"Bar" ]
455 self.assertEqual( self.
config.Tool1.Tool2.Prop3,
"Foo" )
456 self.assertEqual( self.
config.Tool1.Tool2.Prop4, [
"Bar" ] )
462 with self.assertRaises( AttributeError ):
463 value = self.
config.Tool1.BadProp
466 with self.assertRaises( AttributeError ):
467 value = self.
config.Tool1.Tool2.BadProp
473 with self.assertRaises( AttributeError ):