@@ -190,12 +190,17 @@ def load_functions(filepath: t.Optional[str] = None) -> t.Optional[types.ModuleT
190190
191191    mod_name , file_ext  =  os .path .splitext (os .path .split (filepath )[- 1 ])
192192
193+     logger .info (f"Loading functions module { mod_name } { filepath }  )
194+ 
193195    if  file_ext .lower () ==  ".py" :
194196        py_mod  =  imp .load_source (mod_name , filepath )
195197
196198    elif  file_ext .lower () ==  ".pyc" :
197199        py_mod  =  imp .load_compiled (mod_name , filepath )
198200
201+     elif  file_ext .lower () in  [".js" , ".javascript" ]:
202+         py_mod  =  load_source_js (mod_name , filepath )
203+ 
199204    else :
200205        raise  ValueError ("'{}' does not have the .py or .pyc extension" .format (filepath ))
201206
@@ -251,3 +256,28 @@ def load_file(path: t.Union[str, Path], retry_tries=None, retry_interval=0.075,
251256        except :  # pragma: nocover 
252257            pass 
253258    return  reader 
259+ 
260+ 
261+ def  module_factory (name , variables ):
262+     """ 
263+     Create a synthetic Python module object. 
264+ 
265+     Derived from: 
266+     https://www.oreilly.com/library/view/python-cookbook/0596001673/ch15s03.html 
267+     """ 
268+     module  =  imp .new_module (name )
269+     module .__dict__ .update (variables )
270+     module .__file__  =  "<synthesized>" 
271+     return  module 
272+ 
273+ 
274+ def  load_source_js (mod_name , filepath ):
275+     """ 
276+     Load a JavaScript module, and import its exported symbols into a synthetic Python module. 
277+     """ 
278+     import  javascript 
279+ 
280+     js_code  =  load_file (filepath , retry_tries = 0 ).read ().decode ("utf-8" )
281+     module  =  {}
282+     javascript .eval_js (js_code )
283+     return  module_factory (mod_name , module ["exports" ])
0 commit comments