Skip to content
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

Custom page config hook #1495

Merged
merged 19 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions voila/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,22 @@ def hook(req: tornado.web.RequestHandler,
),
)

get_page_config_hook = Callable(
dfguerrerom marked this conversation as resolved.
Show resolved Hide resolved
default_value=lambda page_config, **kwargs: page_config,
dfguerrerom marked this conversation as resolved.
Show resolved Hide resolved
config=True,
help=_(
"""A function that is called to modify the page config for a given notebook.
Should be of the form:

def hook_fn(page_config, **kwargs) -> Dict
dfguerrerom marked this conversation as resolved.
Show resolved Hide resolved

The hook receives the default page_config dictionary and should return a dictionary
that will be passed to the template as the `page_config` variable and the
NotebookRenderer. This can be used to pass custom configuration.
"""
),
)

cookie_secret = Bytes(
b"",
config=True,
Expand Down Expand Up @@ -594,6 +610,7 @@ def init_settings(self) -> Dict:
self.voila_configuration.multi_kernel_manager_class,
preheat_kernel,
pool_size,
get_page_config_hook=self.get_page_config_hook,
)
self.kernel_manager = kernel_manager_class(
parent=self,
Expand Down Expand Up @@ -760,18 +777,29 @@ def init_handlers(self) -> List:
"config": self.config,
"voila_configuration": self.voila_configuration,
"prelaunch_hook": self.prelaunch_hook,
"get_page_config_hook": self.get_page_config_hook,
},
)
)
else:
self.log.debug("serving directory: %r", self.root_dir)
handlers.extend(
[
(self.server_url, TornadoVoilaTreeHandler, tree_handler_conf),
(
self.server_url,
TornadoVoilaTreeHandler,
{
"voila_configuration": self.voila_configuration,
"get_page_config_hook": self.get_page_config_hook,
},
),
(
url_path_join(self.server_url, r"/voila/tree" + path_regex),
TornadoVoilaTreeHandler,
tree_handler_conf,
{
"voila_configuration": self.voila_configuration,
"get_page_config_hook": self.get_page_config_hook,
},
),
(
url_path_join(self.server_url, r"/voila/render/(.*)"),
Expand All @@ -781,6 +809,7 @@ def init_handlers(self) -> List:
"config": self.config,
"voila_configuration": self.voila_configuration,
"prelaunch_hook": self.prelaunch_hook,
"get_page_config_hook": self.get_page_config_hook,
},
),
# On serving a directory, expose the content handler.
Expand Down
24 changes: 18 additions & 6 deletions voila/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ def initialize(self, **kwargs):
self.traitlet_config = kwargs.pop("config", None)
self.voila_configuration: VoilaConfiguration = kwargs["voila_configuration"]
self.prelaunch_hook = kwargs.get("prelaunch_hook", None)
self.get_page_config_hook = kwargs.get(
"get_page_config_hook", lambda page_config, **kwargs: page_config
)

# we want to avoid starting multiple kernels due to template mistakes
self.kernel_started = False

Expand Down Expand Up @@ -186,6 +190,19 @@ async def get_generator(self, path=None):
return
mathjax_config = self.settings.get("mathjax_config")
mathjax_url = self.settings.get("mathjax_url")

page_config_kwargs = {
"base_url": self.base_url,
"settings": self.settings,
"log": self.log,
"voila_configuration": self.voila_configuration,
}
page_config = self.get_page_config_hook(
get_page_config(**page_config_kwargs),
**page_config_kwargs,
notebook_path=notebook_path,
)

gen = NotebookRenderer(
request_handler=self,
voila_configuration=self.voila_configuration,
Expand All @@ -197,12 +214,7 @@ async def get_generator(self, path=None):
base_url=self.base_url,
kernel_spec_manager=self.kernel_spec_manager,
prelaunch_hook=self.prelaunch_hook,
page_config=get_page_config(
base_url=self.base_url,
settings=self.settings,
log=self.log,
voila_configuration=self.voila_configuration,
),
page_config=page_config,
mathjax_config=mathjax_config,
mathjax_url=mathjax_url,
)
Expand Down
21 changes: 16 additions & 5 deletions voila/tornado/treehandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@


class TornadoVoilaTreeHandler(VoilaTreeHandler):
def initialize(self, **kwargs):
super().initialize(**kwargs)
self.get_page_config_hook = kwargs.get(
"get_page_config_hook", lambda page_config, **kwargs: page_config
)

@web.authenticated
async def get(self, path=""):
cm = self.contents_manager
Expand Down Expand Up @@ -58,11 +64,16 @@ def allowed_content(content):

theme_arg = self.validate_theme(theme_arg, classic_tree)

page_config = get_page_config(
base_url=self.base_url,
settings=self.settings,
log=self.log,
voila_configuration=self.voila_configuration,
page_config_kwargs = {
"base_url": self.base_url,
"settings": self.settings,
"log": self.log,
"voila_configuration": self.voila_configuration,
}
page_config = self.get_page_config_hook(
get_page_config(**page_config_kwargs),
**page_config_kwargs,
notebook_path=path,
)
page_config["jupyterLabTheme"] = theme_arg
page_config["frontend"] = "voila"
Expand Down
18 changes: 16 additions & 2 deletions voila/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
from copy import deepcopy
from functools import partial
from pathlib import Path
from typing import Awaitable, Dict, List
from typing import Awaitable, Dict, List, Any
from logging import Logger

import websockets
from jupyter_core.paths import jupyter_path
Expand Down Expand Up @@ -89,7 +90,20 @@ async def _get_request_info(ws_url: str) -> Awaitable:
return ri


def get_page_config(base_url, settings, log, voila_configuration: VoilaConfiguration):
def get_page_config(
base_url: str,
settings: Dict[str, Any],
log: Logger,
voila_configuration: VoilaConfiguration,
):
"""Get the page configuration for Voila.

Args:
base_url (str): The base URL of the Voila application.
settings (Dict[str, Any]): The settings of the Voila application.
log (Logger): The logger instance.
voila_configuration (VoilaConfiguration): The Voila configuration instance.
"""
page_config = {
"appVersion": __version__,
"appUrl": "voila/",
Expand Down
29 changes: 21 additions & 8 deletions voila/voila_kernel_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import os
import re
from pathlib import Path
from typing import Awaitable
from typing import Awaitable, Callable
from typing import Dict as TypeDict
from typing import List as TypeList
from typing import Tuple, Type, TypeVar, Union
Expand All @@ -34,7 +34,10 @@ async def wait_before(delay: float, aw: Awaitable) -> Awaitable:


def voila_kernel_manager_factory(
base_class: Type[T], preheat_kernel: bool, default_pool_size: int
base_class: Type[T],
preheat_kernel: bool,
default_pool_size: int,
get_page_config_hook: Callable = lambda page_config, **kwargs: page_config,
) -> T:
"""
Decorator used to make a normal kernel manager compatible with pre-heated
Expand All @@ -50,10 +53,12 @@ def voila_kernel_manager_factory(
- preheat_kernel (Bool): Flag to decorate the input class
- default_pool_size (int): Size of pre-heated kernel pool for each notebook.
Zero or negative number means disabled
- get_page_config_hook (Callable): Hook to modify the default page config.

Returns:
T: Decorated class
"""

if not preheat_kernel:

class NormalKernelManager(base_class):
Expand Down Expand Up @@ -388,6 +393,19 @@ def _notebook_renderer_factory(
settings = self.parent.app.settings
mathjax_config = settings.get("mathjax_config")
mathjax_url = settings.get("mathjax_url")

page_config_kwargs = {
"base_url": self.parent.base_url,
"settings": self.parent.app.settings,
"log": self.parent.log,
"voila_configuration": voila_configuration,
}
page_config = get_page_config_hook(
get_page_config(**page_config_kwargs),
**page_config_kwargs,
notebook_path=notebook_path,
)

return NotebookRenderer(
voila_configuration=voila_configuration,
traitlet_config=self.parent.config,
Expand All @@ -397,12 +415,7 @@ def _notebook_renderer_factory(
contents_manager=self.parent.contents_manager,
base_url=self.parent.base_url,
kernel_spec_manager=self.parent.kernel_spec_manager,
page_config=get_page_config(
base_url=self.parent.base_url,
settings=self.parent.app.settings,
log=self.parent.log,
voila_configuration=voila_configuration,
),
page_config=page_config,
mathjax_config=mathjax_config,
mathjax_url=mathjax_url,
)
Expand Down