Adding a post_save_hook with an extension?

Is it possible to add a post_save_hook via an extension?

Currently I use a post_save_hook that calls nbconvert to convert the file to a .py file, then modify that file to strip out output text as well as also stripping out any code cells that do not being with “#@!” (an arbitrary comment that I picked).

This automatically saves just the selected cells (that start with #@!) in a notebook to a corresponding python file, while still allowing me to keep other cells in just the .ipynb file but out of the .py file (such as snippets for testing). It also means that I can essentially just call other notebooks through standard Python mechanics, which then makes it much, much easier to deploy the code.

Unfortunately this setup requires me to re-add the post_save_hook when I occasionally create a new Jupyterlab instance, and is perhaps a touch clunky having to add #@! to the cells that I want to save to the python file.

What I’d ideally like to do is to create an extension that adds a new cell type (CodeToSave or something like that), which would act identically to a Code cell within a notebook, but then the post_save_hook would only save those to the .py file (so skipping the need for #@!). While I’ve found some information on adding new cell types through an extension, I haven’t been able to find out if there is a way (and if so how) to add a post_save_hook via an extension. Is it possible?

1 Like

I’ve just been trying to register a post_save_hook from within an extension as well. Have any luck? My extension code throws no errors, but the hook doesn’t seem to be running either…
Greg

There are a lot of ways to get a reference to the FileContentsManager (some better than others :-)). One approach is to create an ExtensionApp and use its settings dictionary in order add the hook to it.

class JupyterLabApp(ExtensionApp):

    def initialize_settings(self):

        try:
            def post_save_hook(model, os_path, contents_manager, **kwargs):
                print('SAVE')
                
            self.settings['contents_manager'].register_post_save_hook(post_save_hook)

        except Exception as e:
            self.log.error(str(e))

It’s possible to get a reference to it in the RouteHandler, but because an instance is created each time a request is made, it may not make sense to do it that way.