Repository: SynBioDex/tyto (language: python)

Issue:
List ontologies for a given endpoint
`QueryBackEnds` should have a method that allows the user to display and list all ontologies available at a given endpoint


Discussion / hints:

Fix patch:
diff --git a/tyto/endpoint/endpoint.py b/tyto/endpoint/endpoint.py
index 08fbcdc..3f13e19 100644
--- a/tyto/endpoint/endpoint.py
+++ b/tyto/endpoint/endpoint.py
@@ -145,17 +145,27 @@ def is_descendant_of(self, ontology: "Ontology", descendant_uri: str, ancestor_u
         descendants = self.query(ontology, query, error_msg)
         return descendant_uri in descendants
 
-    def get_ontology(self):
+    def get_ontologies(self):
         query = '''
-            SELECT distinct ?ontology_uri
+            SELECT distinct ?ontology_uri ?title
+            {from_clause}
             WHERE
-              {
-                ?ontology_uri a owl:Ontology
-              }
+              {{
+                ?ontology_uri a owl:Ontology .
+                ?ontology_uri <http://purl.org/dc/elements/1.1/title> ?title
+              }}
             '''
         error_msg = 'Graph not found'
-        response = self._query(ontology, query, error_msg)[0]
-        return response
+        response = self.query(None, query, error_msg)
+        if not response or len(response) == 0:
+            raise Exception('No ontologies found for this endpoint')
+
+        # Response is a flat list; pack into tuples of (uri, ontology name)
+        ontologies = {}
+        n_ontologies = int(len(response) / 2)
+        for uri, ontology_name in zip(response[:n_ontologies], response[n_ontologies+1:]):
+            ontologies[uri] = ontology_name
+        return ontologies
 
 
 class Endpoint(QueryBackend, abc.ABC):
@@ -199,9 +209,10 @@ def convert(self, response):
         if response:
             response = response.convert()  # Convert http response to JSON
             var = response['head']['vars'][0]
-            for binding in response['results']['bindings']:
-                if var in binding:
-                    converted_response.append(binding[var]['value'])
+            for var in response['head']['vars']:
+                for binding in response['results']['bindings']:
+                    if var in binding:
+                        converted_response.append(binding[var]['value'])
         return converted_response
 
 
@@ -239,7 +250,7 @@ def query(self, ontology, sparql, err_msg):
         # http://purl.obolibrary.org/obo/$foo.owl (note foo must be all lowercase
         # by OBO conventions) to http://purl.obolibrary.org/obo/merged/uppercase($foo).
         from_clause = ''
-        if ontology.uri:
+        if ontology:
             ontology_uri = ontology.uri
             if 'http://purl.obolibrary.org/obo/' in ontology_uri:
                 ontology_uri = ontology_uri.replace('http://purl.obolibrary.org/obo/', '')
@@ -379,6 +390,10 @@ def is_ancestor_of(self, ontology: "Ontology", ancestor_uri: str, descendant_uri
         ancestor_uri = ontology._reverse_sanitize_uri(ancestor_uri)
         return ancestor_uri in self.get_ancestors(ontology, descendant_uri)
 
+    def get_ontologies(self):
+        if not self.ontology_short_ids:
+            self._load_ontology_ids()
+        return self.ontology_short_ids
 
     def convert(self, response):
         pass


Test patch:
diff --git a/test/test_ontology.py b/test/test_ontology.py
index fa13860..833aac7 100644
--- a/test/test_ontology.py
+++ b/test/test_ontology.py
@@ -90,6 +90,14 @@ def test_nonunique_labels(self):
         with self.assertRaises(LookupError):
             uri = o.foobar
 
+    def test_get_ontologies(self):
+       self.assertEqual(tyto.Ontobee.get_ontologies()\
+                        ['http://purl.obolibrary.org/obo/gno.owl'],
+                        'Echinoderm Anatomy and Development Ontology')
+       self.assertEqual(tyto.EBIOntologyLookupService.get_ontologies()
+                        ['http://purl.obolibrary.org/obo/gno.owl'],
+                        'gno')
+
 class TestOLS(unittest.TestCase):
 
     SO_endpoints = SO.endpoints