[docs]defexec_script(path:str,globals:Dict[str,Any]=None)->None:""" Attempt to exec a controller script :param path: full path to the script, beginning with "/" :param globals: the globals to use for execution of the notebook, if you want to have the variables from your script session available use "globals()" """src=dh_globals.j_controller_client_factory.getUnsubscribed().getScriptBody(path,True,dh_globals.script_loader_state)ifsrcisNone:raiseFileNotFoundError("Controller script not found: "+path)exec(compile(src,path,'exec'),globals)
[docs]defmeta_import(root:str="controller")->None:""" Set up a meta importer to enable using a Python import statement that references paths from the Persistent Query Controller. For example, after calling 'meta_import("controller")'; you can then call 'import controller.file' to make the "/file.py" from the controller available as a Python module. :param root: the module name that prefixes all controller sourced modules, defaults to "controller" """sys.meta_path.append(__ControllerImporter(root))
class_ImportedControllerScript:def__init__(self,path,source=None):self.path=pathself.source=sourcedefcreate_module(self,spec):returnNonedefexec_module(self,module):ifself.sourceisnotNone:exec(compile(self.source,'<string>','exec'),module.__dict__)def_j_collection_to_list(jcollection)->List[Any]:"""Converts a java list to a python list."""ifnotjcollection:return[]res:List[Any]=[]it=jcollection.iterator()whileit.hasNext():res.append(jcompat.wrap_j_object(it.next()))returnresclass__ControllerImporter:root:strdef__init__(self,root:str):ifrootisNoneorroot=="":raiseException("root for controller imports must not be empty!")if"."inroot:raiseException("root for controller imports must not contain a period!")self.root=rootself.j_controller_client=dh_globals.j_controller_client_factory.getUnsubscribed()self.loader_state=dh_globals.script_loader_statedeffind_spec(self,name,path,target=None):ifname!=self.rootandnotname.startswith(self.root+"."):# this is not a controller import; return None so that other finder/loaders can tryreturnNonerelevant_path=name[len(self.root)+1:]paths=_j_collection_to_list(self.j_controller_client.getScriptPaths(self.loader_state,True))to_directory=relevant_path.replace(".","/")ifto_directory+".py"inpaths:# this is the right thingsrc_name=to_directory+".py"elifto_directory+"/__init__.py"inpaths:src_name=to_directory+"/__init__.py"elifrelevant_path=="":src_name=Noneelse:# we should check that some path here would be a child of our pathprefix_exists:bool=Falseforxinpaths:ifx.startswith(to_directory+"/"):prefix_exists=Truebreakifnotprefix_exists:returnNonesrc_name=Noneifsrc_nameisNone:src=Noneelse:src=self.j_controller_client.getScriptBody(src_name,True,self.loader_state)module_spec=ModuleSpec(name,_ImportedControllerScript(path,src),is_package=True)module_spec.submodule_search_locations=name.split(".")returnmodule_spec