def get(self, path): """ Inject the user's KBase cookie before trying to look up a file. One of our big use cases bypasses the typical Jupyter login mechanism. """ cookie_regex = re.compile('([^ =|]+)=([^\|]*)') client_ip = self.request.remote_ip http_headers = self.request.headers ua = http_headers.get('User-Agent', 'unknown') found_cookies = [self.cookies[c] for c in all_cookies if c in self.cookies] if found_cookies: cookie_val = urllib.unquote(found_cookies[0].value) cookie_obj = { k: v.replace('EQUALSSIGN', '=').replace('PIPESIGN', '|') for k, v in cookie_regex.findall(cookie_val) } # if app_log.isEnabledFor(logging.DEBUG): # app_log.debug("kbase cookie = {}".format(cookie_val)) # app_log.debug("KBaseLoginHandler.get: user_id={uid} token={tok}" # .format(uid=sess.get('token', 'none'), # tok=sess.get('token', 'none'))) biokbase.auth.set_environ_token(cookie_obj.get('token', None)) kbase_env.session = cookie_obj.get('kbase_sessionid', '') kbase_env.client_ip = client_ip kbase_env.user = cookie_obj.get('user_id', '') log_event(g_log, 'session_start', {'user': kbase_env.user, 'user_agent': ua}) """get renders the notebook template if a name is given, or redirects to the '/files/' handler if the name is not given.""" path = path.strip('/') cm = self.contents_manager # will raise 404 on not found try: model = cm.get(path, content=False) except web.HTTPError as e: raise # if e.status_code == 404 and 'files' in path.split('/'): # # 404, but '/files/' in URL, let FilesRedirect take care of it # return FilesRedirectHandler.redirect_to_files(self, path) # else: # raise if model['type'] != 'notebook': # not a notebook, redirect to files return FilesRedirectHandler.redirect_to_files(self, path) name = url_escape(path.rsplit('/', 1)[-1]) path = url_escape(path) self.write(self.render_template('notebook.html', notebook_path=path, notebook_name=path, kill_kernel=False, mathjax_url=self.mathjax_url, ) )
def redirect_to_files(self, path): """make redirect logic a reusable static method so it can be called from other handlers. """ cm = self.contents_manager if cm.dir_exists(path): # it's a *directory*, redirect to /tree url = url_path_join(self.base_url, 'tree', url_escape(path)) else: orig_path = path # otherwise, redirect to /files parts = path.split('/') if not cm.file_exists(path=path) and 'files' in parts: # redirect without files/ iff it would 404 # this preserves pre-2.0-style 'files/' links self.log.warning("Deprecated files/ URL: %s", orig_path) parts.remove('files') path = '/'.join(parts) if not cm.file_exists(path=path): raise web.HTTPError(404) url = url_path_join(self.base_url, 'files', url_escape(path)) self.log.debug("Redirecting %s to %s", self.request.path, url) self.redirect(url)
def get(self, path): """ Inject the user's KBase cookie before trying to look up a file. One of our big use cases bypasses the typical Jupyter login mechanism. """ cookie_regex = re.compile('([^ =|]+)=([^\|]*)') client_ip = self.request.remote_ip http_headers = self.request.headers ua = http_headers.get('User-Agent', 'unknown') auth_cookie = self.cookies.get(auth_cookie_name, None) if auth_cookie: cookie_val = urllib.unquote(auth_cookie.value) cookie_obj = { k: v.replace('EQUALSSIGN', '=').replace('PIPESIGN', '|') for k, v in cookie_regex.findall(cookie_val) } else: raise web.HTTPError(status_code=401, log_message='No auth cookie, denying access', reason='Authorization required for Narrative access') biokbase.auth.set_environ_token(cookie_obj.get('token', None)) kbase_env.session = cookie_obj.get('kbase_sessionid', '') kbase_env.client_ip = client_ip kbase_env.user = cookie_obj.get('user_id', '') log_event(g_log, 'session_start', {'user': kbase_env.user, 'user_agent': ua}) """get renders the notebook template if a name is given, or redirects to the '/files/' handler if the name is not given.""" path = path.strip('/') cm = self.contents_manager # will raise 404 on not found try: model = cm.get(path, content=False) except web.HTTPError as e: raise # if e.status_code == 404 and 'files' in path.split('/'): # # 404, but '/files/' in URL, let FilesRedirect take care of it # return FilesRedirectHandler.redirect_to_files(self, path) # else: # raise if model['type'] != 'notebook': # not a notebook, redirect to files return FilesRedirectHandler.redirect_to_files(self, path) name = url_escape(path.rsplit('/', 1)[-1]) path = url_escape(path) self.write(self.render_template('notebook.html', notebook_path=path, notebook_name=path, kill_kernel=False, mathjax_url=self.mathjax_url, ) )
def post(self, path=''): """post creates a new checkpoint""" cm = self.contents_manager checkpoint = yield maybe_future(cm.create_checkpoint(path)) data = json.dumps(checkpoint, default=date_default) location = url_path_join(self.base_url, 'api/contents', url_escape(path), 'checkpoints', url_escape(checkpoint['id'])) self.set_header('Location', location) self.set_status(201) self.finish(data)
def get(self, path): """ Inject the user's KBase cookie before trying to look up a file. One of our big use cases bypasses the typical Jupyter login mechanism. """ client_ip = self.request.remote_ip http_headers = self.request.headers ua = http_headers.get('User-Agent', 'unknown') auth_cookie = self.cookies.get(auth_cookie_name, None) if auth_cookie: token = urllib.unquote(auth_cookie.value) else: raise web.HTTPError( status_code=401, log_message='No auth cookie, denying access', reason='Authorization required for Narrative access') if token != kbase_env.auth_token: init_session_env(get_user_info(token), client_ip) log_event(g_log, 'session_start', { 'user': kbase_env.user, 'user_agent': ua }) """ get renders the notebook template if a name is given, or redirects to the '/files/' handler if the name is not given. """ path = path.strip('/') cm = self.contents_manager # will raise 404 on not found try: model = cm.get(path, content=False) except web.HTTPError as e: raise # if e.status_code == 404 and 'files' in path.split('/'): # # 404, but '/files/' in URL, let FilesRedirect take care of it # return FilesRedirectHandler.redirect_to_files(self, path) # else: # raise if model['type'] != 'notebook': # not a notebook, redirect to files return FilesRedirectHandler.redirect_to_files(self, path) name = url_escape(path.rsplit('/', 1)[-1]) path = url_escape(path) self.write( self.render_template('notebook.html', notebook_path=path, notebook_name=path, kill_kernel=False, mathjax_url=self.mathjax_url))
def post(self, path=''): """post creates a new checkpoint""" # grab the commit message from the posted data commit_message = json.loads(self.request.body.decode('utf-8')).get('commit_message', None) # print("CREATING NEW CHECKPOINT WITH MESSAGE: " + str(commit_message)) cm = self.contents_manager checkpoint = yield gen.maybe_future(cm.create_checkpoint(path, commit_message=commit_message)) data = json.dumps(checkpoint, default=date_default) location = url_path_join(self.base_url, 'api/contents', url_escape(path), 'checkpoints', url_escape(checkpoint['id'])) self.set_header('Location', location) self.set_status(201) self.finish(data)
def test_url_escape(): # changes path or notebook name with special characters to url encoding # these tests specifically encode paths with spaces path = url_escape('/this is a test/for spaces/') assert path == '/this%20is%20a%20test/for%20spaces/' path = url_escape('notebook with space.ipynb') assert path == 'notebook%20with%20space.ipynb' path = url_escape('/path with a/notebook and space.ipynb') assert path == '/path%20with%20a/notebook%20and%20space.ipynb' path = url_escape('/ !@$#%^&* / test %^ notebook @#$ name.ipynb') assert path == '/%20%21%40%24%23%25%5E%26%2A%20/%20test%20%25%5E%20notebook%20%40%23%24%20name.ipynb'
def test_url_escape(): # changes path or notebook name with special characters to url encoding # these tests specifically encode paths with spaces path = url_escape('/this is a test/for spaces/') nt.assert_equal(path, '/this%20is%20a%20test/for%20spaces/') path = url_escape('notebook with space.ipynb') nt.assert_equal(path, 'notebook%20with%20space.ipynb') path = url_escape('/path with a/notebook and space.ipynb') nt.assert_equal(path, '/path%20with%20a/notebook%20and%20space.ipynb') path = url_escape('/ !@$#%^&* / test %^ notebook @#$ name.ipynb') nt.assert_equal(path, '/%20%21%40%24%23%25%5E%26%2A%20/%20test%20%25%5E%20notebook%20%40%23%24%20name.ipynb')
def post(self): """Most of this is taken from the super class MainKernelHandler but we hijack the name field to specify the notebook we want to run""" km = self.kernel_manager model = self.get_json_body() if model is None: msg = "Must supply a body with a name formated like {\"name\":\<path_to_notebook>}" raise web.HTTPError(400, msg, reason=msg) name = json.loads(model.get('name', '')) notebook = None if isinstance(name, dict): notebook = name.get('notebook', None) if notebook == None: msg = "Must supply a body with a name formated like {\"name\":\<path_to_notebook>}" raise web.HTTPError(400, msg, reason=msg) del model['name'] model.setdefault('name', km.default_kernel_name) kernel_id = yield gen.maybe_future( km.start_kernel(kernel_name=model['name'])) model = km.kernel_model(kernel_id) location = url_path_join(self.base_url, 'api', 'kernels', url_escape(kernel_id)) kernel_reg.add(kernel_id, notebook) self.set_header('Location', location) self.set_status(201) self.finish(json.dumps(model, default=date_default))
def nbopen(filename): filename = os.path.abspath(filename) home_dir = os.path.expanduser('~') server_inf = find_best_server(filename) if server_inf is not None: print("Using existing server at", server_inf['notebook_dir']) path = os.path.relpath(filename, start=server_inf['notebook_dir']) if os.sep != '/': path = path.replace(os.sep, '/') url = url_path_join(server_inf['url'], 'notebooks', url_escape(path)) na = notebookapp.NotebookApp.instance() na.load_config_file() browser = webbrowser.get(na.browser or None) browser.open(url, new=2) else: if filename.startswith(home_dir): nbdir = home_dir else: nbdir = os.path.dirname(filename) print("Starting new server") notebookapp.launch_new_instance(file_to_run=os.path.abspath(filename), notebook_dir=nbdir, open_browser=True, argv=[], # Avoid it seeing our own argv )
def nbopen(filename): filename = os.path.abspath(filename) home_dir = os.path.expanduser('~') server_inf = find_best_server(filename) if server_inf is not None: print("Using existing server at", server_inf['notebook_dir']) path = os.path.relpath(filename, start=server_inf['notebook_dir']) if os.sep != '/': path = path.replace(os.sep, '/') url = url_path_join(server_inf['url'], 'notebooks', url_escape(path)) na = notebookapp.NotebookApp.instance() na.load_config_file() browser = webbrowser.get(na.browser or None) browser.open(url, new=2) else: if filename.startswith(home_dir): nbdir = home_dir else: nbdir = os.path.dirname(filename) print("Starting new server") # Hack: we want to override these settings if they're in the config file. # The application class allows 'command line' config to override config # loaded afterwards from the config file. So by specifying config, we # can use this mechanism. cfg = Config() cfg.NotebookApp.file_to_run = os.path.abspath(filename) cfg.NotebookApp.notebook_dir = nbdir cfg.NotebookApp.open_browser = True notebookapp.launch_new_instance( config=cfg, argv=[], # Avoid it seeing our own argv )
def post(self, path=''): """post creates a new checkpoint""" # grab the commit message from the posted data commit_message = json.loads(self.request.body.decode('utf-8')).get( 'commit_message', None) # print("CREATING NEW CHECKPOINT WITH MESSAGE: " + str(commit_message)) cm = self.contents_manager checkpoint = yield gen.maybe_future( cm.create_checkpoint(path, commit_message=commit_message)) data = json.dumps(checkpoint, default=date_default) location = url_path_join(self.base_url, 'api/contents', url_escape(path), 'checkpoints', url_escape(checkpoint['id'])) self.set_header('Location', location) self.set_status(201) self.finish(data)
def set_attachment_header(self, filename): """Set Content-Disposition: attachment header As a method to ensure handling of filename encoding """ escaped_filename = url_escape(filename) self.set_header( 'Content-Disposition', 'attachment;' " filename*=utf-8''{utf8}".format(utf8=escaped_filename, ))
def get(self, path): """ Proxy API requests to GitHub, adding authentication parameter(s) if they have been set. """ # Get access to the notebook config object c = GitHubConfig(config=self.config) try: query = self.request.query_arguments params = {key: query[key][0].decode() for key in query} api_path = url_path_join(c.api_url, url_escape(path)) params['per_page'] = 100 access_token = params.pop('access_token', None) if access_token and c.allow_client_side_access_token == True: token = access_token elif access_token and c.allow_client_side_access_token == False: msg = ("Client side (JupyterLab) access tokens have been " "disabled for security reasons.\nPlease remove your " "access token from JupyterLab and instead add it to " "your notebook configuration file:\n" "c.GitHubConfig.access_token = '<TOKEN>'\n") raise HTTPError(403, msg) elif c.access_token != '': # Preferentially use the config access_token if set token = c.access_token api_path = url_concat(api_path, params) client = AsyncHTTPClient() request = HTTPRequest( api_path, validate_cert=c.validate_cert, user_agent='JupyterLab GitHub', headers={"Authorization": "token {}".format(token)}) response = yield client.fetch(request) data = json.loads(response.body.decode('utf-8')) # Check if we need to paginate results. # If so, get pages until all the results # are loaded into the data buffer. next_page_path = self._maybe_get_next_page_path(response) while next_page_path: request = copy.copy(request) request.url = next_page_path response = yield client.fetch(request) next_page_path = self._maybe_get_next_page_path(response) data.extend(json.loads(response.body.decode('utf-8'))) # Send the results back. self.finish(json.dumps(data)) except HTTPError as err: self.set_status(err.code) message = err.response.body if err.response else str(err.code) self.finish(message)
def _check_created(self, resp, path, type='notebook'): self.assertEqual(resp.status_code, 201) location_header = py3compat.str_to_unicode(resp.headers['Location']) self.assertEqual(location_header, url_escape(url_path_join(u'/api/contents', path))) rjson = resp.json() self.assertEqual(rjson['name'], path.rsplit('/', 1)[-1]) self.assertEqual(rjson['path'], path) self.assertEqual(rjson['type'], type) isright = self.isdir if type == 'directory' else self.isfile assert isright(path)
def location_url(self, path): """Return the full URL location of a file. Parameters ---------- path : unicode The API path of the file, such as "foo/bar.txt". """ return url_path_join(self.base_url, 'api', 'contents', url_escape(path))
def generate_breadcrumbs(self, path): """ Generate array of breadcrumb to display in page """ breadcrumbs = [(url_path_join(self.base_url, 'cernbox'), '')] parts = path.split('/') for i in range(len(parts)): if parts[i]: link = url_path_join(self.base_url, 'cernbox', url_escape(url_path_join(*parts[:i+1])), ) breadcrumbs.append((link, parts[i])) return breadcrumbs
def location_url(self, path): """Return the full URL location of a file. Parameters ---------- path : unicode The API path of the file, such as "foo/bar.txt". """ return url_escape(url_path_join( self.base_url, 'api', 'contents', path ))
def set_attachment_header(self, filename): """Set Content-Disposition: attachment header As a method to ensure handling of filename encoding """ escaped_filename = url_escape(filename) self.set_header('Content-Disposition', 'attachment;' " filename*=utf-8''{utf8}" .format( utf8=escaped_filename, ) )
def post(self): km = self.kernel_manager model = self.get_json_body() if model is None: model = {'name': km.default_kernel_name} else: model.setdefault('name', km.default_kernel_name) kernel_id = km.start_kernel(kernel_name=model['name']) model = km.kernel_model(kernel_id) location = url_path_join(self.base_url, 'api', 'kernels', kernel_id) self.set_header('Location', url_escape(location)) self.set_status(201) self.finish(json.dumps(model))
def post(self): km = self.kernel_manager model = self.get_json_body() if model is None: model = {"name": km.default_kernel_name} else: model.setdefault("name", km.default_kernel_name) kernel_id = yield maybe_future( km.start_kernel(kernel_name=model["name"])) model = yield maybe_future(km.kernel_model(kernel_id)) location = url_path_join(self.base_url, "api", "kernels", url_escape(kernel_id)) self.set_header("Location", location) self.set_status(201) self.finish(json.dumps(model, default=date_default))
def post(self): km = self.kernel_manager model = self.get_json_body() if model is None: model = { 'name': km.default_kernel_name } else: model.setdefault('name', km.default_kernel_name) kernel_id = km.start_kernel(kernel_name=model['name']) model = km.kernel_model(kernel_id) location = url_path_join(self.base_url, 'api', 'kernels', kernel_id) self.set_header('Location', url_escape(location)) self.set_status(201) self.finish(json.dumps(model))
def get(self, path=''): """ Proxy API requests to GitHub, adding authentication parameter(s) if they have been set. """ # Get access to the notebook config object c = GitHubConfig(config=self.config) try: api_path = url_path_join(c.api_url, url_escape(path)) query = self.request.query_arguments params = {key: query[key][0].decode() for key in query} params['per_page'] = 100 if c.access_token != '': # Preferentially use the access_token if set params['access_token'] = c.access_token elif c.client_id != '' and c.client_secret != '': # Otherwise use client_id and client_secret if set params['client_id'] = c.client_id params['client_secret'] = c.client_secret api_path = url_concat(api_path, params) client = AsyncHTTPClient() request = HTTPRequest(api_path, validate_cert=c.validate_cert, user_agent='JupyterLab GitHub') response = yield client.fetch(request) data = json.loads(response.body.decode('utf-8')) # Check if we need to paginate results. # If so, get pages until all the results # are loaded into the data buffer. next_page_path = self._maybe_get_next_page_path(response) while next_page_path: request = copy.copy(request) request.url = next_page_path response = yield client.fetch(request) next_page_path = self._maybe_get_next_page_path(response) data.extend(json.loads(response.body.decode('utf-8'))) # Send the results back. self.finish(json.dumps(data)) except HTTPError as err: self.set_status(err.code) message = err.response.body if err.response else str(err.code) self.finish(message)
def post(self): km = self.kernel_manager model = self.get_json_body() if model is None: model = {'name': km.default_kernel_name} else: model.setdefault('name', km.default_kernel_name) kernel_id = yield tornado.gen.maybe_future( km.start_kernel( kernel_name=model['name'], extra_arguments=[self.module_name, self.object_name])) model = km.kernel_model(kernel_id) location = url_path_join(self.base_url, 'api', 'kernels', url_escape(kernel_id)) self.set_header('Location', location) self.set_status(201) self.finish(json.dumps(model, default=date_default))
def get(self, path=''): """ Get handler to cope with Projects as root folder """ path = path.strip('/') cm = self.contents_manager swan_path = url_path_join('SWAN_projects', path) if cm.dir_exists(path=swan_path): if cm.is_hidden(swan_path): self.log.info( "Refusing to serve hidden directory, via 404 Error") raise web.HTTPError(404) if path != '': parent_project = cm._get_project_path(swan_path) if not parent_project or parent_project == 'invalid': self.log.info("Trying to see a folder inside Projects") raise web.HTTPError(404) breadcrumbs = self.generate_breadcrumbs(path) page_title = self.generate_page_title(path) self.write( self.render_template( 'tree.html', page_title=page_title, notebook_path=swan_path, breadcrumbs=breadcrumbs, terminals_available=self.settings['terminals_available'], server_root=self.settings['server_root_dir'], projects_page=True, )) elif cm.file_exists(swan_path): # it's not a directory, we have redirecting to do model = cm.get(swan_path, content=False) # redirect to /api/notebooks if it's a notebook, otherwise /api/files service = 'notebooks' if model['type'] == 'notebook' else 'files' url = url_path_join( self.base_url, service, url_escape(swan_path), ) self.log.debug("Redirecting %s to %s", self.request.swan_path, url) self.redirect(url) else: raise web.HTTPError(404)
def get(self, path): _init_session(self.request, self.cookies) """ get renders the notebook template if a name is given, or redirects to the '/files/' handler if the name is not given. """ path = path.strip("/") cm = self.contents_manager # will raise 404 on not found try: model = cm.get(path, content=False) except web.HTTPError as e: log_event(g_log, "loading_error", {"error": str(e)}) if e.status_code == 403: self.write(self.render_template("403.html", status_code=403)) return else: self.write( self.render_template( "generic_error.html", message=e.log_message, status_code=e.status_code, )) return if model.get("type") != "notebook": # not a notebook, redirect to files return FilesRedirectHandler.redirect_to_files(self, path) path = url_escape(path) self.write( self.render_template( "notebook.html", notebook_path=path, notebook_name=path, kill_kernel=False, mathjax_url=self.mathjax_url, google_analytics_id=URLS.google_analytics_id, userName=kbase_env.user, google_ad_id=URLS.google_ad_id, google_ad_conversion=URLS.google_ad_conversion, ))
def register(self, server_info): """Register attributes that can be computed with the server info.""" # Path relative to the server directory self.path = os.path.relpath(self.filename, start=server_info['notebook_dir']) # Replace backslashes on Windows if os.name == 'nt': self.path = self.path.replace('\\', '/') # Server url to send requests to self.server_url = server_info['url'] # Server token self.token = server_info['token'] url = url_path_join(self.server_url, 'notebook', url_escape(self.path)) # Set file url to load this notebook self.file_url = self.add_token(url)
def post(self): # Creates a new session # (unless a session already exists for the named nb) sm = self.session_manager cm = self.contents_manager km = self.kernel_manager model = self.get_json_body() if model is None: raise web.HTTPError(400, "No JSON data provided") try: path = model["notebook"]["path"] except KeyError: raise web.HTTPError(400, "Missing field in JSON data: notebook.path") try: kernel_name = model["kernel"]["name"] except KeyError: self.log.debug("No kernel name specified, using default kernel") kernel_name = None # Check to see if session exists if sm.session_exists(path=path): model = sm.get_session(path=path) else: try: model = sm.create_session(path=path, kernel_name=kernel_name) except NoSuchKernel: msg = ( "The '%s' kernel is not available. Please pick another " "suitable kernel instead, or install that kernel." % kernel_name ) status_msg = "%s not found" % kernel_name self.log.warn("Kernel not found: %s" % kernel_name) self.set_status(501) self.finish(json.dumps(dict(message=msg, short_message=status_msg))) return location = url_path_join(self.base_url, "api", "sessions", model["id"]) self.set_header("Location", url_escape(location)) self.set_status(201) self.finish(json.dumps(model, default=date_default))
def nbopen(filename, profile='default'): filename = os.path.abspath(filename) home_dir = os.path.expanduser('~') server_inf = find_best_server(filename, profile) if server_inf is not None: print("Using existing server at", server_inf['notebook_dir']) path = os.path.relpath(filename, start=server_inf['notebook_dir']) url = url_path_join(server_inf['url'], 'notebooks', url_escape(path)) webbrowser.open(url, new=2) else: if filename.startswith(home_dir): nbdir = home_dir else: nbdir = os.path.dirname(filename) print("Starting new server") notebookapp.launch_new_instance(file_to_run=os.path.abspath(filename), notebook_dir=nbdir, open_browser=True, argv=[], # Avoid it seeing our own argv )
def open_notebook(notebook_file): """Open the given IPython Notebook file in an existing or a new Jupyter Notebook server""" server = find_running_server(notebook_file) if server: logging.info( f"Using existing Jupyter server at {server['url']} (serving from {server['notebook_dir']})" ) rel_path = Path(notebook_file).resolve(strict=True).relative_to( Path(server['notebook_dir'])) url = url_path_join(server['url'], 'notebooks', url_escape(rel_path.as_posix())) nbapp = notebookapp.NotebookApp.instance() nbapp.load_config_file() browser = webbrowser.get(nbapp.browser or None) browser.open_new_tab(url) else: logging.info("Starting new Jupyter server to serve notebook file") launch_detached_process(sys.executable, '-m', 'notebook', '--NotebookApp.open_browser=True', notebook_file)
def get(self, path): _init_session(self.request, self.cookies) """ get renders the notebook template if a name is given, or redirects to the '/files/' handler if the name is not given. """ path = path.strip('/') cm = self.contents_manager # will raise 404 on not found try: model = cm.get(path, content=False) except web.HTTPError as e: log_event(g_log, 'loading_error', {'error': str(e)}) if e.status_code == 403: self.write(self.render_template('403.html', status_code=403)) return else: self.write(self.render_template( 'generic_error.html', message=e.log_message, status_code=e.status_code )) return if model.get('type') != 'notebook': # not a notebook, redirect to files return FilesRedirectHandler.redirect_to_files(self, path) path = url_escape(path) self.write( self.render_template( 'notebook.html', notebook_path=path, notebook_name=path, kill_kernel=False, mathjax_url=self.mathjax_url, google_analytics_id=URLS.google_analytics_id, userName=kbase_env.user, google_ad_id=URLS.google_ad_id, google_ad_conversion=URLS.google_ad_conversion, ) )
def get(self, path=''): """ Proxy API requests to GitHub, adding 'client_id' and 'client_secret' if they have been set. """ # Get access to the notebook config object c = GitHubConfig(config=self.config) try: api_path = url_path_join(GITHUB_API, url_escape(path)) # If the config has client_id and client_secret set, # apply them to the request. if c.client_id != '' and c.client_secret != '': api_path = url_concat(api_path, {'client_id': c.client_id,\ 'client_secret': c.client_secret,\ 'per_page': 100}) client = AsyncHTTPClient() request = HTTPRequest(api_path, user_agent='JupyterLab GitHub') response = yield client.fetch(request) data = json.loads(response.body.decode('utf-8')) # Check if we need to paginate results. # If so, get pages until all the results # are loaded into the data buffer. next_page_path = self._maybe_get_next_page_path(response) while next_page_path: request = HTTPRequest(next_page_path, user_agent='JupyterLab GitHub') response = yield client.fetch(request) next_page_path = self._maybe_get_next_page_path(response) data.extend(json.loads(response.body.decode('utf-8'))) # Send the results back. self.finish(json.dumps(data)) except HTTPError as err: self.set_status(err.code) self.finish(err.response.body)
def post(self): # Creates a new session #(unless a session already exists for the named nb) sm = self.session_manager cm = self.contents_manager km = self.kernel_manager model = self.get_json_body() if model is None: raise web.HTTPError(400, "No JSON data provided") try: path = model['notebook']['path'] except KeyError: raise web.HTTPError(400, "Missing field in JSON data: notebook.path") try: kernel_name = model['kernel']['name'] except KeyError: self.log.debug("No kernel name specified, using default kernel") kernel_name = None # Check to see if session exists if sm.session_exists(path=path): model = sm.get_session(path=path) else: try: model = sm.create_session(path=path, kernel_name=kernel_name) except NoSuchKernel: msg = ("The '%s' kernel is not available. Please pick another " "suitable kernel instead, or install that kernel." % kernel_name) status_msg = '%s not found' % kernel_name self.log.warn('Kernel not found: %s' % kernel_name) self.set_status(501) self.finish(json.dumps(dict(message=msg, short_message=status_msg))) return location = url_path_join(self.base_url, 'api', 'sessions', model['id']) self.set_header('Location', url_escape(location)) self.set_status(201) self.finish(json.dumps(model, default=date_default))
def get(self, path): _init_session(self.request, self.cookies) """ get renders the notebook template if a name is given, or redirects to the '/files/' handler if the name is not given. """ path = path.strip('/') cm = self.contents_manager # will raise 404 on not found try: model = cm.get(path, content=False) except web.HTTPError as e: log_event(g_log, 'loading_error', {'error': str(e)}) if e.status_code == 403: self.write(self.render_template('403.html', status_code=403)) return else: self.write( self.render_template('generic_error.html', message=e.log_message, status_code=e.status_code)) return if model.get('type') != 'notebook': # not a notebook, redirect to files return FilesRedirectHandler.redirect_to_files(self, path) path = url_escape(path) self.write( self.render_template( 'notebook.html', notebook_path=path, notebook_name=path, kill_kernel=False, mathjax_url=self.mathjax_url, google_analytics_id=URLS.google_analytics_id, ))
def test_url_escape_12(): #test for ? path = url_escape('hostname/?something/') assert path == 'hostname/%3Fsomething/'
def load_jupyter_server_extension(nbapp): """Load the JupyterLab server extension. """ # Delay imports to speed up jlpmapp from json import dumps from jupyterlab_server import add_handlers from notebook.utils import url_path_join as ujoin, url_escape from notebook._version import version_info from tornado.ioloop import IOLoop from markupsafe import Markup from .handlers.build_handler import build_path, Builder, BuildHandler from .handlers.extension_manager_handler import ( extensions_handler_path, ExtensionManager, ExtensionHandler ) from .handlers.error_handler import ErrorHandler from .commands import ( DEV_DIR, HERE, ensure_app, ensure_core, ensure_dev, watch, watch_dev, get_app_dir ) web_app = nbapp.web_app logger = nbapp.log base_url = nbapp.base_url # Handle the app_dir app_dir = getattr(nbapp, 'app_dir', get_app_dir()) # Check for core mode. core_mode = False if getattr(nbapp, 'core_mode', False) or app_dir.startswith(HERE): app_dir = HERE core_mode = True logger.info('Running JupyterLab in core mode') # Check for dev mode. dev_mode = False if getattr(nbapp, 'dev_mode', False) or app_dir.startswith(DEV_DIR): app_dir = DEV_DIR dev_mode = True logger.info('Running JupyterLab in dev mode') # Set the value on nbapp so it will get picked up in load_config nbapp.app_dir = app_dir config = load_config(nbapp) config.app_name = 'JupyterLab' config.app_namespace = 'jupyterlab' config.app_url = '/lab' config.cache_files = True # Check for watch. watch_mode = getattr(nbapp, 'watch', False) if watch_mode and core_mode: logger.warn('Cannot watch in core mode, did you mean --dev-mode?') watch_mode = False if core_mode and dev_mode: logger.warn('Conflicting modes, choosing dev_mode over core_mode') core_mode = False page_config = web_app.settings.setdefault('page_config_data', dict()) page_config['buildAvailable'] = not core_mode and not dev_mode page_config['buildCheck'] = not core_mode and not dev_mode page_config['devMode'] = dev_mode page_config['token'] = nbapp.token # Export the version info tuple to a JSON array. This gets printed # inside double quote marks, so we render it to a JSON string of the # JSON data (so that we can call JSON.parse on the frontend on it). # We also have to wrap it in `Markup` so that it isn't escaped # by Jinja. Otherwise, if the version has string parts these will be # escaped and then will have to be unescaped on the frontend. page_config['notebookVersion'] = Markup(dumps(dumps(version_info))[1:-1]) if nbapp.file_to_run and type(nbapp).__name__ == "LabApp": relpath = os.path.relpath(nbapp.file_to_run, nbapp.notebook_dir) uri = url_escape(ujoin('/lab/tree', *relpath.split(os.sep))) nbapp.default_url = uri nbapp.file_to_run = '' # Print messages. logger.info('JupyterLab extension loaded from %s' % HERE) logger.info('JupyterLab application directory is %s' % app_dir) build_url = ujoin(base_url, build_path) builder = Builder(logger, core_mode, app_dir) build_handler = (build_url, BuildHandler, {'builder': builder}) handlers = [build_handler] errored = False if core_mode: logger.info(CORE_NOTE.strip()) ensure_core(logger) elif dev_mode: if not watch_mode: ensure_dev(logger) logger.info(DEV_NOTE) # Make sure the app dir exists. else: msgs = ensure_app(app_dir) if msgs: [logger.error(msg) for msg in msgs] handler = (ujoin(base_url, '/lab'), ErrorHandler, { 'messages': msgs }) handlers.append(handler) errored = True if watch_mode: logger.info('Starting JupyterLab watch mode...') # Set the ioloop in case the watch fails. nbapp.ioloop = IOLoop.current() if dev_mode: watch_dev(logger) else: watch(app_dir, logger) page_config['buildAvailable'] = False config.cache_files = False if not core_mode and not errored: ext_url = ujoin(base_url, extensions_handler_path) ext_manager = ExtensionManager(logger, app_dir) ext_handler = (ext_url, ExtensionHandler, {'manager': ext_manager}) handlers.append(ext_handler) # Must add before the root server handlers to avoid shadowing. web_app.add_handlers('.*$', handlers) # If running under JupyterHub, add more metadata. if hasattr(nbapp, 'hub_prefix'): page_config['hubPrefix'] = nbapp.hub_prefix page_config['hubHost'] = nbapp.hub_host page_config['hubUser'] = nbapp.user api_token = os.getenv('JUPYTERHUB_API_TOKEN', '') page_config['token'] = api_token # Add the root handlers if we have not errored. if not errored: add_handlers(web_app, config)
def load_jupyter_server_extension(nbapp): """Load the JupyterLab server extension. """ # Delay imports to speed up jlpmapp from json import dumps from jupyterlab_launcher import add_handlers, LabConfig from notebook.utils import url_path_join as ujoin, url_escape from notebook._version import version_info from tornado.ioloop import IOLoop from markupsafe import Markup from .build_handler import build_path, Builder, BuildHandler from .commands import ( get_app_dir, get_user_settings_dir, watch, ensure_dev, watch_dev, pjoin, DEV_DIR, HERE, get_app_info, ensure_core, get_workspaces_dir ) web_app = nbapp.web_app logger = nbapp.log config = LabConfig() app_dir = getattr(nbapp, 'app_dir', get_app_dir()) user_settings_dir = getattr( nbapp, 'user_settings_dir', get_user_settings_dir() ) workspaces_dir = getattr( nbapp, 'workspaces_dir', get_workspaces_dir() ) # Print messages. logger.info('JupyterLab beta preview extension loaded from %s' % HERE) logger.info('JupyterLab application directory is %s' % app_dir) config.app_name = 'JupyterLab Beta' config.app_namespace = 'jupyterlab' config.page_url = '/lab' config.cache_files = True # Check for core mode. core_mode = False if getattr(nbapp, 'core_mode', False) or app_dir.startswith(HERE): core_mode = True logger.info('Running JupyterLab in core mode') # Check for dev mode. dev_mode = False if getattr(nbapp, 'dev_mode', False) or app_dir.startswith(DEV_DIR): dev_mode = True logger.info('Running JupyterLab in dev mode') # Check for watch. watch_mode = getattr(nbapp, 'watch', False) if watch_mode and core_mode: logger.warn('Cannot watch in core mode, did you mean --dev-mode?') watch_mode = False if core_mode and dev_mode: logger.warn('Conflicting modes, choosing dev_mode over core_mode') core_mode = False page_config = web_app.settings.setdefault('page_config_data', dict()) page_config['buildAvailable'] = not core_mode and not dev_mode page_config['buildCheck'] = not core_mode and not dev_mode page_config['token'] = nbapp.token page_config['devMode'] = dev_mode # Export the version info tuple to a JSON array. This get's printed # inside double quote marks, so we render it to a JSON string of the # JSON data (so that we can call JSON.parse on the frontend on it). # We also have to wrap it in `Markup` so that it isn't escaped # by Jinja. Otherwise, if the version has string parts these will be # escaped and then will have to be unescaped on the frontend. page_config['notebookVersion'] = Markup(dumps(dumps(version_info))[1:-1]) if nbapp.file_to_run and type(nbapp).__name__ == "LabApp": relpath = os.path.relpath(nbapp.file_to_run, nbapp.notebook_dir) uri = url_escape(ujoin('/lab/tree', *relpath.split(os.sep))) nbapp.default_url = uri nbapp.file_to_run = '' if core_mode: app_dir = HERE logger.info(CORE_NOTE.strip()) ensure_core(logger) elif dev_mode: app_dir = DEV_DIR ensure_dev(logger) if not watch_mode: logger.info(DEV_NOTE) config.app_settings_dir = pjoin(app_dir, 'settings') config.schemas_dir = pjoin(app_dir, 'schemas') config.themes_dir = pjoin(app_dir, 'themes') config.workspaces_dir = workspaces_dir info = get_app_info(app_dir) config.app_version = info['version'] public_url = info['publicUrl'] if public_url: config.public_url = public_url else: config.static_dir = pjoin(app_dir, 'static') config.user_settings_dir = user_settings_dir # The templates end up in the built static directory. config.templates_dir = pjoin(app_dir, 'static') if watch_mode: logger.info('Starting JupyterLab watch mode...') # Set the ioloop in case the watch fails. nbapp.ioloop = IOLoop.current() if dev_mode: watch_dev(logger) else: watch(app_dir, logger) page_config['buildAvailable'] = False config.cache_files = False base_url = web_app.settings['base_url'] build_url = ujoin(base_url, build_path) builder = Builder(logger, core_mode, app_dir) build_handler = (build_url, BuildHandler, {'builder': builder}) # Must add before the launcher handlers to avoid shadowing. web_app.add_handlers('.*$', [build_handler]) add_handlers(web_app, config)
def load_jupyter_server_extension(nbapp): """Load the JupyterLab server extension. """ # Delay imports to speed up jlpmapp from json import dumps from jupyterlab_server import add_handlers from notebook.utils import url_path_join as ujoin, url_escape from notebook._version import version_info from tornado.ioloop import IOLoop from markupsafe import Markup from .build_handler import build_path, Builder, BuildHandler from .extension_manager_handler import ( extensions_handler_path, ExtensionManager, ExtensionHandler ) from .commands import ( DEV_DIR, HERE, ensure_core, ensure_dev, watch, watch_dev, get_app_dir ) web_app = nbapp.web_app logger = nbapp.log # Handle the app_dir app_dir = getattr(nbapp, 'app_dir', get_app_dir()) # Check for core mode. core_mode = False if getattr(nbapp, 'core_mode', False) or app_dir.startswith(HERE): app_dir = HERE core_mode = True logger.info('Running JupyterLab in core mode') # Check for dev mode. dev_mode = False if getattr(nbapp, 'dev_mode', False) or app_dir.startswith(DEV_DIR): app_dir = DEV_DIR dev_mode = True logger.info('Running JupyterLab in dev mode') # Set the value on nbapp so it will get picked up in load_config nbapp.app_dir = app_dir config = load_config(nbapp) config.app_name = 'JupyterLab' config.app_namespace = 'jupyterlab' config.page_url = '/lab' config.cache_files = True # Check for watch. watch_mode = getattr(nbapp, 'watch', False) if watch_mode and core_mode: logger.warn('Cannot watch in core mode, did you mean --dev-mode?') watch_mode = False if core_mode and dev_mode: logger.warn('Conflicting modes, choosing dev_mode over core_mode') core_mode = False page_config = web_app.settings.setdefault('page_config_data', dict()) page_config['buildAvailable'] = not core_mode and not dev_mode page_config['buildCheck'] = not core_mode and not dev_mode page_config['token'] = nbapp.token page_config['devMode'] = dev_mode # Handle bundle url bundle_url = config.public_url if bundle_url.startswith(config.page_url): bundle_url = ujoin(nbapp.base_url, bundle_url) page_config['bundleUrl'] = bundle_url # Export the version info tuple to a JSON array. This gets printed # inside double quote marks, so we render it to a JSON string of the # JSON data (so that we can call JSON.parse on the frontend on it). # We also have to wrap it in `Markup` so that it isn't escaped # by Jinja. Otherwise, if the version has string parts these will be # escaped and then will have to be unescaped on the frontend. page_config['notebookVersion'] = Markup(dumps(dumps(version_info))[1:-1]) if nbapp.file_to_run and type(nbapp).__name__ == "LabApp": relpath = os.path.relpath(nbapp.file_to_run, nbapp.notebook_dir) uri = url_escape(ujoin('/lab/tree', *relpath.split(os.sep))) nbapp.default_url = uri nbapp.file_to_run = '' if core_mode: logger.info(CORE_NOTE.strip()) ensure_core(logger) elif dev_mode: ensure_dev(logger) if not watch_mode: logger.info(DEV_NOTE) # Print messages. logger.info('JupyterLab extension loaded from %s' % HERE) logger.info('JupyterLab application directory is %s' % app_dir) if watch_mode: logger.info('Starting JupyterLab watch mode...') # Set the ioloop in case the watch fails. nbapp.ioloop = IOLoop.current() if dev_mode: watch_dev(logger) else: watch(app_dir, logger) page_config['buildAvailable'] = False config.cache_files = False base_url = web_app.settings['base_url'] build_url = ujoin(base_url, build_path) builder = Builder(logger, core_mode, app_dir) build_handler = (build_url, BuildHandler, {'builder': builder}) handlers = [build_handler] if not core_mode: ext_url = ujoin(base_url, extensions_handler_path) ext_manager = ExtensionManager(logger, app_dir) ext_handler = (ext_url, ExtensionHandler, {'manager': ext_manager}) handlers.append(ext_handler) # Must add before the launcher handlers to avoid shadowing. web_app.add_handlers('.*$', handlers) add_handlers(web_app, config)
def test_url_escape_14(): #test for + path = url_escape('hostname/+something/') assert path == 'hostname/%2Bsomething/'
def load_jupyter_server_extension(nbapp): """Load the JupyterLab server extension. """ # Delay imports to speed up jlpmapp from json import dumps from jupyterlab_server import add_handlers from notebook.utils import url_path_join as ujoin, url_escape from notebook._version import version_info from tornado.ioloop import IOLoop from markupsafe import Markup from .handlers.build_handler import build_path, Builder, BuildHandler from .handlers.extension_manager_handler import (extensions_handler_path, ExtensionManager, ExtensionHandler) from .handlers.error_handler import ErrorHandler from .commands import (DEV_DIR, HERE, ensure_app, ensure_core, ensure_dev, watch, watch_dev, get_app_dir, AppOptions) web_app = nbapp.web_app logger = nbapp.log base_url = nbapp.base_url # Handle the app_dir app_dir = getattr(nbapp, 'app_dir', get_app_dir()) build_handler_options = AppOptions(logger=logger, app_dir=app_dir) # Check for core mode. core_mode = False if getattr(nbapp, 'core_mode', False) or app_dir.startswith(HERE): app_dir = HERE core_mode = True logger.info('Running JupyterLab in core mode') # Check for dev mode. dev_mode = False if getattr(nbapp, 'dev_mode', False) or app_dir.startswith(DEV_DIR): app_dir = DEV_DIR dev_mode = True logger.info('Running JupyterLab in dev mode') # Set the value on nbapp so it will get picked up in load_config nbapp.app_dir = app_dir config = load_config(nbapp) config.app_name = 'JupyterLab' config.app_namespace = 'jupyterlab' config.app_url = '/lab' config.cache_files = True # Check for watch. watch_mode = getattr(nbapp, 'watch', False) if watch_mode and core_mode: logger.warn('Cannot watch in core mode, did you mean --dev-mode?') watch_mode = False if core_mode and dev_mode: logger.warn('Conflicting modes, choosing dev_mode over core_mode') core_mode = False page_config = web_app.settings.setdefault('page_config_data', dict()) page_config['buildAvailable'] = not core_mode and not dev_mode page_config['buildCheck'] = not core_mode and not dev_mode page_config['devMode'] = dev_mode page_config['token'] = nbapp.token # Handle quit button with support for Notebook < 5.6 page_config['quitButton'] = getattr(nbapp, 'quit_button', False) # Client-side code assumes notebookVersion is a JSON-encoded string # TODO: fix this when we can make such a change page_config['notebookVersion'] = dumps(version_info) page_config['exposeAppInBrowser'] = getattr(nbapp, 'expose_app_in_browser', False) if nbapp.file_to_run and type(nbapp).__name__ == "LabApp": relpath = os.path.relpath(nbapp.file_to_run, nbapp.notebook_dir) uri = url_escape(ujoin('/lab/tree', *relpath.split(os.sep))) nbapp.default_url = uri nbapp.file_to_run = '' # Print messages. logger.info('JupyterLab extension loaded from %s' % HERE) logger.info('JupyterLab application directory is %s' % app_dir) build_url = ujoin(base_url, build_path) builder = Builder(None, core_mode, None, app_options=build_handler_options) build_handler = (build_url, BuildHandler, {'builder': builder}) handlers = [build_handler] errored = False if core_mode: logger.info(CORE_NOTE.strip()) ensure_core(logger) elif dev_mode: if not watch_mode: ensure_dev(logger) logger.info(DEV_NOTE) # Make sure the app dir exists. elif not watch_mode: msgs = ensure_app(app_dir) if msgs: [logger.error(msg) for msg in msgs] handler = (ujoin(base_url, '/lab'), ErrorHandler, { 'messages': msgs }) handlers.append(handler) errored = True if watch_mode: logger.info('Starting JupyterLab watch mode...') # Set the ioloop in case the watch fails. nbapp.ioloop = IOLoop.current() if dev_mode: watch_dev(logger) else: watch(app_options=build_handler_options) page_config['buildAvailable'] = False config.cache_files = False if not core_mode and not errored: ext_url = ujoin(base_url, extensions_handler_path) ext_manager = ExtensionManager(app_options=build_handler_options) ext_handler = (ext_url, ExtensionHandler, {'manager': ext_manager}) handlers.append(ext_handler) # Must add before the root server handlers to avoid shadowing. web_app.add_handlers('.*$', handlers) # If running under JupyterHub, add more metadata. if hasattr(nbapp, 'hub_prefix'): page_config['hubPrefix'] = nbapp.hub_prefix page_config['hubHost'] = nbapp.hub_host page_config['hubUser'] = nbapp.user # Assume the server_name property indicates running JupyterHub 1.0. if hasattr(nbapp, 'server_name'): page_config['hubServerName'] = nbapp.server_name api_token = os.getenv('JUPYTERHUB_API_TOKEN', '') page_config['token'] = api_token # Add the root handlers if we have not errored. if not errored: add_handlers(web_app, config)
def test_url_escape_13(): #test for : path = url_escape('hostname/:something/') assert path == 'hostname/%3Asomething/'