def initialize(webapp, root_dir, connection_url, settings): if os.name == 'nt': default_shell = 'powershell.exe' else: default_shell = which('sh') shell_override = settings.get('shell_command') shell = ( [os.environ.get('SHELL') or default_shell] if shell_override is None else shell_override ) # When the notebook server is not running in a terminal (e.g. when # it's launched by a JupyterHub spawner), it's likely that the user # environment hasn't been fully set up. In that case, run a login # shell to automatically source /etc/profile and the like, unless # the user has specifically set a preferred shell command. if os.name != 'nt' and shell_override is None and not sys.stdout.isatty(): shell.append('-l') terminal_manager = webapp.settings['terminal_manager'] = TerminalManager( shell_command=shell, extra_env={'JUPYTER_SERVER_ROOT': root_dir, 'JUPYTER_SERVER_URL': connection_url, }, parent=webapp.settings['serverapp'], ) terminal_manager.log = webapp.settings['serverapp'].log base_url = webapp.settings['base_url'] handlers = [ (ujoin(base_url, r"/terminals/websocket/(\w+)"), TermSocket, {'term_manager': terminal_manager}), (ujoin(base_url, r"/api/terminals"), api_handlers.TerminalRootHandler), (ujoin(base_url, r"/api/terminals/(\w+)"), api_handlers.TerminalHandler), ] webapp.add_handlers(".*$", handlers)
def initialize(webapp, root_dir, connection_url, settings): if os.name == 'nt': default_shell = 'powershell.exe' else: default_shell = which('sh') shell = settings.get('shell_command', [os.environ.get('SHELL') or default_shell]) # Enable login mode - to automatically source the /etc/profile script if os.name != 'nt': shell.append('-l') terminal_manager = webapp.settings['terminal_manager'] = NamedTermManager( shell_command=shell, extra_env={ 'JUPYTER_SERVER_ROOT': root_dir, 'JUPYTER_SERVER_URL': connection_url, }, ) terminal_manager.log = app_log base_url = webapp.settings['base_url'] handlers = [ (ujoin(base_url, r"/terminals/(\w+)"), TerminalHandler), (ujoin(base_url, r"/terminals/websocket/(\w+)"), TermSocket, { 'term_manager': terminal_manager }), (ujoin(base_url, r"/api/terminals"), api_handlers.TerminalRootHandler), (ujoin(base_url, r"/api/terminals/(\w+)"), api_handlers.TerminalHandler), ] webapp.add_handlers(".*$", handlers)
def get(self): """Get the main page for the application's interface.""" # Options set here can be read with PageConfig.getOption mathjax_config = self.settings.get("mathjax_config", "TeX-AMS_HTML-full,Safe") mathjax_url = self.settings.get( "mathjax_url", "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js" ) config_data = { # Use camelCase here, since that's what the lab components expect "baseUrl": self.base_url, "token": self.settings["token"], "notebookPath": "test.ipynb", "fullStaticUrl": ujoin(self.base_url, "static", self.name), "frontendUrl": ujoin(self.base_url, "example/"), "mathjaxUrl": mathjax_url, "mathjaxConfig": mathjax_config, } return self.write( self.render_template( "index.html", static=self.static_url, base_url=self.base_url, token=self.settings["token"], page_config=config_data, ) )
def initialize_templates(self): # Determine which model to run JupyterLab if self.core_mode or self.app_dir.startswith(HERE + os.sep): self.core_mode = True self.log.info("Running JupyterLab in core mode") if self.dev_mode or self.app_dir.startswith(DEV_DIR + os.sep): self.dev_mode = True self.log.info("Running JupyterLab in dev mode") if self.watch and self.core_mode: self.log.warning("Cannot watch in core mode, did you mean --dev-mode?") self.watch = False if self.core_mode and self.dev_mode: self.log.warning("Conflicting modes, choosing dev_mode over core_mode") self.core_mode = False # Set the paths based on JupyterLab's mode. if self.dev_mode: dev_static_dir = ujoin(DEV_DIR, "static") self.static_paths = [dev_static_dir] self.template_paths = [dev_static_dir] if not self.extensions_in_dev_mode: self.labextensions_path = [] self.extra_labextensions_path = [] elif self.core_mode: dev_static_dir = ujoin(HERE, "static") self.static_paths = [dev_static_dir] self.template_paths = [dev_static_dir] self.labextensions_path = [] self.extra_labextensions_path = [] else: self.static_paths = [self.static_dir] self.template_paths = [self.templates_dir]
async def get(self, path=None): """ Display appropriate page for given path. - A directory listing is shown if path is a directory - Redirected to notebook page if path is a notebook - Render the raw file if path is any other file """ path = path.strip('/') cm = self.contents_manager if await maybe_future(cm.dir_exists(path=path)): if await maybe_future(cm.is_hidden(path)) and not cm.allow_hidden: self.log.info( "Refusing to serve hidden directory, via 404 Error") raise web.HTTPError(404) # Set treePath for routing to the directory page_config = self.get_page_config() page_config['treePath'] = path tpl = self.render_template("tree.html", page_config=page_config) return self.write(tpl) elif await maybe_future(cm.file_exists(path)): # it's not a directory, we have redirecting to do model = await maybe_future(cm.get(path, content=False)) if model['type'] == 'notebook': url = ujoin(self.base_url, 'notebooks', url_escape(path)) else: # Return raw content if file is not a notebook url = ujoin(self.base_url, 'files', url_escape(path)) self.log.debug("Redirecting %s to %s", self.request.path, url) self.redirect(url) else: raise web.HTTPError(404)
def initialize(webapp, root_dir, connection_url, settings): if os.name == "nt": default_shell = "powershell.exe" else: default_shell = which("sh") shell = settings.get("shell_command", [os.environ.get("SHELL") or default_shell]) # Enable login mode - to automatically source the /etc/profile script if os.name != "nt": shell.append("-l") terminal_manager = webapp.settings["terminal_manager"] = NamedTermManager( shell_command=shell, extra_env={ "JUPYTER_SERVER_ROOT": root_dir, "JUPYTER_SERVER_URL": connection_url, }, ) terminal_manager.log = app_log base_url = webapp.settings["base_url"] handlers = [ (ujoin(base_url, r"/terminals/(\w+)"), TerminalHandler), ( ujoin(base_url, r"/terminals/websocket/(\w+)"), TermSocket, {"term_manager": terminal_manager}, ), (ujoin(base_url, r"/api/terminals"), api_handlers.TerminalRootHandler), (ujoin(base_url, r"/api/terminals/(\w+)"), api_handlers.TerminalHandler), ] webapp.add_handlers(".*$", handlers)
def _load_jupyter_server_extension(nbapp): # Set up handlers picked up via config base_url = nbapp.web_app.settings['base_url'] serverproxy = ServerProxy(parent=nbapp) server_processes = [ make_server_process(k, v) for k, v in serverproxy.servers.items() ] server_processes += get_entrypoint_server_processes() server_handlers = make_handlers(base_url, server_processes) nbapp.web_app.add_handlers('.*', server_handlers) # Set up default handler setup_handlers(nbapp.web_app, serverproxy.host_allowlist) launcher_entries = [] icons = {} for sp in server_processes: if sp.launcher_entry.enabled and sp.launcher_entry.icon_path: icons[sp.name] = sp.launcher_entry.icon_path nbapp.web_app.add_handlers( '.*', [(ujoin(base_url, 'server-proxy/servers-info'), ServersInfoHandler, { 'server_processes': server_processes }), (ujoin(base_url, 'server-proxy/icon/(.*)'), IconHandler, { 'icons': icons })])
def _load_jupyter_server_extension(nbapp): # Set up handlers picked up via config base_url = nbapp.web_app.settings['base_url'] serverproxy_config = ServerProxyConfig(parent=nbapp) server_processes = [ 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_handlers = make_handlers(base_url, server_processes) nbapp.web_app.add_handlers('.*', server_handlers) # Set up default non-server handler setup_handlers( nbapp.web_app, serverproxy_config, ) icons = {} for sp in server_processes: if sp.launcher_entry.enabled and sp.launcher_entry.icon_path: icons[sp.name] = sp.launcher_entry.icon_path nbapp.web_app.add_handlers('.*', [ (ujoin(base_url, 'server-proxy/servers-info'), ServersInfoHandler, {'server_processes': server_processes}), (ujoin(base_url, 'server-proxy/icon/(.*)'), IconHandler, {'icons': icons}), ])
async def start_copy(self, name, starter, path, body): """start a copy starter""" root = self.resolve_src(starter) if root is None: return None root_uri = root.as_uri() dest_tmpl_str = starter.get("dest") if dest_tmpl_str is not None: dest_tmpl = self.jinja_env.from_string(dest_tmpl_str) dest = ujoin(path, dest_tmpl.render(**(body or {}))) else: dest = ujoin(path, root.name) await self.save_one(root, dest) for child in iter_not_ignored(root, starter.get("ignore")): await self.save_one( child, unquote(ujoin(dest, child.as_uri().replace(root_uri, ""))), ) return { "body": body, "name": name, "path": dest, "starter": starter, "status": Status.DONE, }
def get(self): """Get the main page for the application's interface.""" # Options set here can be read with PageConfig.getOption mathjax_config = self.settings.get('mathjax_config', 'TeX-AMS_HTML-full,Safe') mathjax_url = self.settings.get( 'mathjax_url', 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js') config_data = { # Use camelCase here, since that's what the lab components expect 'baseUrl': self.base_url, 'token': self.settings['token'], 'notebookPath': 'test.ipynb', 'fullStaticUrl': ujoin(self.base_url, 'static', self.name), 'frontendUrl': ujoin(self.base_url, 'example/'), 'mathjaxUrl': mathjax_url, 'mathjaxConfig': mathjax_config } return self.write( self.render_template('index.html', static=self.static_url, base_url=self.base_url, token=self.settings['token'], page_config=config_data))
def start(self): app = LabApp(config=self.config) # TODO(@echarles) Fix this... # base_url = app.serverapp.base_url base_url = '/' directory = app.workspaces_dir app_url = app.app_url if len(self.extra_args) > 1: print('Too many arguments were provided for workspace export.') self.exit(1) workspaces_url = ujoin(app_url, 'workspaces') raw = (app_url if not self.extra_args else ujoin(workspaces_url, self.extra_args[0])) slug = slugify(raw, base_url) workspace_path = pjoin(directory, slug + WORKSPACE_EXTENSION) if osp.exists(workspace_path): with open(workspace_path) as fid: try: # to load the workspace file. print(fid.read()) except Exception as e: print(json.dumps(dict(data=dict(), metadata=dict(id=raw)))) else: print(json.dumps(dict(data=dict(), metadata=dict(id=raw))))
def _validate(self, data, base_url, app_url, workspaces_url): workspace = json.load(data) if 'data' not in workspace: raise Exception('The `data` field is missing.') # If workspace_name is set in config, inject the # name into the workspace metadata. if self.workspace_name is not None: if self.workspace_name == "": workspace_id = ujoin(base_url, app_url) else: workspace_id = ujoin(base_url, workspaces_url, self.workspace_name) workspace['metadata'] = {'id': workspace_id} # else check that the workspace_id is valid. else: if 'id' not in workspace['metadata']: raise Exception('The `id` field is missing in `metadata`.') else: id = workspace['metadata']['id'] if id != ujoin(base_url, app_url) and not id.startswith(ujoin(base_url, workspaces_url)): error = '%s does not match app_url or start with workspaces_url.' raise Exception(error % id) return workspace
def initialize_templates(self): # Determine which model to run JupyterLab if self.core_mode or self.app_dir.startswith(HERE): self.core_mode = True self.log.info('Running JupyterLab in dev mode') if self.dev_mode or self.app_dir.startswith(DEV_DIR): self.dev_mode = True self.log.info('Running JupyterLab in dev mode') if self.watch and self.core_mode: self.log.warn('Cannot watch in core mode, did you mean --dev-mode?') self.watch = False if self.core_mode and self.dev_mode: self.log.warn('Conflicting modes, choosing dev_mode over core_mode') self.core_mode = False # Set the paths based on JupyterLab's mode. if self.dev_mode: dev_static_dir = ujoin(DEV_DIR, 'static') self.static_paths = [dev_static_dir] self.template_paths = [dev_static_dir] elif self.core_mode: dev_static_dir = ujoin(HERE, 'static') self.static_paths = [dev_static_dir] self.template_paths = [dev_static_dir] else: self.static_paths = [self.static_dir] self.template_paths = [self.templates_dir]
async def test_redirects_from_classic_notebook_endpoints( jp_fetch, jp_base_url, asset_file): old_prefix = ujoin("static", "components", "MathJax") new_prefix = ujoin("static", "jupyter_server_mathjax") # Verify that the redirect is in place with pytest.raises(HTTPClientError) as error_info, pytest.deprecated_call( match="Redirecting old Notebook MathJax URL .*"): await jp_fetch(old_prefix, asset_file, follow_redirects=False) err = error_info.value assert err.code == 301 assert err.response.headers["Location"] == ujoin(jp_base_url, new_prefix, asset_file)
def get_page_config(self): config = LabConfig() app = self.extensionapp base_url = self.settings.get("base_url") page_config = { "appVersion": version, "baseUrl": self.base_url, "terminalsAvailable": self.settings.get('terminals_available', False), "token": self.settings["token"], "fullStaticUrl": ujoin(self.base_url, "static", self.name), "frontendUrl": ujoin(self.base_url, "classic/"), } mathjax_config = self.settings.get("mathjax_config", "TeX-AMS_HTML-full,Safe") # TODO Remove CDN usage. mathjax_url = self.settings.get( "mathjax_url", "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js", ) page_config.setdefault("mathjaxConfig", mathjax_config) page_config.setdefault("fullMathjaxUrl", mathjax_url) # Put all our config in page_config for name in config.trait_names(): page_config[_camelCase(name)] = getattr(app, name) # Add full versions of all the urls for name in config.trait_names(): if not name.endswith("_url"): continue full_name = _camelCase("full_" + name) full_url = getattr(app, name) if not is_url(full_url): # Relative URL will be prefixed with base_url full_url = ujoin(base_url, full_url) page_config[full_name] = full_url labextensions_path = app.extra_labextensions_path + app.labextensions_path recursive_update( page_config, get_page_config( labextensions_path, logger=self.log, ), ) return page_config
def get(self): config_data = { # Use camelCase here, since that's what the lab components expect "appVersion": version, 'baseUrl': self.base_url, 'token': self.settings['token'], 'fullStaticUrl': ujoin(self.base_url, 'static', self.name), 'frontendUrl': ujoin(self.base_url, 'example/'), } return self.write( self.render_template('index.html', static=self.static_url, base_url=self.base_url, token=self.settings['token'], page_config=config_data))
def get(self): """Get the main page for the application's interface.""" config_data = { # Use camelCase here, since that's what the lab components expect 'baseUrl': self.base_url, 'token': self.settings['token'], 'fullStaticUrl': ujoin(self.base_url, 'static', self.name), 'frontendUrl': ujoin(self.base_url, 'example/'), } return self.write( self.render_template('index.html', static=self.static_url, base_url=self.base_url, token=self.settings['token'], page_config=config_data))
def get(self): config_data = { "appVersion": __version__, "baseUrl": self.base_url, "token": self.settings["token"], "fullStaticUrl": ujoin(self.base_url, "static", self.name), "frontendUrl": ujoin(self.base_url, "gator/"), } return self.write( self.render_template( "index.html", static=self.static_url, base_url=self.base_url, token=self.settings["token"], page_config=config_data, ))
def start(self): app = LabApp(config=self.config) base_url = app.settings.get('base_url', '/') directory = app.workspaces_dir app_url = app.app_url workspaces_url = ujoin(app.app_url, 'workspaces') if len(self.extra_args) != 1: print('One argument is required for workspace import.') self.exit(1) workspace = dict() with self._smart_open() as fid: try: # to load, parse, and validate the workspace file. workspace = self._validate(fid, base_url, app_url, workspaces_url) except Exception as e: print('%s is not a valid workspace:\n%s' % (fid.name, e)) self.exit(1) if not osp.exists(directory): try: os.makedirs(directory) except Exception as e: print('Workspaces directory could not be created:\n%s' % e) self.exit(1) slug = slugify(workspace['metadata']['id'], base_url) workspace_path = pjoin(directory, slug + WORKSPACE_EXTENSION) # Write the workspace data to a file. with open(workspace_path, 'w') as fid: fid.write(json.dumps(workspace)) print('Saved workspace: %s' % workspace_path)
def _default_static_url_prefix(self): if self.override_static_url: return self.override_static_url else: static_url = "/static/{name}/".format( name=self.name) return ujoin(self.serverapp.base_url, static_url)
def get(self): config_data = { "appVersion": version, 'baseUrl': self.base_url, 'token': self.settings['token'], 'fullStaticUrl': ujoin(self.base_url, 'static', self.name), 'frontendUrl': ujoin(self.base_url, 'gridstack/'), } return self.write( self.render_template( 'index.html', static=self.static_url, base_url=self.base_url, token=self.settings['token'], page_config=config_data ) )
def get(self): config_data = { # Use camelCase here, since that's what the lab components expect "appVersion": version, "baseUrl": self.base_url, "token": self.settings["token"], "fullStaticUrl": ujoin(self.base_url, "static", self.name), "frontendUrl": ujoin(self.base_url, "example/"), } return self.write( self.render_template( "index.html", static=self.static_url, base_url=self.base_url, token=self.settings["token"], page_config=config_data, ))
def add_handlers(nbapp): """Add Language Server routes to the notebook server web application""" lsp_url = ujoin(nbapp.base_url, "lsp") re_langservers = "(?P<language_server>.*)" opts = {"manager": nbapp.language_server_manager} nbapp.web_app.add_handlers( ".*", [ (ujoin(lsp_url, "status"), LanguageServersHandler, opts), ( ujoin(lsp_url, "ws", re_langservers), LanguageServerWebSocketHandler, opts, ), ], )
def load_jupyter_server_extension(nbapp): """Load the nbserver extension""" nbapp.log.info("Loading IPython parallel extension") webapp = nbapp.web_app webapp.settings['cluster_manager'] = ClusterManager(parent=nbapp) base_url = webapp.settings['base_url'] webapp.add_handlers(".*$", [(ujoin(base_url, pat), handler) for pat, handler in default_handlers])
def init_webapp(self): """initialize tornado webapp and httpserver.""" super().init_webapp() default_handlers = [( ujoin(self.base_url, r"/listings/(.*)"), FileFindHandler, { "path": os.path.join(HERE, "list") }, )] self.web_app.add_handlers(".*$", default_handlers)
def init_webapp(self): """initialize tornado webapp and httpserver. """ super().init_webapp() default_handlers = [ ( ujoin(self.base_url, r"/listings/(.*)"), FileFindHandler, {'path': os.path.join(HERE, 'list')} ) ] self.web_app.add_handlers('.*$', default_handlers)
def add_handlers(nbapp, manager) -> None: """Add starter routes to the notebook server web application""" opts = {"manager": manager} url = ujoin(nbapp.base_url, NS) starter_url = ujoin(url, "(?P<starter>.*?)", "(?P<path>.*?)", "?$") nbapp.log.debug("💡 starters will list under %s", url) nbapp.log.debug("💡 starters will run under %s", starter_url) nbapp.web_app.add_handlers( ".*", [ (url, StartersHandler, opts), ( starter_url, StarterHandler, opts, ), ], )
def get(self): """Get the main page for the application's interface.""" available = self.settings["terminals_available"] config_data = { # Use camelCase here, since that's what the lab components expect "appVersion": version, "baseUrl": self.base_url, "token": self.settings["token"], "fullStaticUrl": ujoin(self.base_url, "static", self.name), "frontendUrl": ujoin(self.base_url, "example/"), "terminalsAvailable": available, } return self.write( self.render_template( "index.html", static=self.static_url, base_url=self.base_url, token=self.settings["token"], terminals_available=available, page_config=config_data, ))
def make_handlers(base_url, server_processes): """ Get tornado handlers for registered server_processes """ handlers = [] for sp in server_processes: handler = _make_serverproxy_handler( sp.name, sp.command, sp.environment, sp.timeout, sp.absolute_url, sp.port, sp.mappath, ) handlers.append(( ujoin(base_url, sp.name, r'(.*)'), handler, dict(state={}), )) handlers.append((ujoin(base_url, sp.name), AddSlashHandler)) return handlers
def initialize(webapp, root_dir, connection_url, settings): if os.name == "nt": default_shell = "powershell.exe" else: default_shell = which("sh") shell_override = settings.get("shell_command") shell = [os.environ.get("SHELL") or default_shell ] if shell_override is None else shell_override # When the notebook server is not running in a terminal (e.g. when # it's launched by a JupyterHub spawner), it's likely that the user # environment hasn't been fully set up. In that case, run a login # shell to automatically source /etc/profile and the like, unless # the user has specifically set a preferred shell command. if os.name != "nt" and shell_override is None and not sys.stdout.isatty(): shell.append("-l") terminal_manager = webapp.settings["terminal_manager"] = TerminalManager( shell_command=shell, extra_env={ "JUPYTER_SERVER_ROOT": root_dir, "JUPYTER_SERVER_URL": connection_url, }, parent=webapp.settings["serverapp"], ) terminal_manager.log = webapp.settings["serverapp"].log base_url = webapp.settings["base_url"] handlers = [ ( ujoin(base_url, r"/terminals/websocket/(\w+)"), TermSocket, { "term_manager": terminal_manager }, ), (ujoin(base_url, r"/api/terminals"), api_handlers.TerminalRootHandler), (ujoin(base_url, r"/api/terminals/(\w+)"), api_handlers.TerminalHandler), ] webapp.add_handlers(".*$", handlers)