-
Notifications
You must be signed in to change notification settings - Fork 310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
kernel_manager_class configurable by a server extension? #207
Comments
Thanks for opening this discussion David. This is tricky since this is a singleton. I suppose this becomes a question for how we support "core" extensions - should these be done via server extensions or the only via the subclassing/mixin approach mentioned in the service composition issue? Because of the singularity, I'm inclined to say these should not be configurable by server extensions but am open to discussing further. That said because these are configurable anyway, why should a server extension be prevented from doing something that can be done from the command line? (Hmm, one answer might be because singularity is still preserved via command line settings, while multiple server extensions could compete with each other - last setter wins.) |
Thanks for the explanation Kevin. |
Hmm. This is the multi kernel manager so I think we have to limit to one instance. I hate that the name is so generic. We probably can't change the trait KernelProviders enable the ability to "bring your own kernel manager", but those will still be invoked via the single "multi" kernel manager instance. In this sense, one could view a provider as a special kind of server extension. |
Actually, this changed in #180. Jupyter server extensions configs are gathered before
In short, I think this should already be possible. Let me know if you are experiencing something different (I might have misunderstood your question). |
Thanks Zach, that was very helpful. |
Ah, I see. You're right—your extension's Just an aside here, you could use the |
We could also add a For your use-case, this would look something like: # myextension/config.py
def _get_server_config():
return {
"ServerApp": {
"kernel_manager_class" : ...,
}
} # myextension/__init__.py
def _jupyter_server_extension_paths():
"""
Returns a list of dictionaries with metadata describing
where to find the `_load_jupyter_server_extension` function.
"""
return [
{
"module": "myextension",
"config": "myextension.config"
}
] If this seems like a reasonable feature, we would need to add logic to the server to look for this "config" key in the |
Yes it looks like a reasonable feature to have. |
Given that the trait enforces the override be a class of Btw, I would love to rename this trait to something more like
|
As @kevin-bates mentioned—this becomes a little messy if multiple extensions try to configure the same trait. I'm not sure how to reconcile that, because there is no clear order to which extensions should be loaded first vs. last. The only solution I can come up with is that extension authors should require their users to manually set the shared trait directly in their ServerApp config, rather than allow all extensions to affect any ServerApp config automatically. |
I believe we should avoid (and even enforce) extension authors to make any change to the core serverapp. This should be IMHO something only accessible to the Administrator of the server. |
@davidbrochart - is there a particular use case for allowing an extension to bring its own MappingKernelManager (subclass) implementation? Just wondering if it makes sense to bake that into server (i.e., MappingKernelManager) in the first place. To Eric's point, I think any Singleton is in jeopardy in the server extension discussion w/o saying "last setter wins". There was a way to say that a given extension is exclusive and will not co-exist with other extensions - is that right? (Sorry, I should know this and haven't spent enough time here.) If so, would it be possible to enforce that only those "exclusive" extensions can set traits corresponding to singletons? I suppose you could set up an |
It is for Voila, I'd like to have an |
Actually, we should switch jupyter server to always be async now. This will be the case when moving to providers anyway. The non async version is purely to reduce risk, but in server, we are free to live on the edge! 😄 FWIW, I've been using Notebook's AsyncMappingKernelManager in EG for a while - just waiting on the next NB release to merge it. Its really nice from the throughput perspective! |
Shoot, I went to flip the switch here and immediately ran into this block: https://github.com/jupyter/jupyter_server/blob/master/jupyter_server/serverapp.py#L1262-L1269 Since Lab still needs to support 3.5, I don't think switching at this time is the right step. Perhaps we could make the change through Voila and let this use case be a litmus test for server extension overrides? |
I think we can make the case that Jupyterlab 3.0 does not need to support Python 3.5. I'll bring it up at our next meeting. |
I like that idea to expose to extension authors ways to interact with the core server settings. I would put on this feature two requirements:
|
This issue popped up in jupyter-fs. This extension needs to automatically configure the Server's contents manager class when enabled. This convinces me that we need a way to load server config from extensions. I agree with @echarles. We should have a list of traits that extensions can override, and config+CLI supersedes the extension's config (though it should throw a warning). We also need a way to check for conflicting config if multiple extensions touch the same trait. My initial thought is that we don't load conflicting extensions and throw warnings saying that one of the extensions must be disabled. |
That would be a great feature to bring flexibility while ensuring stability and debugability. To start, the limited list of trait could be limited to just two (kernel_manager and content_manager). We could add more on request. I would be tempted to fail fast on conflicting extensions. I am OK also with a more user-friendly warning but would love to have a real visible multi-line warning to avoid the log message to be lost in the other log messages. |
#248 offers a simple way to configure the underlying Jupyter Server from an ExtensionApp. It exposes a To address the issue mentioned here, you'll want to write something like: class MyApp(ExtensionApp):
...
serverapp_config = {
"kernel_manager_class" : ...,
...
} |
As Zach mentions, #248 enables the ability for an ExtensionApp to adjust server config and given that @davidbrochart - would you agree? |
I agree, thanks! |
@Zsailer @kevin-bates Wait wait. I just tried rewriting the import warnings
from jupyter_server.extension.application import ExtensionApp
from jupyter_server.utils import url_path_join
from ._version import __version__ # noqa: F401
from .metamanager import MetaManager, MetaManagerHandler
_mm_config_warning_msg = """Misconfiguration of MetaManager. Please add:
"ServerApp": {
"contents_manager_class": "jupyterfs.metamanager.MetaManager"
}
to your Notebook Server config."""
def _jupyter_server_extension_paths():
return [{
"module": "jupyterfs.extension",
"app": JupyterfsApp
}]
class JupyterfsApp(ExtensionApp):
# name = "jupyterfs.extension"
serverapp_config = {
"contents_manager_class": "jupyterfs.metamanager.MetaManager"
}
# def initialize_handlers(self):
@classmethod
def _load_jupyter_server_extension(cls, serverapp):
"""
Called when the extension is loaded.
Args:
nb_server_app (NotebookWebApplication): handle to the Notebook webserver instance.
"""
super()._load_jupyter_server_extension(serverapp)
web_app = serverapp.web_app
base_url = web_app.settings["base_url"]
host_pattern = ".*$"
if not isinstance(serverapp.contents_manager, MetaManager):
warnings.warn(_mm_config_warning_msg)
return
resources_url = "jupyterfs/resources"
print("Installing jupyter-fs resources handler on path %s" % url_path_join(base_url, resources_url))
web_app.add_handlers(host_pattern, [(url_path_join(base_url, resources_url), MetaManagerHandler)]) What I'm seeing is that the |
Hi @telamonian - thanks for raising this issue. Since David's original use-case was actually resolved by the switch to using async kernel management by default (although that doesn't necessarily match the title of this issue) and your issue is relative to the general ability to introduce this functionality via #248, would you mind opening a new issue specific to your attempt to set the ContentsManager? I'd rather keep this issue closed and party on a new issue that is more of a bug issue than a feature request issue such as was originally raised here. |
k |
Does it make sense to have the
ServerApp.kernel_manager_class
trait configurable by a server extension? Today it doesn't seem to be possible as the extensions are loaded afterinit_configurables()
, where the kernel manager is created.The text was updated successfully, but these errors were encountered: