diff --git a/jupyter-openbis-extension/.server.py.swp b/jupyter-openbis-extension/.server.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..c294c69447df13190139740612a621e8cc044143 Binary files /dev/null and b/jupyter-openbis-extension/.server.py.swp differ diff --git a/jupyter-openbis-extension/__init__.py b/jupyter-openbis-extension/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/jupyter-openbis-extension/__pycache__/__init__.cpython-36.pyc b/jupyter-openbis-extension/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..17c85d6c830fc23516d571d3b9fbc90fd636a634 Binary files /dev/null and b/jupyter-openbis-extension/__pycache__/__init__.cpython-36.pyc differ diff --git a/jupyter-openbis-extension/__pycache__/extension.cpython-36.pyc b/jupyter-openbis-extension/__pycache__/extension.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5f03417cffd6d3922495cb9dca6bf4efab96353 Binary files /dev/null and b/jupyter-openbis-extension/__pycache__/extension.cpython-36.pyc differ diff --git a/jupyter-openbis-extension/__pycache__/server.cpython-36.pyc b/jupyter-openbis-extension/__pycache__/server.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a1e17fe0c786f4007391b5c58e6c6c99190b531 Binary files /dev/null and b/jupyter-openbis-extension/__pycache__/server.cpython-36.pyc differ diff --git a/jupyter-openbis-extension/server.py b/jupyter-openbis-extension/server.py new file mode 100644 index 0000000000000000000000000000000000000000..8a6781c7fc2b90b8518cfc8b2ce59e4c405934cc --- /dev/null +++ b/jupyter-openbis-extension/server.py @@ -0,0 +1,238 @@ +from notebook.utils import url_path_join +from notebook.base.handlers import IPythonHandler +from pybis import Openbis + +import json +import os +import urllib +from subprocess import check_output +from urllib.parse import urlsplit, urlunsplit +import yaml + +openbis_connections = {} + + +def _jupyter_server_extension_paths(): + return [{'module': 'jupyter-openbis-extension.server'}] + +def _load_configuration(filename='openbis-connections.yaml'): + + home = os.path.expanduser("~") + abs_filename = os.path.join(home, '.jupyter', filename) + + with open(abs_filename, 'r') as stream: + try: + config = yaml.safe_load(stream) + return config + except yaml.YAMLexception as exc: + print(exc) + return None + + +def load_jupyter_server_extension(nb_server_app): + """Call when the extension is loaded. + :param nb_server_app: Handle to the Notebook webserver instance. + """ + + # load the configuration file + config = _load_configuration() + if config is not None: + for conn in config['connections']: + try: + register_connection(conn) + except Exception as exc: + print(exc) + + + web_app = nb_server_app.web_app + host_pattern = '.*$' + + base_url = web_app.settings['base_url'] + + web_app.add_handlers( + host_pattern, + [(url_path_join( + base_url, + '/openbis/dataset/(?P<connection_name>.*)?/(?P<permId>.*)'), + DataSetHandler + )] + ) + web_app.add_handlers( + host_pattern, + [(url_path_join( + base_url, + '/openbis/sample/(?P<connection_name>.*)?/(?P<permId>.*)'), + SampleHandler + )] + ) + web_app.add_handlers( + host_pattern, + [(url_path_join(base_url, '/openbis/conn'), OpenBISHandler)] + ) + + + print("pybis loaded: {}".format(Openbis)) + + +def register_connection(connection_info): + + conn = OpenBISConnection( + name = connection_info['name'], + url = connection_info['url'], + verify_certificates = connection_info['verify_certificates'], + username = connection_info['username'], + password = connection_info['password'], + status = 'not connected', + ) + openbis_connections[conn.name] = conn + + openbis = Openbis( + url = conn.url, + verify_certificates = conn.verify_certificates + ) + conn.openbis = openbis + + try: + openbis.login( + username = conn.username, + password = conn.password + ) + conn.status = 'connected' + except Exception as exc: + conn.status = 'FAILED: {}'.format(exc) + raise exc + + +def check_connection(connection_name): + """Checks whether connection is valid and session is still active + and tries to reconnect, if possible. Returns the active session + """ + + if connection_name not in openbis_connections: + return None + + conn = openbis_connections[connection_name] + if not conn.openbis.isSessionActive(): + conn.openbis.login(conn.username, conn.password) + + +class OpenBISConnection: + """register an openBIS connection + """ + + def __init__(self, **kwargs): + for key in kwargs: + setattr(self, key, kwargs[key]) + + def is_session_active(self): + return self.openbis.is_session_active() + + def reconnect(self): + openbis.login(self.username, self.password) + + +class OpenBISHandler(IPythonHandler): + """Handle the requests to /openbis/conn + """ + + def get(self): + """returns all available openBIS connections + """ + connections= [] + for conn in openbis_connections.values(): + connections.append({ + 'name': conn.name, + 'url' : conn.url + }) + + self.write({ + 'connections': connections + }) + return + +class SampleHandler(IPythonHandler): + """Handle the requests for /openbis/sample/connection/permId""" + + def get_datasets(self, conn, permId): + sample = None + try: + sample = conn.openbis.get_sample(permId) + except Exception: + self.send_error( + reason = 'No such sample found: {}'.format(permId) + ) + return + + datasets = sample.get_datasets().df + dataset_records = datasets.to_dict(orient='records') + self.write({'dataSets': dataset_records }) + return + + def get(self, **params): + """Handle a request to /openbis/sample/connection_name/permId + download the data and return a message + """ + try: + conn = openbis_connections[params['connection_name']] + except KeyError: + self.send_error( + reason = 'connection {} was not found'.format(params['connection_name']) + ) + return + + results = self.get_datasets(conn, params['permId']) + + +class DataSetHandler(IPythonHandler): + """Handle the requests for /openbis/dataset/connection/permId""" + + + def download_data(self, conn, permId): + if not conn.is_session_active(): + try: + conn.reconnect() + except Exception as exc: + self.send_error( + reason = 'connection to {} could not be established: {}'.format(conn.name, exc) + ) + return + + try: + dataset = conn.openbis.get_dataset(permId) + except Exception as exc: + self.send_error( + reason = 'No such dataSet found: {}'.format(permId) + ) + return + + # dataset was found, download the data to the disk + try: + destination = dataset.download() + except Exception as exc: + print(exc) + self.send_error( + reason = 'Data for DataSet {} could not be downloaded: {}'.format(permId, exc) + ) + return + + # return success message + path = os.path.join(destination, dataset.permId) + self.write({ + 'permId' : dataset.permId, + 'statusText': 'Data for DataSet {} was successfully downloaded to {}.'.format(dataset.permId, path) + }) + + def get(self, **params): + """Handle a request to /openbis/dataset/connection_name/permId + download the data and return a message + """ + try: + conn = openbis_connections[params['connection_name']] + except KeyError: + self.send_error( + reason = 'connection {} was not found'.format(params['connection_name']) + ) + return + + results = self.download_data(conn, params['permId']) +