@@ -166,16 +166,42 @@ def job(
166166 # empty/default inputs of a workflow step).
167167 #
168168 # The solution below evaluates the requirements and hints for
169- # the workflow, for each step of the workflow, and for the
170- # embedded tool (command-line or expression tools) of each
171- # step.
169+ # the workflow (parent), keeping track of the name of the
170+ # requirements and hints. For each step of the workflow and of
171+ # the embedded tool (command-line or expression tools) it will
172+ # then evaluate the requirements or hints that have the same
173+ # name - even though they may be re-evaluated at the step
174+ # level (e.g. a workflow defines a requirement resource that
175+ # uses inputs.threads_max, and a command-line tool of the same
176+ # workflow also defines a requirement with the same name, but
177+ # using the command-line tool input values).
172178 #
173179 # This prevents evaluation at the step level (i.e. the values
174180 # were already loaded earlier/eagerly).
175181 def _fix_hints_and_requirements (
176182 hints_or_requirements : List [CWLObjectType ],
183+ requirements_or_hints_to_evaluate : List [str ],
177184 ) -> None :
185+ """Internal function to iterate the hints or requirements of steps
186+ provided and evaluate the ones that exist in the parent process.
187+ """
178188 for hint_or_requirement in hints_or_requirements :
189+ for key , value in hint_or_requirement .items ():
190+ if key in requirements_or_hints_to_evaluate :
191+ hint_or_requirement [key ] = expression .do_eval (
192+ ex = value ,
193+ jobinput = job_order ,
194+ requirements = self .requirements ,
195+ outdir = runtimeContext .outdir ,
196+ tmpdir = runtimeContext .tmpdir ,
197+ resources = {},
198+ context = None ,
199+ timeout = runtimeContext .eval_timeout ,
200+ )
201+
202+ for attr_key in ["hints" , "requirements" ]:
203+ parent_entries = []
204+ for hint_or_requirement in getattr (self , attr_key ):
179205 for key , value in hint_or_requirement .items ():
180206 hint_or_requirement [key ] = expression .do_eval (
181207 ex = value ,
@@ -187,12 +213,13 @@ def _fix_hints_and_requirements(
187213 context = None ,
188214 timeout = runtimeContext .eval_timeout ,
189215 )
216+ parent_entries .append (key )
190217
191- for key in ["hints" , "requirements" ]:
192- _fix_hints_and_requirements (getattr (self , key ))
193218 for step in self .steps :
194- _fix_hints_and_requirements (getattr (step , key ))
195- _fix_hints_and_requirements (getattr (step .embedded_tool , key ))
219+ _fix_hints_and_requirements (getattr (step , attr_key ), parent_entries )
220+ _fix_hints_and_requirements (
221+ getattr (step .embedded_tool , attr_key ), parent_entries
222+ )
196223
197224 builder = self ._init_job (job_order , runtimeContext )
198225
0 commit comments