Skip to content

Commit a457763

Browse files
Separate Tornado handlers into their own class (#1330)
* Separate Tornado handlers into their own class * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Move Tornado-specific handlers to tornado directory --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent f416ab5 commit a457763

File tree

6 files changed

+105
-76
lines changed

6 files changed

+105
-76
lines changed

voila/app.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
from .configuration import VoilaConfiguration
6868
from .execute import VoilaExecutor
6969
from .exporter import VoilaExporter
70-
from .handler import VoilaHandler
7170
from .paths import ROOT, STATIC_ROOT, collect_static_paths, collect_template_paths
7271
from .request_info_handler import RequestInfoSocketHandler
7372
from .shutdown_kernel_handler import VoilaShutdownKernelHandler
@@ -76,7 +75,8 @@
7675
TemplateStaticFileHandler,
7776
WhiteListFileHandler,
7877
)
79-
from .treehandler import VoilaTreeHandler
78+
from .tornado.handler import TornadoVoilaHandler
79+
from .tornado.treehandler import TornadoVoilaTreeHandler
8080
from .utils import create_include_assets_functions
8181
from .voila_kernel_manager import voila_kernel_manager_factory
8282

@@ -684,7 +684,7 @@ def init_handlers(self) -> List:
684684
handlers.append(
685685
(
686686
url_path_join(self.server_url, r"/(.*)"),
687-
VoilaHandler,
687+
TornadoVoilaHandler,
688688
{
689689
"notebook_path": os.path.relpath(
690690
self.notebook_path, self.root_dir
@@ -700,15 +700,15 @@ def init_handlers(self) -> List:
700700
self.log.debug("serving directory: %r", self.root_dir)
701701
handlers.extend(
702702
[
703-
(self.server_url, VoilaTreeHandler, tree_handler_conf),
703+
(self.server_url, TornadoVoilaTreeHandler, tree_handler_conf),
704704
(
705705
url_path_join(self.server_url, r"/voila/tree" + path_regex),
706-
VoilaTreeHandler,
706+
TornadoVoilaTreeHandler,
707707
tree_handler_conf,
708708
),
709709
(
710710
url_path_join(self.server_url, r"/voila/render/(.*)"),
711-
VoilaHandler,
711+
TornadoVoilaHandler,
712712
{
713713
"template_paths": self.template_paths,
714714
"config": self.config,

voila/handler.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from pathlib import Path
1414
from typing import Dict
1515

16-
import tornado.web
1716
from jupyter_server.base.handlers import JupyterHandler
1817
from jupyter_server.utils import url_path_join
1918
from nbclient.util import ensure_async
@@ -255,13 +254,6 @@ async def put_html():
255254
break
256255
yield html_snippet
257256

258-
@tornado.web.authenticated
259-
async def get(self, path=None):
260-
gen = self.get_generator(path=path)
261-
async for html in gen:
262-
self.write(html)
263-
self.flush()
264-
265257
def redirect_to_file(self, path):
266258
self.redirect(url_path_join(self.base_url, "voila", "files", path))
267259

voila/server_extension.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
from jupyterlab_server.themes_handler import ThemesHandler
1717

1818
from .configuration import VoilaConfiguration
19-
from .handler import VoilaHandler
19+
from .tornado.handler import TornadoVoilaHandler
2020
from .paths import ROOT, collect_static_paths, collect_template_paths, jupyter_path
2121
from .shutdown_kernel_handler import VoilaShutdownKernelHandler
2222
from .static_file_handler import (
2323
MultiStaticFileHandler,
2424
TemplateStaticFileHandler,
2525
WhiteListFileHandler,
2626
)
27-
from .treehandler import VoilaTreeHandler
27+
from .tornado.treehandler import TornadoVoilaTreeHandler
2828
from .utils import get_server_root_dir
2929

3030

@@ -66,17 +66,21 @@ def _load_jupyter_server_extension(server_app):
6666
[
6767
(
6868
url_path_join(base_url, "/voila/render/(.*)"),
69-
VoilaHandler,
69+
TornadoVoilaHandler,
7070
{
7171
"config": server_app.config,
7272
"template_paths": template_paths,
7373
"voila_configuration": voila_configuration,
7474
},
7575
),
76-
(url_path_join(base_url, "/voila"), VoilaTreeHandler, tree_handler_conf),
76+
(
77+
url_path_join(base_url, "/voila"),
78+
TornadoVoilaTreeHandler,
79+
tree_handler_conf,
80+
),
7781
(
7882
url_path_join(base_url, "/voila/tree" + path_regex),
79-
VoilaTreeHandler,
83+
TornadoVoilaTreeHandler,
8084
tree_handler_conf,
8185
),
8286
(

voila/tornado/handler.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#############################################################################
2+
# Copyright (c) 2018, Voilà Contributors #
3+
# Copyright (c) 2018, QuantStack #
4+
# #
5+
# Distributed under the terms of the BSD 3-Clause License. #
6+
# #
7+
# The full license is in the file LICENSE, distributed with this software. #
8+
#############################################################################
9+
import tornado.web
10+
11+
from ..handler import VoilaHandler
12+
13+
14+
class TornadoVoilaHandler(VoilaHandler):
15+
@tornado.web.authenticated
16+
async def get(self, path=None):
17+
gen = self.get_generator(path=path)
18+
async for html in gen:
19+
self.write(html)
20+
self.flush()

voila/tornado/treehandler.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#############################################################################
2+
# Copyright (c) 2018, Voilà Contributors #
3+
# Copyright (c) 2018, QuantStack #
4+
# #
5+
# Distributed under the terms of the BSD 3-Clause License. #
6+
# #
7+
# The full license is in the file LICENSE, distributed with this software. #
8+
#############################################################################
9+
import os
10+
11+
from jupyter_server.utils import url_escape, url_path_join
12+
from nbclient.util import ensure_async
13+
from tornado import web
14+
15+
from ..treehandler import VoilaTreeHandler
16+
from ..utils import get_server_root_dir
17+
18+
19+
class TornadoVoilaTreeHandler(VoilaTreeHandler):
20+
@web.authenticated
21+
async def get(self, path=""):
22+
cm = self.contents_manager
23+
dir_exists = await ensure_async(cm.dir_exists(path=path))
24+
file_exists = await ensure_async(cm.file_exists(path))
25+
if dir_exists:
26+
is_hidden = await ensure_async(cm.is_hidden(path))
27+
if is_hidden and not cm.allow_hidden:
28+
self.log.info("Refusing to serve hidden directory, via 404 Error")
29+
raise web.HTTPError(404)
30+
breadcrumbs = self.generate_breadcrumbs(path)
31+
page_title = self.generate_page_title(path)
32+
contents = await ensure_async(cm.get(path))
33+
34+
def allowed_content(content):
35+
if content["type"] in ["directory", "notebook"]:
36+
return True
37+
__, ext = os.path.splitext(content.get("path"))
38+
return ext in self.allowed_extensions
39+
40+
contents["content"] = sorted(contents["content"], key=lambda i: i["name"])
41+
contents["content"] = filter(allowed_content, contents["content"])
42+
43+
self.write(
44+
self.render_template(
45+
"tree.html",
46+
frontend="voila",
47+
main_js="voila.js",
48+
page_title=page_title,
49+
notebook_path=path,
50+
breadcrumbs=breadcrumbs,
51+
contents=contents,
52+
terminals_available=False,
53+
server_root=get_server_root_dir(self.settings),
54+
query=self.request.query,
55+
)
56+
)
57+
elif file_exists:
58+
# it's not a directory, we have redirecting to do
59+
model = await ensure_async(cm.get(path, content=False))
60+
# redirect to /api/notebooks if it's a notebook, otherwise /api/files
61+
service = "notebooks" if model["type"] == "notebook" else "files"
62+
url = url_path_join(
63+
self.base_url,
64+
service,
65+
url_escape(path),
66+
)
67+
self.log.debug("Redirecting %s to %s", self.request.path, url)
68+
self.redirect(url)
69+
else:
70+
raise web.HTTPError(404)

voila/treehandler.py

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,9 @@
66
# #
77
# The full license is in the file LICENSE, distributed with this software. #
88
#############################################################################
9-
import os
10-
119
from jupyter_server.utils import url_escape, url_path_join
12-
from tornado import web
1310

1411
from .handler import BaseVoilaHandler
15-
from .utils import get_server_root_dir
16-
from nbclient.util import ensure_async
1712

1813

1914
class VoilaTreeHandler(BaseVoilaHandler):
@@ -50,55 +45,3 @@ def generate_page_title(self, path):
5045
return page_title + "/"
5146
else:
5247
return "Voilà Home"
53-
54-
@web.authenticated
55-
async def get(self, path=""):
56-
cm = self.contents_manager
57-
dir_exists = await ensure_async(cm.dir_exists(path=path))
58-
file_exists = await ensure_async(cm.file_exists(path))
59-
if dir_exists:
60-
is_hidden = await ensure_async(cm.is_hidden(path))
61-
if is_hidden and not cm.allow_hidden:
62-
self.log.info("Refusing to serve hidden directory, via 404 Error")
63-
raise web.HTTPError(404)
64-
breadcrumbs = self.generate_breadcrumbs(path)
65-
page_title = self.generate_page_title(path)
66-
contents = await ensure_async(cm.get(path))
67-
68-
def allowed_content(content):
69-
if content["type"] in ["directory", "notebook"]:
70-
return True
71-
__, ext = os.path.splitext(content.get("path"))
72-
return ext in self.allowed_extensions
73-
74-
contents["content"] = sorted(contents["content"], key=lambda i: i["name"])
75-
contents["content"] = filter(allowed_content, contents["content"])
76-
77-
self.write(
78-
self.render_template(
79-
"tree.html",
80-
frontend="voila",
81-
main_js="voila.js",
82-
page_title=page_title,
83-
notebook_path=path,
84-
breadcrumbs=breadcrumbs,
85-
contents=contents,
86-
terminals_available=False,
87-
server_root=get_server_root_dir(self.settings),
88-
query=self.request.query,
89-
)
90-
)
91-
elif file_exists:
92-
# it's not a directory, we have redirecting to do
93-
model = await ensure_async(cm.get(path, content=False))
94-
# redirect to /api/notebooks if it's a notebook, otherwise /api/files
95-
service = "notebooks" if model["type"] == "notebook" else "files"
96-
url = url_path_join(
97-
self.base_url,
98-
service,
99-
url_escape(path),
100-
)
101-
self.log.debug("Redirecting %s to %s", self.request.path, url)
102-
self.redirect(url)
103-
else:
104-
raise web.HTTPError(404)

0 commit comments

Comments
 (0)