Skip to content



Splices the post save hook into the global Jupyter configuration file

Source code in nbautoexport/
def install_post_save_hook(config_path: Optional[Path] = None):
    """Splices the post save hook into the global Jupyter configuration file"""
    if config_path is None:
        config_dir = jupyter_config_dir()
        config_path = Path(config_dir) / ""

    config_path = config_path.expanduser().resolve()

    if not config_path.exists():
        logger.debug(f"No existing Jupyter configuration detected at {config_path}. Creating...")
        config_path.parent.mkdir(exist_ok=True, parents=True)
        with"w", encoding="utf-8") as fp:
            fp.write(post_save_hook_initialize_block)"nbautoexport post-save hook installed.")

    # If config exists, check for existing nbautoexport initialize block and install as appropriate
    logger.debug(f"Detected existing Jupyter configuration at {config_path}")

    with"r", encoding="utf-8") as fp:
        config =

        logger.debug("Detected existing nbautoexport post-save hook.")

        version_match =
        if version_match:
            existing_version =
            logger.debug(f"Existing post-save hook is version {existing_version}")
            existing_version = ""
            logger.debug("Existing post-save hook predates versioning.")

        if parse_version(existing_version) < parse_version(__version__):
  "Updating nbautoexport post-save hook with version {__version__}...")
            with"w", encoding="utf-8") as fp:
                # Open as w replaces existing file. We're replacing entire config.
                fp.write(block_regex.sub(post_save_hook_initialize_block, config))
            logger.debug("No changes made.")
    else:"Installing post-save hook.")
        with"a") as fp:
            # Open as a just appends. We append block at the end of existing file.
            fp.write("\n" + post_save_hook_initialize_block)"nbautoexport post-save hook installed.")