From c5d8bf9e42de54d590b0c3bcdb5f822a1fecb4a2 Mon Sep 17 00:00:00 2001
From: Diane Adjavon <diane.adjavon@ed.ac.uk>
Date: Fri, 7 Feb 2020 15:54:49 +0000
Subject: [PATCH] Begin testing suite

---
 README.md                     | 25 +++++++++++++--
 config.json                   |  1 +
 core/__init__.py              |  1 +
 core/{omero.py => connect.py} | 42 ++++++++++---------------
 install.sh                    |  6 ++++
 omero_py/__init__.py          |  5 +++
 test/__init__.py              |  0
 test/connect_to_omero.py      | 54 ++++++++++++++++----------------
 test/test_connections.py      | 59 +++++++++++++++++++++++++++++++++++
 9 files changed, 138 insertions(+), 55 deletions(-)
 create mode 100644 config.json
 rename core/{omero.py => connect.py} (64%)
 create mode 100644 install.sh
 create mode 100644 omero_py/__init__.py
 create mode 100644 test/__init__.py
 create mode 100644 test/test_connections.py

diff --git a/README.md b/README.md
index 0f6d0e0d..73ab9ee6 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,26 @@
 
 The core classes and methods for the python microfluidics, microscopy, and analysis pypline pipeline.
 
-References:
-* OMERO python bindings : https://docs.openmicroscopy.org/omero/5.4.0/developers/Python.html
-* Ice3.5 : https://zeroc.com/downloads/ice/3.5#macos
+## References
+* [OMERO python bindings](https://docs.openmicroscopy.org/omero/5.4.0/developers/Python.html)
+* [Zeroc-ice python](https://pypi.org/project/zeroc-ice/3.6.5/) 
+
+## Installation 
+How to set up access to OMERO from python:
+* Install openssl headers version 1.0.2: `sudo apt-get install libssl1.0-dev`
+* Install the corresponding openssl (as default is 1.1.1): `conda install openssl==1.0.2k`
+* Install bzip headers : `sudo apt-get install libbz2-dev`
+* Install zeroc-ice from PyPI, which includes Ice: `pip install zeroc-ice==3.6.0`
+* Run `connect_to_omero.py` as a test (TODO TESTS)
+
+## Disclaimers
+TLDR: Most of this stuff is depcrecated. 
+Using OMERO 5.2.5 means that we need to use depreacted python 2.7 (EOL 2020.01.01), 
+and we need to use `zeroc-ice` version 3.6 which is also dropped in the newer version of OMERO.
+The local version of `openssl` (`conda`) needs to fit the headers of `libssl-dev` (`apt-get`). 
+By default conda will install OpenSSL version 1.1.1 as all the others are no longer maintained. 
+However, using the headers of verions 1.0.2 means that we have to downgrade OpenSSL to version 1.0.2 also. 
+
+It is highly recommended that we upgrade OMERO to 5.6 in order to use Python 3, in which case it will even 
+be possible to get OMERO.py directly from PyPI with easy installation, [omero-py](https://pypi.org/project/omero-py/)
 
diff --git a/config.json b/config.json
new file mode 100644
index 00000000..2cadfef2
--- /dev/null
+++ b/config.json
@@ -0,0 +1 @@
+{"host": "sce-bio-c04287.bio.ed.ac.uk", "password": "***REMOVED***", "port": 4064, "user": "upload"}
diff --git a/core/__init__.py b/core/__init__.py
index e69de29b..d28ccbde 100644
--- a/core/__init__.py
+++ b/core/__init__.py
@@ -0,0 +1 @@
+import omero_py
diff --git a/core/omero.py b/core/connect.py
similarity index 64%
rename from core/omero.py
rename to core/connect.py
index 1f148c3a..3389fcda 100644
--- a/core/omero.py
+++ b/core/connect.py
@@ -5,68 +5,56 @@
 # Copyright (C) 2014 University of Dundee & Open Microscopy Environment.
 #                    All Rights Reserved.
 # Use is subject to license terms supplied in LICENSE.txt
+import itertools
 
-
-USERNAME = 'upload'
-PASSWORD = '***REMOVED***'
-HOST = 'sce-bio-c04287.bio.ed.ac.uk'
-PORT = 4064
 from omero.gateway import BlitzGateway
 
 from utils import repr_obj
 
 class Database:
-    def __init__(self):
-        self.conn = BlitzGateway(USERNAME, PASSWORD, host=HOST, port=PORT)
+    def __init__(self, username, password, host, port):
+        self.conn = BlitzGateway(username, password, host=host, port=port)
 
     def __repr__(self):
         return repr_obj(self.conn)
         _
-    def connect(self):
+    def connect(self, secure=False):
         connected = self.conn.connect()
-
-        # Check if you are connected
-        # ==========================
-        if not connected:
-            import sys
-            sys.stderr.write(
-                "Error: Connection not available, please check your user name and"
-                " password.\n")
-            sys.exit(1)
-
-        # Using secure connection
-        # =======================
-        # By default, once we have logged in, data transfer is not encrypted
-        # (faster)
-        # To use a secure connection, call setSecure(True):
-
-        #self.conn.setSecure(True)         # <--------- Uncomment this
+        self.conn.setSecure(secure)
+        return connected
     
     def disconnect(self):
         self.conn.seppuku()
 
     @property
     def user(self):
+        # TODO cache
         user = self.conn.getUser()
         return dict(ID=user.getId(), Username=user.getName())
 
     @property
     def groups(self):
+        # TODO cache
         return [dict(ID=g.getId(), Name=g.getName()) for g in
                 self.conn.getGroupsMemberOf()]
 
     @property
     def current_group(self):
+        # TODO cache
         g = self.conn.getGroupFromContext()
         return dict(ID=g.getId(), Name=g.getName())
 
     def isAdmin(self):
+        # TODO cache
         return self.conn.isAdmin()
 
     def getDataset(self, dataset_id):
         ds = self.conn.getObject("Dataset", dataset_id)
         return Dataset(ds)
 
+    def getDatasets(self, n):
+        top_n = itertools.islice(self.conn.getObjects("Dataset"), n)
+        return [Dataset(ds) for ds in top_n]
 
 class Dataset:
     def __init__(self, dataset_wrapper):
@@ -75,6 +63,10 @@ class Dataset:
     def __repr__(self):
         return repr_obj(self.dataset)
 
+    def getImages(self, n):
+        top_n = itertools.islice(self.dataset.listChildren(), n)
+        return [Image(im) for im in top_n]
+
 class Image:
     def __init__(self, image_wrapper):
         self.image = image_wrapper
diff --git a/install.sh b/install.sh
new file mode 100644
index 00000000..638039e7
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,6 @@
+sudo apt-get install libbz2-dev # Install bzip headers
+sudo apt-get install libssl1.0-dev # Install openssl headers
+conda install openssl==1.0.2n # Install local openssl to match
+pip install --no-cache-dir zeroc-ice==3.6.5
+python connect_to_omero.py
+
diff --git a/omero_py/__init__.py b/omero_py/__init__.py
new file mode 100644
index 00000000..d7648721
--- /dev/null
+++ b/omero_py/__init__.py
@@ -0,0 +1,5 @@
+import os
+THISPATH = os.path.dirname(os.path.abspath(__file__))
+
+import sys
+sys.path.insert(0, THISPATH)
diff --git a/test/__init__.py b/test/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/test/connect_to_omero.py b/test/connect_to_omero.py
index 92a56da7..d91eece9 100644
--- a/test/connect_to_omero.py
+++ b/test/connect_to_omero.py
@@ -7,13 +7,13 @@
 #                    All Rights Reserved.
 # Use is subject to license terms supplied in LICENSE.txt
 #
+from __future__ import print_function
 
-"""
-FOR TRAINING PURPOSES ONLY!
-"""
-import sys
-sys.path.insert(0, './omero_py')
-
+# TODO remove and use unittest to run tests
+import os 
+import sys 
+sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
+import omero_py
 
 USERNAME = 'upload'
 PASSWORD = '***REMOVED***'
@@ -26,12 +26,12 @@ def print_obj(obj, indent=0):
     Helper method to display info about OMERO objects.
     Not all objects will have a "name" or owner field.
     """
-    print """%s%s:%s  Name:"%s" (owner=%s)""" % (
+    print("""%s%s:%s  Name:"%s" (owner=%s)""" % (
         " " * indent,
         obj.OMERO_CLASS,
         obj.getId(),
         obj.getName(),
-        obj.getAnnotation())
+        obj.getAnnotation()))
 
 
 if __name__ == '__main__':
@@ -74,40 +74,40 @@ if __name__ == '__main__':
     # clients.
 
     user = conn.getUser()
-    print "Current user:"
-    print "   ID:", user.getId()
-    print "   Username:", user.getName()
-    print "   Full Name:", user.getFullName()
+    print( "Current user:")
+    print( "   ID:", user.getId())
+    print( "   Username:", user.getName())
+    print( "   Full Name:", user.getFullName())
 
     # Check if you are an Administrator
-    print "   Is Admin:", conn.isAdmin()
+    print( "   Is Admin:", conn.isAdmin())
 
-    print "Member of:"
+    print( "Member of:")
     for g in conn.getGroupsMemberOf():
-        print "   ID:", g.getId(), " Name:", g.getName()
+        print( "   ID:", g.getId(), " Name:", g.getName())
     group = conn.getGroupFromContext()
-    print "Current group: ", group.getName()
+    print( "Current group: ", group.getName())
 
     # List the group owners and other members
     owners, members = group.groupSummary()
-    print "   Group owners:"
+    print( "   Group owners:")
     for o in owners:
-        print "     ID: %s UserName: %s Name: %s" % (
-            o.getId(), o.getOmeName(), o.getFullName())
-    print "   Group members:"
+        print( "     ID: %s UserName: %s Name: %s" % (
+            o.getId(), o.getOmeName(), o.getFullName()))
+    print( "   Group members:")
     for m in members:
-        print "     ID: %s UserName: %s Name: %s" % (
-            m.getId(), m.getOmeName(), m.getFullName())
+        print( "     ID: %s UserName: %s Name: %s" % (
+            m.getId(), m.getOmeName(), m.getFullName()))
 
-    print "Owner of:"
+    print( "Owner of:")
     for g in conn.listOwnedGroups():
-        print "   ID: ", g.getId(), " Name:", g.getName()
+        print( "   ID: ", g.getId(), " Name:", g.getName())
 
     # New in OMERO 5
-    print "Admins:"
+    print( "Admins:")
     for exp in conn.getAdministrators():
-        print "   ID: %s UserName: %s Name: %s" % (
-            exp.getId(), exp.getOmeName(), exp.getFullName())
+        print( "   ID: %s UserName: %s Name: %s" % (
+            exp.getId(), exp.getOmeName(), exp.getFullName()))
 
     # The 'context' of our current session
     ctx = conn.getEventContext()
diff --git a/test/test_connections.py b/test/test_connections.py
new file mode 100644
index 00000000..27923029
--- /dev/null
+++ b/test/test_connections.py
@@ -0,0 +1,59 @@
+"""
+Testing suite for connection to OMERO
+"""
+# TODO use omero.gateway.scripts.testdb_create module
+from __future__ import print_function
+
+import sys
+print(sys.path)
+
+import unittest
+import json
+
+import omero_py
+from core.connect import Database, Dataset
+
+class TestConnections(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        with open('config.json', 'r') as fd:
+            config = json.load(fd)
+        cls._config = config
+        cls._db = Database(cls._config['user'], 
+                                   cls._config['password'], 
+                                   cls._config['host'], 
+                                   cls._config['port'])
+
+    @classmethod
+    def tearDownClass(cls):
+        cls._db.disconnect()
+    
+    def testConnection(self):
+        self.assertTrue(self._db.connect())
+
+    def testUser(self):
+        self.assertEquals(self._db.user['Username'], self._config['user'])
+
+    def testDataset(self):
+        dataset = self._db.getDatasets(1)
+        self.assertTrue(dataset is not None)
+        # FIXME cannot do this as it is instanciated anew.
+        # self._ds = dataset
+
+    def testImage(self):
+        dataset = self._db.getDatasets(1)
+        self.assertTrue(dataset is not None)
+       
+        #FIXME return single dataset
+        image = dataset[0].getImages(1)
+        self.assertTrue(image is not None)
+        # FIXME cannot do this as it is instanciated anew.
+        self._im = image
+
+    def testRenderImage(self):
+        pass
+
+
+if __name__ == "__main__":
+    unittest.main()
-- 
GitLab