You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			304 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			304 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
from functools import wraps
 | 
						|
from copy import deepcopy
 | 
						|
from traitlets import TraitError
 | 
						|
from traitlets.config.loader import (
 | 
						|
    Config,
 | 
						|
)
 | 
						|
from jupyter_core.application import JupyterApp
 | 
						|
from jupyter_server.serverapp import ServerApp
 | 
						|
from jupyter_server.extension.application import ExtensionApp
 | 
						|
from .traits import NotebookAppTraits
 | 
						|
 | 
						|
 | 
						|
def NBAPP_AND_SVAPP_SHIM_MSG(trait_name): return (
 | 
						|
    "'{trait_name}' was found in both NotebookApp "
 | 
						|
    "and ServerApp. This is likely a recent change. "
 | 
						|
    "This config will only be set in NotebookApp. "
 | 
						|
    "Please check if you should also config these traits in "
 | 
						|
    "ServerApp for your purpose.".format(
 | 
						|
        trait_name=trait_name,
 | 
						|
    )
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def NBAPP_TO_SVAPP_SHIM_MSG(trait_name): return (
 | 
						|
    "'{trait_name}' has moved from NotebookApp to "
 | 
						|
    "ServerApp. This config will be passed to ServerApp. "
 | 
						|
    "Be sure to update your config before "
 | 
						|
    "our next release.".format(
 | 
						|
        trait_name=trait_name,
 | 
						|
    )
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def EXTAPP_AND_NBAPP_AND_SVAPP_SHIM_MSG(trait_name, extapp_name): return (
 | 
						|
    "'{trait_name}' is found in {extapp_name}, NotebookApp, "
 | 
						|
    "and ServerApp. This is a recent change. "
 | 
						|
    "This config will only be set in {extapp_name}. "
 | 
						|
    "Please check if you should also config these traits in "
 | 
						|
    "NotebookApp and ServerApp for your purpose.".format(
 | 
						|
        trait_name=trait_name,
 | 
						|
        extapp_name=extapp_name
 | 
						|
    )
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def EXTAPP_AND_SVAPP_SHIM_MSG(trait_name, extapp_name): return (
 | 
						|
    "'{trait_name}' is found in both {extapp_name} "
 | 
						|
    "and ServerApp. This is a recent change. "
 | 
						|
    "This config will only be set in {extapp_name}. "
 | 
						|
    "Please check if you should also config these traits in "
 | 
						|
    "ServerApp for your purpose.".format(
 | 
						|
        trait_name=trait_name,
 | 
						|
        extapp_name=extapp_name
 | 
						|
    )
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def EXTAPP_AND_NBAPP_SHIM_MSG(trait_name, extapp_name): return (
 | 
						|
    "'{trait_name}' is found in both {extapp_name} "
 | 
						|
    "and NotebookApp. This is a recent change. "
 | 
						|
    "This config will only be set in {extapp_name}. "
 | 
						|
    "Please check if you should also config these traits in "
 | 
						|
    "NotebookApp for your purpose.".format(
 | 
						|
        trait_name=trait_name,
 | 
						|
        extapp_name=extapp_name
 | 
						|
    )
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def NOT_EXTAPP_NBAPP_AND_SVAPP_SHIM_MSG(trait_name, extapp_name): return (
 | 
						|
    "'{trait_name}' is not found in {extapp_name}, but "
 | 
						|
    "it was found in both NotebookApp "
 | 
						|
    "and ServerApp. This is likely a recent change. "
 | 
						|
    "This config will only be set in ServerApp. "
 | 
						|
    "Please check if you should also config these traits in "
 | 
						|
    "NotebookApp for your purpose.".format(
 | 
						|
        trait_name=trait_name,
 | 
						|
        extapp_name=extapp_name
 | 
						|
    )
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def EXTAPP_TO_SVAPP_SHIM_MSG(trait_name, extapp_name): return (
 | 
						|
    "'{trait_name}' has moved from {extapp_name} to "
 | 
						|
    "ServerApp. Be sure to update your config before "
 | 
						|
    "our next release.".format(
 | 
						|
        trait_name=trait_name,
 | 
						|
        extapp_name=extapp_name
 | 
						|
    )
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
def EXTAPP_TO_NBAPP_SHIM_MSG(trait_name, extapp_name): return (
 | 
						|
    "'{trait_name}' has moved from {extapp_name} to "
 | 
						|
    "NotebookApp. Be sure to update your config before "
 | 
						|
    "our next release.".format(
 | 
						|
        trait_name=trait_name,
 | 
						|
        extapp_name=extapp_name
 | 
						|
    )
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
# A tuple of traits that shouldn't be shimmed or throw any
 | 
						|
# warnings of any kind.
 | 
						|
IGNORED_TRAITS = ("open_browser", "log_level", "log_format", "default_url", "show_banner")
 | 
						|
 | 
						|
 | 
						|
class NotebookConfigShimMixin:
 | 
						|
    """A Mixin class for shimming configuration from
 | 
						|
    NotebookApp to ServerApp. This class handles warnings, errors,
 | 
						|
    etc.
 | 
						|
 | 
						|
    This class should be used during a transition period for apps
 | 
						|
    that are switching from depending on NotebookApp to ServerApp.
 | 
						|
 | 
						|
    After one release cycle, this class can be safely removed
 | 
						|
    from the inheriting class.
 | 
						|
 | 
						|
    TL;DR
 | 
						|
 | 
						|
    The entry point to shimming is at the `update_config` method.
 | 
						|
    Once traits are loaded, before updating config across all
 | 
						|
    configurable objects, this class injects a method to reroute
 | 
						|
    traits to their *most logical* classes.
 | 
						|
 | 
						|
    This class raises warnings when:
 | 
						|
        1. a trait has moved.
 | 
						|
        2. a trait is redundant across classes.
 | 
						|
 | 
						|
    Redundant traits across multiple classes now must be
 | 
						|
    configured separately, *or* removed from their old
 | 
						|
    location to avoid this warning.
 | 
						|
 | 
						|
    For a longer description on how individual traits are handled,
 | 
						|
    read the docstring under `shim_config_from_notebook_to_jupyter_server`.
 | 
						|
    """
 | 
						|
 | 
						|
    @wraps(JupyterApp.update_config)
 | 
						|
    def update_config(self, config):
 | 
						|
        # Shim traits to handle transition from NotebookApp to ServerApp
 | 
						|
        shimmed_config = self.shim_config_from_notebook_to_jupyter_server(
 | 
						|
            config)
 | 
						|
        super().update_config(shimmed_config)
 | 
						|
 | 
						|
    def shim_config_from_notebook_to_jupyter_server(self, config):
 | 
						|
        """Reorganizes a config object to reroute traits to their expected destinations
 | 
						|
        after the transition from NotebookApp to ServerApp.
 | 
						|
 | 
						|
        A detailed explanation of how traits are handled:
 | 
						|
 | 
						|
        1. If the argument is prefixed with `ServerApp`,
 | 
						|
            pass this trait to `ServerApp`.
 | 
						|
        2. If the argument is prefixed with `NotebookApp`,
 | 
						|
            * If the argument is a trait of `NotebookApp` *and* `ServerApp`:
 | 
						|
                1. Raise a warning—**for the extension developers**—that
 | 
						|
                    there's redundant traits.
 | 
						|
                2. Pass trait to `NotebookApp`.
 | 
						|
            * If the argument is a trait of just `ServerApp` only
 | 
						|
                (i.e. the trait moved from `NotebookApp` to `ServerApp`):
 | 
						|
                1. Raise a "this trait has moved" **for the user**.
 | 
						|
                3. Pass trait to `ServerApp`.
 | 
						|
            * If the argument is a trait of `NotebookApp` only, pass trait
 | 
						|
                to `NotebookApp`.
 | 
						|
            * If the argument is not found in any object, raise a
 | 
						|
                `"Trait not found."` error.
 | 
						|
        3. If the argument is prefixed with `ExtensionApp`:
 | 
						|
            * If the argument is a trait of `ExtensionApp`,
 | 
						|
                `NotebookApp`, and `ServerApp`,
 | 
						|
                1. Raise a warning about redundancy.
 | 
						|
                2. Pass to the ExtensionApp
 | 
						|
            * If the argument is a trait of `ExtensionApp` and `NotebookApp`,
 | 
						|
                1. Raise a warning about redundancy.
 | 
						|
                2. Pass to ExtensionApp.
 | 
						|
            * If the argument is a trait of `ExtensionApp` and `ServerApp`,
 | 
						|
                1. Raise a warning about redundancy.
 | 
						|
                2. Pass to ExtensionApp.
 | 
						|
            * If the argument is a trait of `ExtensionApp`.
 | 
						|
                1. Pass to ExtensionApp.
 | 
						|
            * If the argument is a trait of `NotebookApp` but not `ExtensionApp`,
 | 
						|
                1. Raise a warning that trait has likely moved to NotebookApp.
 | 
						|
                2. Pass to NotebookApp
 | 
						|
            * If the arguent is a trait of `ServerApp` but not `ExtensionApp`,
 | 
						|
                1. Raise a warning that the trait has likely moved to ServerApp.
 | 
						|
                2. Pass to ServerApp.
 | 
						|
            * else
 | 
						|
                * Raise a TraitError: "trait not found."
 | 
						|
        """
 | 
						|
        extapp_name = self.__class__.__name__
 | 
						|
 | 
						|
        # Pop out the various configurable objects that we need to evaluate.
 | 
						|
        nbapp_config = config.pop('NotebookApp', {})
 | 
						|
        svapp_config = config.pop('ServerApp', {})
 | 
						|
        extapp_config = config.pop(extapp_name, {})
 | 
						|
 | 
						|
        # Created shimmed configs.
 | 
						|
        # Leave the rest of the config alone.
 | 
						|
        config_shim = deepcopy(config)
 | 
						|
        svapp_config_shim = {}
 | 
						|
        nbapp_config_shim = {}
 | 
						|
        extapp_config_shim = {}
 | 
						|
 | 
						|
        extapp_traits = (
 | 
						|
            self.__class__.class_trait_names() +
 | 
						|
            ExtensionApp.class_trait_names()
 | 
						|
        )
 | 
						|
        svapp_traits = ServerApp.class_trait_names()
 | 
						|
        nbapp_traits = (
 | 
						|
            NotebookAppTraits.class_trait_names() +
 | 
						|
            ExtensionApp.class_trait_names()
 | 
						|
        )
 | 
						|
 | 
						|
        # 1. Handle ServerApp traits.
 | 
						|
        svapp_config_shim.update(svapp_config)
 | 
						|
 | 
						|
        # 2. Handle NotebookApp traits.
 | 
						|
        warning_msg = None
 | 
						|
        for trait_name, trait_value in nbapp_config.items():
 | 
						|
            in_svapp = trait_name in svapp_traits
 | 
						|
            in_nbapp = trait_name in nbapp_traits
 | 
						|
            if trait_name in IGNORED_TRAITS:
 | 
						|
                # Pass trait through without any warning message.
 | 
						|
                nbapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_svapp and in_nbapp:
 | 
						|
                warning_msg = NBAPP_AND_SVAPP_SHIM_MSG(trait_name)
 | 
						|
                nbapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_svapp:
 | 
						|
                warning_msg = NBAPP_TO_SVAPP_SHIM_MSG(trait_name)
 | 
						|
                svapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_nbapp:
 | 
						|
                nbapp_config_shim.update({trait_name: trait_value})
 | 
						|
            else:
 | 
						|
                raise TraitError("Trait, {}, not found.".format(trait_name))
 | 
						|
 | 
						|
            # Raise a warning if it's given.
 | 
						|
            if warning_msg:
 | 
						|
                self.log.warning(warning_msg)
 | 
						|
 | 
						|
        # 3. Handle ExtensionApp traits.
 | 
						|
        warning_msg = None
 | 
						|
        for trait_name, trait_value in extapp_config.items():
 | 
						|
            in_extapp = trait_name in extapp_traits
 | 
						|
            in_svapp = trait_name in svapp_traits
 | 
						|
            in_nbapp = trait_name in nbapp_traits
 | 
						|
            if trait_name in IGNORED_TRAITS:
 | 
						|
                # Pass trait through without any warning message.
 | 
						|
                extapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif all([in_extapp, in_svapp, in_nbapp]):
 | 
						|
                warning_msg = EXTAPP_AND_NBAPP_AND_SVAPP_SHIM_MSG(
 | 
						|
                    trait_name,
 | 
						|
                    extapp_name
 | 
						|
                )
 | 
						|
                extapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_extapp and in_svapp:
 | 
						|
                warning_msg = EXTAPP_AND_SVAPP_SHIM_MSG(
 | 
						|
                    trait_name,
 | 
						|
                    extapp_name
 | 
						|
                )
 | 
						|
                extapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_extapp and in_nbapp:
 | 
						|
                warning_msg = EXTAPP_AND_NBAPP_SHIM_MSG(
 | 
						|
                    trait_name,
 | 
						|
                    extapp_name
 | 
						|
                )
 | 
						|
                extapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_extapp:
 | 
						|
                extapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_svapp and in_nbapp:
 | 
						|
                warning_msg = NOT_EXTAPP_NBAPP_AND_SVAPP_SHIM_MSG(
 | 
						|
                    trait_name,
 | 
						|
                    extapp_name
 | 
						|
                )
 | 
						|
                svapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_svapp:
 | 
						|
                warning_msg = EXTAPP_TO_SVAPP_SHIM_MSG(
 | 
						|
                    trait_name,
 | 
						|
                    extapp_name
 | 
						|
                )
 | 
						|
                svapp_config_shim.update({trait_name: trait_value})
 | 
						|
            elif in_nbapp:
 | 
						|
                warning_msg = EXTAPP_TO_NBAPP_SHIM_MSG(
 | 
						|
                    trait_name,
 | 
						|
                    extapp_name
 | 
						|
                )
 | 
						|
                nbapp_config_shim.update({trait_name: trait_value})
 | 
						|
            else:
 | 
						|
                raise TraitError("Trait, {}, not found.".format(trait_name))
 | 
						|
 | 
						|
            # Raise warning if one is given
 | 
						|
            if warning_msg:
 | 
						|
                self.log.warning(warning_msg)
 | 
						|
 | 
						|
        # Build config for shimmed traits.
 | 
						|
        new_config = Config({
 | 
						|
            'NotebookApp': nbapp_config_shim,
 | 
						|
            'ServerApp': svapp_config_shim,
 | 
						|
        })
 | 
						|
        if extapp_config_shim:
 | 
						|
            new_config.update(Config({
 | 
						|
                self.__class__.__name__: extapp_config_shim
 | 
						|
            }))
 | 
						|
        # Update the full config with new values
 | 
						|
        config_shim.update(new_config)
 | 
						|
        return config_shim
 |