You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
3.6 KiB

4 years ago
  1. #############################################################################
  2. # Copyright (c) 2018, Voila 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. from tornado import web
  11. from jupyter_server.base.handlers import JupyterHandler
  12. from jupyter_server.utils import url_path_join, url_escape
  13. from .utils import get_server_root_dir
  14. class VoilaTreeHandler(JupyterHandler):
  15. def initialize(self, **kwargs):
  16. self.voila_configuration = kwargs['voila_configuration']
  17. self.allowed_extensions = list(self.voila_configuration.extension_language_mapping.keys()) + ['.ipynb']
  18. def get_template(self, name):
  19. """Return the jinja template object for a given name"""
  20. return self.settings['voila_jinja2_env'].get_template(name)
  21. def generate_breadcrumbs(self, path):
  22. breadcrumbs = [(url_path_join(self.base_url, 'voila/tree'), '')]
  23. parts = path.split('/')
  24. for i in range(len(parts)):
  25. if parts[i]:
  26. link = url_path_join(self.base_url, 'voila/tree',
  27. url_escape(url_path_join(*parts[:i + 1])),
  28. )
  29. breadcrumbs.append((link, parts[i]))
  30. return breadcrumbs
  31. def generate_page_title(self, path):
  32. parts = path.split('/')
  33. if len(parts) > 3: # not too many parts
  34. parts = parts[-2:]
  35. page_title = url_path_join(*parts)
  36. if page_title:
  37. return page_title + '/'
  38. else:
  39. return 'Voila Home'
  40. @web.authenticated
  41. def get(self, path=''):
  42. cm = self.contents_manager
  43. if cm.dir_exists(path=path):
  44. if cm.is_hidden(path) and not cm.allow_hidden:
  45. self.log.info("Refusing to serve hidden directory, via 404 Error")
  46. raise web.HTTPError(404)
  47. breadcrumbs = self.generate_breadcrumbs(path)
  48. page_title = self.generate_page_title(path)
  49. contents = cm.get(path)
  50. def allowed_content(content):
  51. if content['type'] in ['directory', 'notebook']:
  52. return True
  53. __, ext = os.path.splitext(content.get('path'))
  54. return ext in self.allowed_extensions
  55. contents['content'] = filter(allowed_content, contents['content'])
  56. self.write(self.render_template('tree.html',
  57. page_title=page_title,
  58. notebook_path=path,
  59. breadcrumbs=breadcrumbs,
  60. contents=contents,
  61. terminals_available=False,
  62. server_root=get_server_root_dir(self.settings)))
  63. elif cm.file_exists(path):
  64. # it's not a directory, we have redirecting to do
  65. model = cm.get(path, content=False)
  66. # redirect to /api/notebooks if it's a notebook, otherwise /api/files
  67. service = 'notebooks' if model['type'] == 'notebook' else 'files'
  68. url = url_path_join(
  69. self.base_url, service, url_escape(path),
  70. )
  71. self.log.debug("Redirecting %s to %s", self.request.path, url)
  72. self.redirect(url)
  73. else:
  74. raise web.HTTPError(404)