diff --git a/GH/PyGH/components/scriptsynccpy/code.py b/GH/PyGH/components/scriptsynccpy/code.py index 98753e5..1dfdcfd 100644 --- a/GH/PyGH/components/scriptsynccpy/code.py +++ b/GH/PyGH/components/scriptsynccpy/code.py @@ -176,7 +176,6 @@ def handle_connection_error(self, e): self.add_runtime_warning(error_messages[type(e)]) self.is_connected = False if type(e) != socket.error or e.winerror != 10056 else True - class FileChangedThread(GHThread): """ A thread to check if the file has changed on disk. @@ -286,7 +285,7 @@ def reload_all_modules(self, directory): if module_name in sys.modules: importlib.reload(sys.modules[module_name]) - def safe_exec(self, path, globals, locals): + def safe_exec(self, path, globals, locals, packages_2_reload): """ Execute Python3 code safely. It redirects the output of the code to a string buffer 'stdout' to output to the GH component param. @@ -295,10 +294,20 @@ def safe_exec(self, path, globals, locals): :param path: The path of the file to execute. :param globals: The globals dictionary. :param locals: The locals dictionary. + :param packages_2_reload: The list of packages to reload, this is used for custom packages developement. + installed on the system via an editable pip installation for example. """ try: with open(path, 'r') as f: - # add the path and sub directories to the sys path + # reload the specifyed packages + if packages_2_reload is not None: + if packages_2_reload.__len__() != 0: + for package in packages_2_reload: + for key in list(sys.modules.keys()): + if package in key: + importlib.reload(sys.modules[key]) + + # add the path and sub directories to the sys path path_dir = os.path.dirname(path) sub_dirs = [] for root, dirs, files in os.walk(path_dir): @@ -366,9 +375,12 @@ def safe_exec(self, path, globals, locals): err_msg = f"script-sync::Error in the code: {str(e)}" raise Exception(err_msg) - def RunScript(self, btn: bool, x: float): + def RunScript(self, + btn: bool, + packages_2_reload : list, + x: float + ): """ This method is called whenever the component has to be recalculated it's the solve main instance. """ - self.is_success = False # set the path if button is pressed @@ -394,7 +406,7 @@ def RunScript(self, btn: bool, x: float): # add to the globals all the input parameters of the component (the locals) globals().update(locals()) - res = self.safe_exec(self.path, None, globals()) + res = self.safe_exec(self.path, None, globals(), packages_2_reload) self.is_success = True return diff --git a/GH/PyGH/components/scriptsynccpy/metadata.json b/GH/PyGH/components/scriptsynccpy/metadata.json index 3f8b9b9..a40e064 100644 --- a/GH/PyGH/components/scriptsynccpy/metadata.json +++ b/GH/PyGH/components/scriptsynccpy/metadata.json @@ -24,6 +24,20 @@ "reverse": false, "simplify": false }, + { + "name": "packages_2_reload", + "nickname": "packages_2_reload", + "description": "Pass a list with the name of the custom packages you want to reload. This function is useful if you are developing a i.e. PyPI package and you want to reload the submodules after you modified something. The function will reload the package and all its submodules. If you want to reload the package and all its submodules, just pass the package name. If you want to reload only a submodule, pass the package name and the submodule name separated by a dot. If you want to reload multiple submodules, pass the package", + "optional": true, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "list", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "str", + "reverse": false, + "simplify": false + }, { "name": "x", "nickname": "x",