| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- 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
|