Skip to content

Commit

Permalink
Entrypoints can be trailtlets Configurable
Browse files Browse the repository at this point in the history
This means a custom proxy can be installed, and configured using traitlets in a standard jupyter_server_config file
  • Loading branch information
manics committed Nov 6, 2024
1 parent c01de61 commit 297eda5
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 5 deletions.
7 changes: 6 additions & 1 deletion jupyter_server_proxy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from ._version import __version__ # noqa
from .api import IconHandler, ServersInfoHandler
from .config import ServerProcess, ServerProcessEntryPoint
from .config import ServerProxy as ServerProxyConfig
from .config import get_entrypoint_server_processes, make_handlers, make_server_process
from .handlers import setup_handlers
Expand Down Expand Up @@ -45,7 +46,9 @@ def _load_jupyter_server_extension(nbapp):
make_server_process(name, server_process_config, serverproxy_config)
for name, server_process_config in serverproxy_config.servers.items()
]
server_processes += get_entrypoint_server_processes(serverproxy_config)
server_processes += get_entrypoint_server_processes(
serverproxy_config, parent=nbapp
)
server_handlers = make_handlers(base_url, server_processes)
nbapp.web_app.add_handlers(".*", server_handlers)

Expand Down Expand Up @@ -81,3 +84,5 @@ def _load_jupyter_server_extension(nbapp):
# For backward compatibility
load_jupyter_server_extension = _load_jupyter_server_extension
_jupyter_server_extension_paths = _jupyter_server_extension_points

__all__ = ["ServerProcess", "ServerProcessEntryPoint"]
31 changes: 27 additions & 4 deletions jupyter_server_proxy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def _default_path_info(self):
)


class ServerProcess(Configurable):
class _ServerProcess(Configurable):
name = Unicode(help="Name of the server").tag(config=True)

command = List(
Expand Down Expand Up @@ -264,6 +264,22 @@ def cats_only(response, path):
).tag(config=True)


class ServerProcess(_ServerProcess):
"""
A configurable server process for single standalone servers.
This is separate from ServerProcessEntryPoint so that we can configure it
independently of ServerProcessEntryPoint
"""


class ServerProcessEntryPoint(_ServerProcess):
"""
A ServeProcess entrypoint that is a Configurable.
This is separate from ServerProcess so that we can configure it
independently of ServerProcess
"""


def _make_proxy_handler(sp: ServerProcess):
"""
Create an appropriate handler with given parameters
Expand Down Expand Up @@ -319,16 +335,23 @@ def get_timeout(self):
return _Proxy


def get_entrypoint_server_processes(serverproxy_config):
def get_entrypoint_server_processes(serverproxy_config, parent):
sps = []
for entry_point in entry_points(group="jupyter_serverproxy_servers"):
name = entry_point.name
try:
server_process_config = entry_point.load()()
server_process_callable = entry_point.load()
if issubclass(server_process_callable, ServerProcessEntryPoint):
server_process = server_process_callable(name=name, parent=parent)
sps.append(server_process)
else:
server_process_config = server_process_callable()
sps.append(
make_server_process(name, server_process_config, serverproxy_config)
)
except Exception as e:
warn(f"entry_point {name} was unable to be loaded: {str(e)}")
continue
sps.append(make_server_process(name, server_process_config, serverproxy_config))
return sps


Expand Down
6 changes: 6 additions & 0 deletions tests/resources/jupyter_server_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ def my_env():
return {"MYVAR": "String with escaped {{var}}"}


# Traitlets configuration for test-serverprocessentrypoint in the dummyentrypoint package
c.CustomServerProcessEntryPoint.request_headers_override = {
"X-Custom-Header": "custom-configurable"
}


c.ServerProxy.servers = {
"python-http": {
"command": [sys.executable, _get_path("httpinfo.py"), "--port={port}"],
Expand Down
8 changes: 8 additions & 0 deletions tests/test_proxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,3 +528,11 @@ async def test_server_proxy_rawsocket(
await conn.write_message(msg)
res = await conn.read_message()
assert res == msg.swapcase()


def test_server_configurable_class(a_server_port_and_token: Tuple[int, str]) -> None:
PORT, TOKEN = a_server_port_and_token
r = request_get(PORT, "/test-serverprocessentrypoint/", TOKEN, host="127.0.0.1")
assert r.code == 200
s = r.read().decode("ascii")
assert "X-Custom-Header: custom-configurable\n" in s

0 comments on commit 297eda5

Please sign in to comment.