From c2f66d56b0ec4bbcb4bf8c03c855f9eb8f302f8c Mon Sep 17 00:00:00 2001 From: Sam Bloomquist Date: Thu, 8 Dec 2022 10:11:30 -0600 Subject: [PATCH 1/4] formatting fix --- jupyter_server/services/kernelspecs/handlers.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/jupyter_server/services/kernelspecs/handlers.py b/jupyter_server/services/kernelspecs/handlers.py index 6cd5d9dcba..c862819d2b 100644 --- a/jupyter_server/services/kernelspecs/handlers.py +++ b/jupyter_server/services/kernelspecs/handlers.py @@ -48,6 +48,18 @@ def is_kernelspec_model(spec_dict): ) +def gateway_kernelspec_model(handler, name, spec_dict, resources): + """Helper method to prepend the server's base_url, if configured, to the kernelspec resource path. + This will occur when using a gateway + """ + d = {"name": name, "spec": spec_dict, "resources": {}} + + for resource_name in resources: + resource_path = url_path_join(handler.base_url, resources[resource_name]) + d["resources"][resource_name] = resource_path + return d + + class KernelSpecsAPIHandler(APIHandler): auth_resource = AUTH_RESOURCE @@ -65,7 +77,9 @@ async def get(self): for kernel_name, kernel_info in kspecs.items(): try: if is_kernelspec_model(kernel_info): - d = kernel_info + d = gateway_kernelspec_model( + self, kernel_name, kernel_info["spec"], kernel_info["resources"] + ) else: d = kernelspec_model( self, From c48da5291da89a860a2cf5873bd25c9d0833c664 Mon Sep 17 00:00:00 2001 From: Sam Bloomquist Date: Sat, 10 Dec 2022 10:28:32 -0600 Subject: [PATCH 2/4] Moved method into gateway classes --- jupyter_server/gateway/managers.py | 22 ++++++++++++++++++- .../services/kernelspecs/handlers.py | 4 +--- tests/test_gateway.py | 6 ++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/jupyter_server/gateway/managers.py b/jupyter_server/gateway/managers.py index 968d5f2d00..f60e1a8a2a 100644 --- a/jupyter_server/gateway/managers.py +++ b/jupyter_server/gateway/managers.py @@ -200,9 +200,28 @@ def _get_endpoint_for_user_filter(default_endpoint): return "?user=".join([default_endpoint, kernel_user]) return default_endpoint + def _replace_path_kernelspec_resources(self, kernel_specs): + """Helper method that replaces any gateway base_url with the server's base_url + This enables clients to properly route through jupyter_server to a gateway + for kernel resources such as logo files + """ + kernelspecs = kernel_specs["kernelspecs"] + for kernel_name in kernelspecs: + resources = kernelspecs[kernel_name]["resources"] + for resource_name in resources: + original_path = resources[resource_name] + split_eg_base_url = str.rsplit(original_path, sep="/kernelspecs/", maxsplit=1) + kernel_specs["kernelspecs"][kernel_name]["resources"][ + resource_name + ] = url_path_join(self.parent.base_url, "/kernelspecs", split_eg_base_url[1]) + self.log.debug( + f"Replaced original kernel resource path {original_path} with new " + f"path {kernel_specs['kernelspecs'][kernel_name]['resources'][resource_name]}" + ) + return kernel_specs + def _get_kernelspecs_endpoint_url(self, kernel_name=None): """Builds a url for the kernels endpoint - Parameters ---------- kernel_name : kernel name (optional) @@ -237,6 +256,7 @@ async def list_kernel_specs(self): self.log.debug(f"Request list kernel specs at: {kernel_spec_url}") response = await gateway_request(kernel_spec_url, method="GET") kernel_specs = json_decode(response.body) + kernel_specs = self._replace_path_kernelspec_resources(kernel_specs) return kernel_specs async def get_kernel_spec(self, kernel_name, **kwargs): diff --git a/jupyter_server/services/kernelspecs/handlers.py b/jupyter_server/services/kernelspecs/handlers.py index c862819d2b..0f57cfe07d 100644 --- a/jupyter_server/services/kernelspecs/handlers.py +++ b/jupyter_server/services/kernelspecs/handlers.py @@ -77,9 +77,7 @@ async def get(self): for kernel_name, kernel_info in kspecs.items(): try: if is_kernelspec_model(kernel_info): - d = gateway_kernelspec_model( - self, kernel_name, kernel_info["spec"], kernel_info["resources"] - ) + d = kernel_info else: d = kernelspec_model( self, diff --git a/tests/test_gateway.py b/tests/test_gateway.py index 7515e2a947..430317e3f1 100644 --- a/tests/test_gateway.py +++ b/tests/test_gateway.py @@ -38,7 +38,11 @@ def generate_kernelspec(name): "metadata": {}, } } - kernelspec_stanza = {"name": name, "spec": spec_stanza, "resources": {}} + kernelspec_stanza = { + "name": name, + "spec": spec_stanza, + "resources": {"logo-64x64": f"f/kernelspecs/{name}/logo-64x64.png"}, + } return kernelspec_stanza From eba2ba33cadc7295f5366a2b9e509505d677641a Mon Sep 17 00:00:00 2001 From: Sam Bloomquist Date: Sat, 10 Dec 2022 10:32:00 -0600 Subject: [PATCH 3/4] Remove moved method --- jupyter_server/services/kernelspecs/handlers.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/jupyter_server/services/kernelspecs/handlers.py b/jupyter_server/services/kernelspecs/handlers.py index 0f57cfe07d..6cd5d9dcba 100644 --- a/jupyter_server/services/kernelspecs/handlers.py +++ b/jupyter_server/services/kernelspecs/handlers.py @@ -48,18 +48,6 @@ def is_kernelspec_model(spec_dict): ) -def gateway_kernelspec_model(handler, name, spec_dict, resources): - """Helper method to prepend the server's base_url, if configured, to the kernelspec resource path. - This will occur when using a gateway - """ - d = {"name": name, "spec": spec_dict, "resources": {}} - - for resource_name in resources: - resource_path = url_path_join(handler.base_url, resources[resource_name]) - d["resources"][resource_name] = resource_path - return d - - class KernelSpecsAPIHandler(APIHandler): auth_resource = AUTH_RESOURCE From 2c8cb2e6d637ef2a4c6688542f8f6322614e3fa0 Mon Sep 17 00:00:00 2001 From: Sam Bloomquist Date: Mon, 12 Dec 2022 16:16:13 -0600 Subject: [PATCH 4/4] conditional on debug log, validate base_url in testcase --- jupyter_server/gateway/managers.py | 14 +++++++------- tests/test_gateway.py | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/jupyter_server/gateway/managers.py b/jupyter_server/gateway/managers.py index f60e1a8a2a..3d9b4e64dd 100644 --- a/jupyter_server/gateway/managers.py +++ b/jupyter_server/gateway/managers.py @@ -211,13 +211,13 @@ def _replace_path_kernelspec_resources(self, kernel_specs): for resource_name in resources: original_path = resources[resource_name] split_eg_base_url = str.rsplit(original_path, sep="/kernelspecs/", maxsplit=1) - kernel_specs["kernelspecs"][kernel_name]["resources"][ - resource_name - ] = url_path_join(self.parent.base_url, "/kernelspecs", split_eg_base_url[1]) - self.log.debug( - f"Replaced original kernel resource path {original_path} with new " - f"path {kernel_specs['kernelspecs'][kernel_name]['resources'][resource_name]}" - ) + new_path = url_path_join(self.parent.base_url, "kernelspecs", split_eg_base_url[1]) + kernel_specs["kernelspecs"][kernel_name]["resources"][resource_name] = new_path + if original_path != new_path: + self.log.debug( + f"Replaced original kernel resource path {original_path} with new " + f"path {kernel_specs['kernelspecs'][kernel_name]['resources'][resource_name]}" + ) return kernel_specs def _get_kernelspecs_endpoint_url(self, kernel_name=None): diff --git a/tests/test_gateway.py b/tests/test_gateway.py index 430317e3f1..2c4817f786 100644 --- a/tests/test_gateway.py +++ b/tests/test_gateway.py @@ -407,6 +407,9 @@ async def test_gateway_get_kernelspecs(init_gateway, jp_fetch, jp_serverapp): kspecs = content.get("kernelspecs") assert len(kspecs) == 2 assert kspecs.get("kspec_bar").get("name") == "kspec_bar" + assert ( + kspecs.get("kspec_bar").get("resources")["logo-64x64"].startswith(jp_serverapp.base_url) + ) async def test_gateway_get_named_kernelspec(init_gateway, jp_fetch):