ATLAS Offline Software
flagTestLOD.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 #
4 # @file D3PDMakerCoreComps/python/flagTestLOD.py
5 # @author scott snyder <snyder@bnl.gov>
6 # @date Nov, 2012
7 # @brief Helper for making LOD functions to evaluate flags.
8 #
9 
10 from .D3PDObject import DeferArg
11 
12 
13 def _eval_deferred (expr, fdict, hookargs, **kw):
14  dd = fdict.copy()
15  dd.update (hookargs)
16  dd.update (kw)
17  return eval (expr, globals(), dd)
18 
19 
20 def flagTestLOD (expr, flags, hook = None):
21  """Helper for making LOD functions to evaluate flags.
22 
23  Numerous parts of the D3PD configuration use arbitrary global flags
24  to control which blocks are included. This is bad because there
25  can be interference when multiple tuples are configured in the
26  same job.
27 
28  Better is to use the level-of-detail mechanism to do this,
29  passing in flags as extra arguments to the D3PDObject.
30 
31  This helper is to ease this conversion, while still allowing
32  backwards compatibility with flag-based configuration.
33 
34  flagTestLOD will return a level-of-detail function that evaluates
35  the provided expression string EXP. This will be evaluated
36  in an environment that includes names for all flags in the flags
37  class(es) FLAGS, merged with the value of the hookargs.
38  The requested level of detail is also available as `reqlev'.
39  Thus, if you have something like:
40 
41  myobj = make_SGDataVector_D3PDObject ('mycont', 'mykey', 'my_', 'myob',
42  allow_args = ['myLevel'])
43  myobj.defineBlock (flagTestLOD('myLevel>2', myFlags),
44  'myblock', filler_tool)
45 
46  then myblock will be included in the tuple if the property
47  myFlags.myLevel() is greater than two. However, this can be overridden
48  by passing an argument to the D3PDObject:
49 
50  alg += myobj (level, myLevel=4)
51 
52  Explicit inclusion / exclusion also overrides this determination.
53 
54  Flags are evaluated at the point where flagTestLOD is called.
55 
56  If HOOK is supplied, then it is called if the LOD test passes.
57  It is passed as arguments two dictionaries: the block filler tool
58  arguments and the hook arguments.
59 
60  Examples:
61  >>> from AthenaConfiguration.AllConfigFlags import initConfigFlags
62  >>> flags = initConfigFlags()
63  >>> flags.addFlag ('D3PD.flag1', True)
64  >>> flags.addFlag ('D3PD.flag2', False)
65 
66  >>> lod = flagTestLOD ('flag1', flags.D3PD)
67  >>> lod(2, {}, {})
68  True
69  >>> lod(2, {}, {'flag1': False})
70  False
71  >>> lod(-999, {}, {})
72  False
73  >>> lod(999, {}, {'flag1': False})
74  True
75  >>> lod = flagTestLOD ('flag2 or reqlev>4', flags.D3PD)
76  >>> lod(2, {}, {})
77  False
78  >>> lod(10, {}, {})
79  True
80  >>> def hook(*args):
81  ... print(args)
82  >>> lod = flagTestLOD ('flag2 or reqlev>4', flags.D3PD, hook)
83  >>> lod(2, {}, {})
84  False
85  >>> lod(10, {'a':1}, {'b':2})
86  ({'a': 1}, {'b': 2})
87  True
88 """
89 
90  fdict = flags.asdict()
91  def flagTestLODFunc (reqlev, args, hookargs):
92  if reqlev < 0: return False # explicit exclusion
93  if reqlev > 900:
94  ret = True # explicit inclusion
95  else:
96  ret = _eval_deferred (expr, fdict, hookargs, reqlev=reqlev)
97  if ret and hook:
98  hook (args, hookargs)
99  return ret
100  return flagTestLODFunc
101 
102 
103 def deferFlag (expr, flags, gdict={}):
104  """Helper for making deferred arguments that evaluate flags.
105 
106  Numerous parts of the D3PD configuration use arbitrary global flags
107  to control how tuples are configured. This is bad because there
108  can be interference when multiple tuples are configured in the
109  same job.
110 
111  Better is to pass the flags in as arguments to the D3PDObject and pass
112  them to blocks using the DeferArg mechanism.
113 
114  This helper is to ease this conversion, while still allowing
115  backwards compatibility with flag-based configuration.
116 
117  deferFlag will return a DeferArg object that evaluates
118  the provided expression string EXP. This will be evaluated
119  in an environment that includes names for all flags in the flags
120  class(es) FLAGS, merged with the value of the hookargs.
121 
122  So if you do something like
123 
124  myobj = make_SGDataVector_D3PDObject ('mycont', 'mykey', 'my_', 'myob',
125  allow_args = ['doExtra'])
126  myobj.defineBlock (0, 'myblock', filler_tool,
127  DoExtra = deferFlag ('doExtra', myFlags))
128 
129  then the DoExtra property will be set from the property myFlags.doExtra()
130  unless it's overridden by passing an argument to the D3PDObject:
131 
132  alg += myobj (level, doExtra = True)
133 
134  Flags are evaluated at the point where deferFlag is called.
135 
136  GDICT gives extra names to be made available when evaluating EXPR.
137 
138 
139  Examples:
140  >>> from AthenaConfiguration.AllConfigFlags import initConfigFlags
141  >>> flags = initConfigFlags()
142  >>> flags.addFlag ('D3PD.flag3', True)
143 
144  >>> arg = deferFlag ('flag3', flags.D3PD)
145  >>> arg()
146  True
147  >>> arg({'flag3':False})
148  False
149  >>> arg = deferFlag ('foo', flags.D3PD, {'foo' : 2})
150  >>> arg()
151  2
152 """
153  fdict = flags.asdict()
154  return DeferArg ('_eval_deferred(expr, fdict, locals(), **_gdict)',
155  expr = expr,
156  fdict = fdict,
157  _gdict = gdict,
158  _eval_deferred = _eval_deferred)
python.flagTestLOD._eval_deferred
def _eval_deferred(expr, fdict, hookargs, **kw)
Definition: flagTestLOD.py:13
python.flagTestLOD.deferFlag
def deferFlag(expr, flags, gdict={})
Definition: flagTestLOD.py:103
python.flagTestLOD.flagTestLOD
def flagTestLOD(expr, flags, hook=None)
Definition: flagTestLOD.py:20