# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from jupyter_server.extension.application import ExtensionApp from types import SimpleNamespace from unittest.mock import Mock, patch import pytest from cylc.uiserver.authorise import (Authorization, AuthorizationMiddleware, get_list_of_mutations, parse_group_ids) log = ExtensionApp().log CONTROL_OPS = [ "clean", "ext_trigger", "hold", "kill", "message", "pause", "play", "poll", "release", "release_hold_point", "reload", "remove", "resume",
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 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.") # 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 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.") # 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