Repository: SynBioDex/tyto (language: python)

Issue:
Implement __getitem__ 
Some ontology terms, especially in NCBI taxonomy contain special characters that would result in invalid attribute names, e.g., `NCBITaxon.Escherichia_coli_#1/H766` 

This could be avoided by also supporting `__getitem__` method, e.g., `NCBITaxon['Escherichia coli #1/H766']`


Discussion / hints:

Fix patch:
diff --git a/setup.py b/setup.py
index 580c533..07b7c2f 100644
--- a/setup.py
+++ b/setup.py
@@ -36,7 +36,8 @@
       install_requires=[
             'rdflib>=5.0',
             'SPARQLWrapper',
-            'requests'
+            'requests',
+            'pyparsing<3'  # See https://github.com/RDFLib/rdflib/issues/1190
       ],
       test_suite='test',
       tests_require=[
diff --git a/tyto/endpoint/endpoint.py b/tyto/endpoint/endpoint.py
index feab17a..ad159fa 100644
--- a/tyto/endpoint/endpoint.py
+++ b/tyto/endpoint/endpoint.py
@@ -297,6 +297,7 @@ def get_uri_by_term(self, ontology: "Ontology", term: str):
             raise LookupError(f'Ontology {ontology.uri} is not available at EBI Ontology Lookup Service')
         short_id = self.ontology_short_ids[ontology.uri]
 
+        term = urllib.parse.quote_plus(term)
         get_query = f'{self.url}/search?q={term}&ontology={short_id}&queryFields=label'
         response = requests.get(get_query)
         if response.status_code == 200:
diff --git a/tyto/tyto.py b/tyto/tyto.py
index 82df554..5d585ec 100644
--- a/tyto/tyto.py
+++ b/tyto/tyto.py
@@ -51,24 +51,30 @@ def _handler(self, method_name, exception, *args):
         # than querying over the network
         if self.graph and self.graph.is_loaded():
             method = getattr(self.graph, method_name)
-            try:
-                response = method(self, *args)
-                if response is not None:
-                    return response
-            except Exception as x:
-                LOGGER.error(x)
+            response = method(self, *args)
+            if response is not None:
+                return response
+            #try:
+            #    response = method(self, *args)
+            #    if response is not None:
+            #        return response
+            #except Exception as x:
+            #    LOGGER.error(x)
 
         # Try endpoints
         if self.endpoints:
             for e in self.endpoints:
                 method = getattr(e, method_name)
-                try:
-                    response = method(self, *args)
-                    if response is not None:
-                        return response
-                except Exception as x:
-                    LOGGER.error(x)
-                    raise
+                response = method(self, *args)
+                if response is not None:
+                    return response
+                #try:
+                #    response = method(self, *args)
+                #    if response is not None:
+                #        return response
+                #except Exception as x:
+                #    LOGGER.error(x)
+                #    raise
 
         # If the connection fails or nothing found, fall back and load the ontology locally
         if self.graph and not self.graph.is_loaded():
@@ -119,6 +125,8 @@ def _reverse_sanitize_term(self, term):
         # or changing camel-case to snake-case
         return term
 
+    def __getitem__(self, key):
+        return self.get_uri_by_term(key)
 
 class URI(str):
 


Test patch:
diff --git a/test/test_ontology.py b/test/test_ontology.py
index a43cc1e..2609447 100644
--- a/test/test_ontology.py
+++ b/test/test_ontology.py
@@ -17,6 +17,13 @@ def test_SO(self):
         term_b = SO.get_term_by_uri('http://identifiers.org/so/SO:0000110')
         self.assertEqual(term_a, term_b)
 
+    def test_getitem(self):
+        # For terms with special characters, we must use subscripting
+        # rather than dynamic attributes for ontology terms
+        term_a = 'Escherichia coli #1/H766'
+        uri = NCBITaxon[term_a]
+        self.assertEqual(uri, 'https://identifiers.org/taxonomy:1354003')
+
     def test_SBO(self):
         uri_a = 'https://identifiers.org/SBO:0000000'
         term = SBO.get_term_by_uri(uri_a)