2 from AthenaConfiguration.ComponentFactory
import CompFactory
5 AthSequencer = CompFactory.AthSequencer
8 """parallel AND sequencer"""
13 Members = subs.copy() )
16 """parallel OR sequencer
17 This is the default sequencer and lets the DataFlow govern the execution entirely.
23 Members = subs.copy() )
26 """sequential AND sequencer"""
31 Members = subs.copy() )
34 """sequential OR sequencer
35 Used when a barrier needs to be set by all subs reached irrespective of the decision
41 Members = subs.copy() )
45 """Return sequence children (empty if comp is not a sequence)"""
48 except AttributeError:
53 """ Enforce rules for sequence graph - identical items can not be added to itself (even indirectly) """
55 def __noSubSequenceOfName( s, n, seen = set() ):
60 raise RuntimeError(f
"Sequence {c.getName()} contains itself")
63 raise RuntimeError(f
"Sequence {n} contains sub-sequence of the same name")
64 __noSubSequenceOfName( c, c.getName(), seen )
65 __noSubSequenceOfName( c, n, seen )
67 __noSubSequenceOfName( seq, seq.getName() )
73 return isinstance(obj, AthSequencer)
77 """ Traverse sequences tree to find a sequence of a given name. The first one is returned. """
78 if start.getName() == nameToLookFor:
82 if c.getName() == nameToLookFor:
91 """ find sequence that owns the sequence nameTooLookFor"""
93 if c.getName() == nameToLookFor:
103 """ Traverse sequences tree to find the first algorithm satisfying given predicate. The first encountered is returned.
105 Depth of the search can be controlled by the depth parameter.
106 Typical use is to limit search to the startSequence with depth parameter set to 1
122 """ Traverse sequences tree to find the algorithm of given name. The first encountered is returned.
124 The name() method is used to obtain the algorithm name, that one has to match to the request.
131 Returns flat listof of all algorithm instances in this, and in sub-sequences
138 if nameToLookFor
is None or child.getName() == nameToLookFor:
139 algorithms.append(child)
145 Finds all algorithms in sequence and groups them by name
147 Resulting dict has a following structure
148 {"Alg1Name":[(Alg1Instance, parentSequenceA, indexInSequenceA),(Alg1Instance, parentSequenceB, indexInSequenceB)],
149 "Alg2Name":(Alg2Instance, parentSequence, indexInThisSequence),
152 algorithms = collections.defaultdict(list)
154 if child.getName() == sequence.getName():
155 raise RuntimeError(f
"Recursively-nested sequence: {child.getName()} contains itself")
158 for algName
in childAlgs:
159 algorithms[algName] += childAlgs[algName]
161 if namesToLookFor
is None or child.getName()
in namesToLookFor:
162 algorithms[child.getName()].
append( (child, sequence, idx) )
167 """ Converts tree like structure of sequences into dictionary
168 keyed by top/start sequence name containing lists of of algorithms & sequences."""
170 def __inner( seq, collector ):
172 collector[seq.getName()].
append( c )
174 __inner( c, collector )
176 from collections
import defaultdict,OrderedDict
177 c = defaultdict(list)
179 return OrderedDict(c)
183 """Iterator of sequences and their algorithms from (and including) the `start`
184 sequence object. Do start from a sequence name use findSubSequence."""
189 yield from __inner(c)
191 yield from __inner(start)
199 import AthenaPython.PyAthena
as PyAthena
202 top.Members += [
parOR(
"nest1")]
204 top.Members += [nest2]
206 nest2.Members += [
parOR(
"deep_nest1")]
207 nest2.Members += [
parOR(
"deep_nest2")]
216 self.assertIsNotNone( f,
"Can not find sequence at start" )
217 self.assertEqual( f.getName(),
"top",
"Wrong sequence" )
220 self.assertIsNotNone( nest2,
"Can not find sub sequence" )
221 self.assertEqual( nest2.getName(),
"nest2",
"Sub sequence incorrect" )
226 self.assertIsNotNone( d,
"Deep searching for sub seqeunce fails" )
227 self.assertEqual( d.getName(),
"deep_nest2",
"Wrong sub sequence in deep search" )
232 self.assertIsNone( d,
"Algorithm confused as a sequence" )
236 self.assertIsNone( inexistent,
"ERROR, found sub sequence that does not relay exist" )
240 self.assertIsNone( inexistent,
"ERROR, found owner of inexistent sequence " )
244 self.assertEqual( owner.getName(),
"nest2",
"Wrong owner %s" % owner.getName() )
247 self.assertEqual( owner.getName(),
"nest2",
"Wrong owner %s" % owner.getName() )
250 self.assertEqual( owner.getName(),
"nest2",
"Wrong owner %s" % owner.getName() )
253 self.assertEqual( owner.getName() ,
"top",
"Wrong owner %s" % owner.getName() )
258 self.assertEqual( result, [
'top',
'nest1',
'nest2',
'deep_nest1',
'deep_nest2',
259 'SomeAlg1',
'SomeAlg2',
'SomeAlg3',
'SomeAlg0'] )
264 self.assertEqual( result, [
'nest2',
'deep_nest1',
'deep_nest2',
265 'SomeAlg1',
'SomeAlg2',
'SomeAlg3'] )
269 result = [seq.getName()
for seq
in iterSequences( deep_nest2 )]
270 self.assertEqual( result, [
'deep_nest2'] )
275 self.assertEqual( result, [
'SomeAlg1'] )
279 self.assertIsNotNone( a1,
"Can't find algorithm present in sequence" )
282 self.assertIsNotNone( a1,
"Can't find nested algorithm " )
287 self.assertIsNone( a1,
"Finding algorithm that is in the upper sequence" )
290 self.assertIsNone( a1,
"Finding algorithm that is does not exist" )
293 self.assertIsNotNone( a1,
"Could not find algorithm within the required nesting depth == 1" )
296 self.assertIsNone( a1,
"Could find algorithm even if it is deep in sequences structure" )
299 self.assertIsNotNone( a1,
"Could not find algorithm within the required nesting depth == 2" )
302 self.assertIsNotNone( a1
is None,
"Could find algorithm even if it is deep in sequences structure" )
307 global isComponentAccumulatorCfg
308 isComponentAccumulatorCfg =
lambda :
True
311 nest1 =
parOR(
"nest1")
313 top.Members += [nest1, nest2]
315 deep_nest1 =
seqAND(
"deep_nest1")
316 nest1.Members += [deep_nest1]
318 nest2.Members += [nest1]
320 deep_nest1.Members += [nest1]
321 self.assertRaises( RuntimeError, checkSequenceConsistency, top )