Skip to content

Commit 297eda5

Browse files
committed
Entrypoints can be trailtlets Configurable
This means a custom proxy can be installed, and configured using traitlets in a standard jupyter_server_config file
1 parent c01de61 commit 297eda5

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

jupyter_server_proxy/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from ._version import __version__ # noqa
44
from .api import IconHandler, ServersInfoHandler
5+
from .config import ServerProcess, ServerProcessEntryPoint
56
from .config import ServerProxy as ServerProxyConfig
67
from .config import get_entrypoint_server_processes, make_handlers, make_server_process
78
from .handlers import setup_handlers
@@ -45,7 +46,9 @@ def _load_jupyter_server_extension(nbapp):
4546
make_server_process(name, server_process_config, serverproxy_config)
4647
for name, server_process_config in serverproxy_config.servers.items()
4748
]
48-
server_processes += get_entrypoint_server_processes(serverproxy_config)
49+
server_processes += get_entrypoint_server_processes(
50+
serverproxy_config, parent=nbapp
51+
)
4952
server_handlers = make_handlers(base_url, server_processes)
5053
nbapp.web_app.add_handlers(".*", server_handlers)
5154

@@ -81,3 +84,5 @@ def _load_jupyter_server_extension(nbapp):
8184
# For backward compatibility
8285
load_jupyter_server_extension = _load_jupyter_server_extension
8386
_jupyter_server_extension_paths = _jupyter_server_extension_points
87+
88+
__all__ = ["ServerProcess", "ServerProcessEntryPoint"]

jupyter_server_proxy/config.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def _default_path_info(self):
7676
)
7777

7878

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

8282
command = List(
@@ -264,6 +264,22 @@ def cats_only(response, path):
264264
).tag(config=True)
265265

266266

267+
class ServerProcess(_ServerProcess):
268+
"""
269+
A configurable server process for single standalone servers.
270+
This is separate from ServerProcessEntryPoint so that we can configure it
271+
independently of ServerProcessEntryPoint
272+
"""
273+
274+
275+
class ServerProcessEntryPoint(_ServerProcess):
276+
"""
277+
A ServeProcess entrypoint that is a Configurable.
278+
This is separate from ServerProcess so that we can configure it
279+
independently of ServerProcess
280+
"""
281+
282+
267283
def _make_proxy_handler(sp: ServerProcess):
268284
"""
269285
Create an appropriate handler with given parameters
@@ -319,16 +335,23 @@ def get_timeout(self):
319335
return _Proxy
320336

321337

322-
def get_entrypoint_server_processes(serverproxy_config):
338+
def get_entrypoint_server_processes(serverproxy_config, parent):
323339
sps = []
324340
for entry_point in entry_points(group="jupyter_serverproxy_servers"):
325341
name = entry_point.name
326342
try:
327-
server_process_config = entry_point.load()()
343+
server_process_callable = entry_point.load()
344+
if issubclass(server_process_callable, ServerProcessEntryPoint):
345+
server_process = server_process_callable(name=name, parent=parent)
346+
sps.append(server_process)
347+
else:
348+
server_process_config = server_process_callable()
349+
sps.append(
350+
make_server_process(name, server_process_config, serverproxy_config)
351+
)
328352
except Exception as e:
329353
warn(f"entry_point {name} was unable to be loaded: {str(e)}")
330354
continue
331-
sps.append(make_server_process(name, server_process_config, serverproxy_config))
332355
return sps
333356

334357

tests/resources/jupyter_server_config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ def my_env():
5151
return {"MYVAR": "String with escaped {{var}}"}
5252

5353

54+
# Traitlets configuration for test-serverprocessentrypoint in the dummyentrypoint package
55+
c.CustomServerProcessEntryPoint.request_headers_override = {
56+
"X-Custom-Header": "custom-configurable"
57+
}
58+
59+
5460
c.ServerProxy.servers = {
5561
"python-http": {
5662
"command": [sys.executable, _get_path("httpinfo.py"), "--port={port}"],

tests/test_proxies.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,11 @@ async def test_server_proxy_rawsocket(
528528
await conn.write_message(msg)
529529
res = await conn.read_message()
530530
assert res == msg.swapcase()
531+
532+
533+
def test_server_configurable_class(a_server_port_and_token: Tuple[int, str]) -> None:
534+
PORT, TOKEN = a_server_port_and_token
535+
r = request_get(PORT, "/test-serverprocessentrypoint/", TOKEN, host="127.0.0.1")
536+
assert r.code == 200
537+
s = r.read().decode("ascii")
538+
assert "X-Custom-Header: custom-configurable\n" in s

0 commit comments

Comments
 (0)