1- import logging
2- import urllib
31from collections import ChainMap
42from dataclasses import dataclass , field
5- from typing import Any , Dict , Iterable , Iterator , List , Tuple , Union
3+ from typing import Any , ClassVar , Dict , Iterable , Iterator , List , Tuple , Union
64
75import requests
6+ from ols_client import Client , EBIClient , TIBClient
87from sssom_schema import Mapping
98
109from oaklib .datamodels import oxo
1110from oaklib .datamodels .oxo import ScopeEnum
1211from oaklib .datamodels .search import SearchConfiguration , SearchProperty
1312from oaklib .datamodels .text_annotator import TextAnnotation
1413from oaklib .datamodels .vocabulary import IS_A , SEMAPV
15- from oaklib .implementations .ols import SEARCH_CONFIG
16- from oaklib .implementations .ols .oxo_utils import load_oxo_payload
1714from oaklib .interfaces .basic_ontology_interface import PREFIX_MAP
1815from oaklib .interfaces .mapping_provider_interface import MappingProviderInterface
1916from oaklib .interfaces .search_interface import SearchInterface
2017from oaklib .interfaces .text_annotator_interface import TextAnnotatorInterface
2118from oaklib .types import CURIE , PRED_CURIE
2219
20+ from .constants import SEARCH_CONFIG
21+ from .oxo_utils import load_oxo_payload
22+
23+ __all__ = [
24+ # Abstract classes
25+ "BaseOlsImplementation" ,
26+ # Concrete classes
27+ "OlsImplementation" ,
28+ "TIBOlsImplementation" ,
29+ ]
30+
2331ANNOTATION = Dict [str , Any ]
2432SEARCH_ROWS = 50
2533
3240
3341
3442@dataclass
35- class OlsImplementation (TextAnnotatorInterface , SearchInterface , MappingProviderInterface ):
43+ class BaseOlsImplementation (TextAnnotatorInterface , SearchInterface , MappingProviderInterface ):
3644 """
3745 Implementation over OLS and OxO APIs
3846 """
3947
40- ols_api_key : str = None
48+ ols_client_class : ClassVar [ type [ Client ]]
4149 label_cache : Dict [CURIE , str ] = field (default_factory = lambda : {})
4250 base_url = "https://www.ebi.ac.uk/spot/oxo/api/mappings"
43- ols_base_url = "https://www.ebi.ac.uk/ols/api"
4451 _prefix_map : Dict [str , str ] = field (default_factory = lambda : {})
4552 focus_ontology : str = None
53+ client : Client = field (init = False )
4654
4755 def __post_init__ (self ):
56+ self .client = self .ols_client_class ()
4857 if self .focus_ontology is None :
4958 if self .resource :
5059 self .focus_ontology = self .resource .slug
@@ -71,30 +80,20 @@ def annotate_text(self, text: str) -> Iterator[TextAnnotation]:
7180 def ancestors (
7281 self , start_curies : Union [CURIE , List [CURIE ]], predicates : List [PRED_CURIE ] = None
7382 ) -> Iterable [CURIE ]:
74- query = "hierarchicalAncestors"
83+ func = self . client . iter_hierarchical_ancestors
7584 if predicates :
7685 if predicates == [IS_A ]:
77- query = "ancestors"
86+ func = self . client . iter_ancestors
7887 elif IS_A not in predicates :
7988 raise NotImplementedError (f"OLS always include { IS_A } , you selected: { predicates } " )
8089 if not isinstance (start_curies , list ):
8190 start_curies = [start_curies ]
8291 ancs = set ()
8392 ontology = self .focus_ontology
8493 for curie in start_curies :
85- term_id = self .curie_to_uri (curie )
86- # must be double encoded https://www.ebi.ac.uk/ols/docs/api
87- term_id_quoted = urllib .parse .quote (term_id , safe = "" )
88- term_id_quoted = urllib .parse .quote (term_id_quoted , safe = "" )
89- url = f"{ self .ols_base_url } /ontologies/{ ontology } /terms/{ term_id_quoted } /{ query } "
90- logging .debug (f"URL={ url } " )
91- result = requests .get (url )
92- obj = result .json ()
93- if result .status_code == 200 and "_embedded" in obj :
94- ancs .update ([x ["obo_id" ] for x in obj ["_embedded" ]["terms" ]])
95- else :
96- logging .debug (f"No ancestors for { url } (maybe ontology not indexed in OLS?)" )
97- ancs = []
94+ iri = self .curie_to_uri (curie )
95+ records = func (ontology = ontology , iri = iri )
96+ ancs .update (record ["obo_id" ] for record in records )
9897 return list (ancs )
9998
10099 # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -119,7 +118,6 @@ def basic_search(
119118 query_fields .update (["description" ])
120119
121120 params = {
122- "q" : search_term ,
123121 "type" : "class" ,
124122 "local" : "true" ,
125123 "fieldList" : "iri,label" ,
@@ -134,19 +132,10 @@ def basic_search(
134132 if self .focus_ontology :
135133 params ["ontology" ] = self .focus_ontology .lower ()
136134
137- finished = False
138- while not finished :
139- response = requests .get (f"{ self .ols_base_url } /search" , params = params )
140- logging .debug (f"URL={ response .url } " )
141- body = response .json ()
142- params ["start" ] += params ["rows" ]
143- if params ["start" ] > body ["response" ]["numFound" ]:
144- finished = True
145- for doc in body ["response" ]["docs" ]:
146- curie = self .uri_to_curie (doc ["iri" ])
147- label = doc ["label" ]
148- self .label_cache [curie ] = label
149- yield curie
135+ for record in self .client .search (search_term , params = params ):
136+ curie = self .uri_to_curie (record ["iri" ])
137+ self .label_cache [curie ] = record ["label" ]
138+ yield curie
150139
151140 # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
152141 # Implements: MappingsInterface
@@ -199,3 +188,15 @@ def convert_payload(self, container: oxo.Container) -> Iterator[Mapping]:
199188 # msdoc.mapping_set.mappings.append(m)
200189 # n += 1
201190 # return n
191+
192+
193+ class OlsImplementation (BaseOlsImplementation ):
194+ """Implementation for the EBI OLS instance."""
195+
196+ ols_client_class = EBIClient
197+
198+
199+ class TIBOlsImplementation (BaseOlsImplementation ):
200+ """Implementation for the TIB Hannover OLS instance."""
201+
202+ ols_client_class = TIBClient
0 commit comments