77
88import copy
99import glob
10+ import importlib
1011import json
1112import os
1213import sys
@@ -135,6 +136,58 @@ def genTests(self) -> list:
135136 # ok
136137 return result
137138
139+ def buildPyHooks (self , config : dict ) -> dict :
140+ # init
141+ result = {}
142+ key : str
143+
144+ # extract and build dict
145+ for key , value in config .items ():
146+ if key .startswith ("callPyFunction" ):
147+ when = key .replace ("callPyFunction" , "" )
148+ result [when ] = value
149+
150+ # ok
151+ return result
152+
153+ # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
154+ def importFromPath (self , moduleName : str , filePath : str ):
155+ spec = importlib .util .spec_from_file_location (moduleName , filePath )
156+ module = importlib .util .module_from_spec (spec )
157+ # sys.modules[moduleName] = module
158+ spec .loader .exec_module (module )
159+ return module
160+
161+ def callPyHook (self , dir : str , hooks : dict , name : str ) -> None :
162+ # nothing to do
163+ if name not in hooks :
164+ return
165+
166+ # split file:funcName
167+ params = hooks [name ].split (":" , 1 )
168+ filePath = params [0 ]
169+ funcName = params [1 ]
170+
171+ # complete
172+ fileFullPath = os .path .join (dir , filePath )
173+
174+ # log
175+ print ("************** CALLING PY FUNCTION ****************" )
176+ print (f"Hook: { name } " )
177+ print (f"HookValue: { hooks [name ]} " )
178+ print (f"Import { fileFullPath } " )
179+ print (f"Call: { funcName } " )
180+ print ("***************************************************" )
181+
182+ # import the module
183+ module = self .importFromPath ("idefix_test_py_hooks" , fileFullPath )
184+
185+ # get function
186+ function = getattr (module , funcName )
187+
188+ # call it
189+ function ()
190+
138191 def run (self , config : dict ) -> None :
139192 # clone before modify to not modity for caller
140193 config = copy .deepcopy (config )
@@ -155,6 +208,7 @@ def run(self, config: dict) -> None:
155208 nonRegressionTestIni = config .get ("nonRegressionTestIni" , None )
156209 check_file_produced = config .get ("check_file_produced" , [])
157210 problemDir = os .path .dirname (testfile )
211+ pyHooks = self .buildPyHooks (config )
158212
159213 # cleanup some keyword not handled at the
160214 # level of idx_test so we don't perturbate it
@@ -169,6 +223,12 @@ def run(self, config: dict) -> None:
169223 del config ["nonRegressionTest" ]
170224 if "nonRegressionTestIni" in config :
171225 del config ["nonRegressionTestIni" ]
226+ for hook in pyHooks :
227+ del config [f"callPyFunction{ hook } " ]
228+
229+ # call hook before
230+ with moveInDir (problemDir ):
231+ self .callPyHook (problemDir , pyHooks , "Before" )
172232
173233 # if switch from test, rebuild the runner (a runner make for one dir)
174234 if self .currentTestFile != testfile :
@@ -189,11 +249,16 @@ def run(self, config: dict) -> None:
189249 )
190250
191251 # check produced
192- for file in check_file_produced :
193- if not os .path .exists (file ) and not self .currentTestRunner .fake :
194- raise Exception (
195- f"Don't find expected file to be produced by the run : { file } !"
196- )
252+ with moveInDir (problemDir ):
253+ for file in check_file_produced :
254+ if not os .path .exists (file ) and not self .currentTestRunner .fake :
255+ raise Exception (
256+ f"Don't find expected file to be produced by the run : { file } !"
257+ )
258+
259+ # call hook after
260+ with moveInDir (problemDir ):
261+ self .callPyHook (problemDir , pyHooks , "After" )
197262
198263 def _runNonRegression (
199264 self ,
@@ -365,7 +430,7 @@ def main(self, all: bool = False):
365430 os .environ ["IDEFIX_TEST_FILTER_SUBDIR" ] = idefixTest .filterSubdir
366431
367432 if idefixTest .all :
368- pytest .main (
433+ status = pytest .main (
369434 [
370435 "-v" ,
371436 "--no-header" ,
@@ -375,6 +440,7 @@ def main(self, all: bool = False):
375440 + idefixTest .remainingArgs
376441 + [self .parentScritFile ]
377442 )
443+ sys .exit (status )
378444 else :
379445 raise NotImplementedError ("Not yet supported !" )
380446 # elif self.check:
0 commit comments