Tested on ST3+ with Python 3.7+
Sublime text editor loads all plugin related files at once on the start
and only reloads if there's any change in the .py
files located in the
root of plugin directory, and to reload any changes made in the sub modules
located somewhere in the nested folder in your plugin then you have to close the application and
reopen it to load the changes.
There are other reloader
scripts which basically reloads the given plugin
modules stored in the sub-directories and they work very well, for eg these:
- https://github.com/astrauka/TestRSpec/blob/v1.0.4/plugin_helpers/reloader.py
- https://github.com/wbond/sublime_package_control/blob/master/package_control/reloader.py
But it requires you to put module names in the list to load.
Therefore on the same principle wrote this script which it automatically finds
all the nested
plugin files your main plugin directory have, it just requires you to give your plugin name
.
This also handles the scenario if the file/folder is renamed/deleted
which was an edge case for these
scripts as mentioned here:
Now with this script whenever you make any changes in any of the root .py
files
this will reload all and only your plugin files. so when you hit save on any your root
.py
files where this reloader
is imported
it will reload all other files in the plugin
directory.
-
Create
reloader.py
anywhere in your plugin directory, copy below code into it:import importlib, os from types import ModuleType from typing import Optional def import_sub_module(module_path) -> Optional[ModuleType]: """ :module_path -> In form of "Plugin.foo.bar" """ try: return importlib.import_module(module_path) except ModuleNotFoundError: print(f"Unable to import {module_path}") return None def walk_sub_modules(plugin_name, base_path): for dir, _, files in os.walk(base_path): parent_module_imported = False # If its a root directory if plugin_name == os.path.basename(dir): parent_module_path = plugin_name else: # This gives result as Plugin.foo.bar parent_module_path = f"{plugin_name}{'.'.join(str(dir).split(plugin_name)[-1].split(os.path.sep))}" for file in files: file_name, extension = os.path.splitext(file) if extension == '.py': # Importing once only if not parent_module_imported: # Only trying to import parent once we know it has .py file import_sub_module(parent_module_path) parent_module_imported = True # Importing .py file import_sub_module(f"{parent_module_path}.{file_name}") def reload(plugin_name): plugin = importlib.import_module(plugin_name) walk_sub_modules(plugin_name, plugin.__path__[0])
-
Now import the
reloader
into your plugin command files located in your root directory of plugin:If you have multiple
.py
files in root then import the reloader in all of them# Put this on top of the file # # Reloads the submodules # For eg. if your folder structure is this # / # - src/ # - reloader.py # - <main plugin file>.py # Then in <main plugin file>.py the import should be like this: # from .src import reloader from <your_path_to_reloader_file> import reloader import importlib # Optional: this reloads the reloader, if there's any change importlib.reload(reloader) # Plugin should match exactly how its shown in sublime text reloader.reload("<Your Plugin Name>") # for eg. reloader.reload("GitGutter") # # <your rest of the plugin code goes here...> #