From 3017361904582bf206d7c37fc46e89b26931db61 Mon Sep 17 00:00:00 2001
From: vermeul <swen@ethz.ch>
Date: Wed, 31 Oct 2018 18:10:32 +0100
Subject: [PATCH] added server.py

---
 jupyter-openbis-extension/.server.py.swp      | Bin 0 -> 28672 bytes
 jupyter-openbis-extension/__init__.py         |   0
 .../__pycache__/__init__.cpython-36.pyc       | Bin 0 -> 161 bytes
 .../__pycache__/extension.cpython-36.pyc      | Bin 0 -> 2057 bytes
 .../__pycache__/server.cpython-36.pyc         | Bin 0 -> 6373 bytes
 jupyter-openbis-extension/server.py           | 238 ++++++++++++++++++
 6 files changed, 238 insertions(+)
 create mode 100644 jupyter-openbis-extension/.server.py.swp
 create mode 100644 jupyter-openbis-extension/__init__.py
 create mode 100644 jupyter-openbis-extension/__pycache__/__init__.cpython-36.pyc
 create mode 100644 jupyter-openbis-extension/__pycache__/extension.cpython-36.pyc
 create mode 100644 jupyter-openbis-extension/__pycache__/server.cpython-36.pyc
 create mode 100644 jupyter-openbis-extension/server.py

diff --git a/jupyter-openbis-extension/.server.py.swp b/jupyter-openbis-extension/.server.py.swp
new file mode 100644
index 0000000000000000000000000000000000000000..c294c69447df13190139740612a621e8cc044143
GIT binary patch
literal 28672
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

literal 0
HcmV?d00001

diff --git a/jupyter-openbis-extension/__init__.py b/jupyter-openbis-extension/__init__.py
new file mode 100644
index 0000000..e69de29
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
GIT binary patch
literal 161
zcmXr!<>jhByCs?d2p)q77+?f49Dul(1xTbY1T$zd`mJOr0tq9CUw-<b#i>Qb`ems_
zxv8Z&`dOs~l_jY~y7>jEc}bbYx~UZ<sd>ej`FVI`;^Q;(GE3s)^$IF)aoFVMr<CTT
L+JWpT24V&PvAQeO

literal 0
HcmV?d00001

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
GIT binary patch
literal 2057
zcmaJ?Uys{F5Z_(@iO+Fz=~Yxvpje_p<fJ+hyr2`RPHHQtkgk>5!pS^XPIm9&)Un;&
zHP^TaFR6Ir1@YJ~z&qkI@C}gmm8X6Mo|xS@cjZrOYuB^0GqW?ZzZrkp>-pV3e*JdU
zLFiBP%3}k42t)h?6Gar~XpUoyHBE9dw_?lCR&LLo*ujW7)TYjlIChyk>rj_=*2GA7
zxfgq&<>fo^j`{kr58s`<I}hT($oP40-jDn9-FO$)T^c+`@qqSdAHJ8qKy;T5o+CP7
z*4m2qsP_O3FTDi6&=9L$&GV#6<usX<Spkgx-TMnUEsHPHg650^r*p4j#W)kqwW*Yq
zI2esY#j`@*C^!6w$!QZ!rXXs8wYc*g<8xN$&ETtAN|w`<Qkd&cq9YIqCQ~+foRqb!
zYB?mz0~Jx_nN&Vdbz$g<_HO$SAa21BK1>u-lHpSfF<3{+otL!ES@Yqnt`?H<txGr9
zQ^^XEl|^(;{erkQa54RLZ}dnoE=H}tqt_aF!_K++s9LBGlGa25cEM_LzH3q}c6Agw
z9E5oQ^8{-e9t{^gOqe%;SfUwPVTxBo;w7FDO5Q=#T9cIpD{D!Xmb6dEDb^s70G*jD
zJ8Qhw0CONUZZp4?=6QHFWko2bEIfB4%tV-%DP=VB{ScmmD&^@sEXG@()2ccMH@6?k
z(r6!*l8wvqad^hYo5;ef5Hc+$EHXwKE84#vd*f8F1a7ezj9P4rXexmzn?bbz2(?Ea
zgwIw-Lr-<UUIOQFos-xDIhhrwA`SpC$#eriq58MM#sel>L@LLiPq`;0pQn=RybbNR
z_m2p8Pg@M8rI0%H0F5H<aR43LE-!GvyCAFH*I9Y({apqTgFocB*d_zKhxsMo{RgOr
zTJUX{7>Y4PF`+oND4`aVqD^hM8;AE{ySa9|JS+5>Cc~UPshN<BhHbFt&~QQcT^I%$
zzX744u?BD~`VxS#giBwMZ&0ysBWXSM`5{L71u0wC%FNLc)OtY-IKY8pv<Q}D=7J3i
z^gaW<4(R=W(aOfCd9T%UwC2)YgX<T%)Lz-&+sCLN$4Gj!oteJ`FwVLFOvmWCdPO^+
z>%ghr3u}AoaHqN2f+`Jb08x1V(ZjF}JIa2BN`RDXE*j7gPRcr`VNuF(%)*nhE@%YJ
z!UfRDS}1?>eF(5VYCd|M8f`Pos0Q52-*wvex58(s2t_@aFd<IrJYR$t(i-;9R?*Pn
zd!VA+3i{by$~6XtLEJlKGMS08NX8{yC|t%}&7m8hEC1^>uh|{WORk(Vo&od*pa?y@
z^+xU7c{*X0gyy73DU_|dud;Rf<!|XDTxAQEpO^*UN2o3ZXk<ldR50Tj4*!O)1>N*I
z@Wsb4A<H8K_u;h(Ap_#VD!>D?+Jp6g03TM(UYm`!v?4HaG<1}gBt<%BNuvBD*|b=o
zgCu!Ur+K^6NfKI4l7xqF-Yedi9;++Lz+7(%U7;SfEyEdJj{9(}rk_N$%yO}*{wwE9
z-9@5p^>Yi9W5;w4Q|kN*FqD&*r&$46gL~jtHOGa%lV@XqMm?^0sqdBR+EKw~BZ58$
tu!A2p;+~##12#2m-1@%=l=t~2_?x;<o2m{Vj{)&vcv!!XRm-!z-rwt0ESLZQ

literal 0
HcmV?d00001

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
GIT binary patch
literal 6373
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

literal 0
HcmV?d00001

diff --git a/jupyter-openbis-extension/server.py b/jupyter-openbis-extension/server.py
new file mode 100644
index 0000000..8a6781c
--- /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'])
+
-- 
GitLab