Skip to content

Commit d2fba29

Browse files
Simplify downloader adapter and update documentation and tests (#25)
* feat: change explicit downloader adapter by strings to reduce user cognitive load * docs: update documentation based on latest changes in previous commit * test: update unit tests accordingly to changes to improve the client API * chores: update showcase script and configuration file
1 parent 62bb7f7 commit d2fba29

11 files changed

Lines changed: 113 additions & 32 deletions

File tree

04_workdir.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ logging:
77
filename: logs/app_go_logger.log
88
loggers:
99
default:
10-
level: DEBUG
10+
level: WARNING
11+
12+
# Logger configuration for each package
1113
pkg_infra:
1214
level: INFO
13-
handlers: [file, console]
14-
propagate: false
15+
1516
download_manager:
1617
level: INFO
1718
handlers: [file, console]
@@ -30,6 +31,7 @@ integrations: # New question: store the big yaml?
3031
settings:
3132
- enabled: true # This will be switch <--- what should be the default value?
3233
- cache_path: ontograph_config.yaml
34+
- downloader: download_manager
3335
- source_ontology: chebi
3436
- backend: graphblas
3537

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ from ontograph.config.settings import DEFAULT_CACHE_DIR
3636
# Instantiate a client for your catalog
3737
client_catalog = ClientCatalog(cache_dir="./data/out")
3838

39-
# Optional: choose a downloader adapter explicitly
39+
# Optional: choose downloader via string or adapter (client-level only)
40+
# client_catalog = ClientCatalog(cache_dir="./data/out", downloader="download_manager")
4041
# downloader = DownloadManagerAdapter(cache_dir=DEFAULT_CACHE_DIR, backend="requests")
4142
# client_catalog = ClientCatalog(cache_dir="./data/out", downloader=downloader)
4243

@@ -71,7 +72,8 @@ client_dummy_ontology = ClientOntology(cache_dir="./data/out")
7172
# Load a dummy ontology, we prepare a simple one to try out this package.
7273
client_dummy_ontology.load(source="./tests/resources/dummy_ontology.obo")
7374

74-
# Optional: choose a downloader adapter explicitly
75+
# Optional: choose downloader via string or adapter (client-level only)
76+
# client_dummy_ontology = ClientOntology(cache_dir="./data/out", downloader="pooch")
7577
# downloader = DownloadManagerAdapter(cache_dir=DEFAULT_CACHE_DIR, backend="requests")
7678
# client_dummy_ontology = ClientOntology(cache_dir="./data/out", downloader=downloader)
7779
```
@@ -158,6 +160,7 @@ client_go.load(source="go")
158160
By default, the project uses a configurable downloader backend. You can set a global default in `ontograph/config/settings.py`:
159161

160162
```python
163+
# Used as the fallback when no downloader is provided
161164
DEFAULT_DOWNLOADER = "pooch"
162165
# or
163166
DEFAULT_DOWNLOADER = "download_manager"

docs/learn/tutorials/quickstart.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ client_catalog = ClientCatalog(cache_dir="./data/out")
2020
# Load the catalog (downloads if not cached)
2121
client_catalog.load_catalog()
2222

23-
# Optional: choose a downloader adapter explicitly
23+
# Optional: choose downloader via string or adapter (client-level only)
24+
# client_catalog = ClientCatalog(cache_dir="./data/out", downloader="download_manager")
2425
# downloader = DownloadManagerAdapter(cache_dir=DEFAULT_CACHE_DIR, backend="requests")
2526
# client_catalog = ClientCatalog(cache_dir="./data/out", downloader=downloader)
2627
```
@@ -63,7 +64,8 @@ client_ontology = ClientOntology(cache_dir="./data/out")
6364
# Load a sample ontology (provided in the repo for testing)
6465
client_ontology.load(source="./tests/resources/dummy_ontology.obo")
6566

66-
# Optional: choose a downloader adapter explicitly
67+
# Optional: choose downloader via string or adapter (client-level only)
68+
# client_ontology = ClientOntology(cache_dir="./data/out", downloader="pooch")
6769
# downloader = DownloadManagerAdapter(cache_dir=DEFAULT_CACHE_DIR, backend="requests")
6870
# client_ontology = ClientOntology(cache_dir="./data/out", downloader=downloader)
6971
```

docs/learn/tutorials/tutorial0001_basics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ DEFAULT_DOWNLOADER = "download_manager"
1515
```
1616

1717
Now any client will use the configured backend unless you pass a downloader explicitly.
18+
Only client classes accept backend strings; lower-level components expect a downloader adapter instance.
1819

1920
---
2021

docs/reference/source/ontograph/client-catalog.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ from ontograph.config.settings import DEFAULT_CACHE_DIR
2424

2525
client_catalog = ClientCatalog(cache_dir="./data/out")
2626

27-
# Optional: use Download Manager for all catalog downloads
27+
# Optional: use a backend string (client-level only)
28+
# client_catalog = ClientCatalog(cache_dir="./data/out", downloader="download_manager")
29+
# Or pass the adapter explicitly
2830
# downloader = DownloadManagerAdapter(cache_dir=DEFAULT_CACHE_DIR, backend="requests")
2931
# client_catalog = ClientCatalog(cache_dir="./data/out", downloader=downloader)
3032
```

docs/reference/source/ontograph/client-ontology.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ from ontograph.config.settings import DEFAULT_CACHE_DIR
2424

2525
client_ontology = ClientOntology(cache_dir="./data/out")
2626

27-
# Optional: use Download Manager for all remote downloads
27+
# Optional: use a backend string (client-level only)
28+
# client_ontology = ClientOntology(cache_dir="./data/out", downloader="pooch")
29+
# Or pass the adapter explicitly
2830
# downloader = DownloadManagerAdapter(cache_dir=DEFAULT_CACHE_DIR, backend="requests")
2931
# client_ontology = ClientOntology(cache_dir="./data/out", downloader=downloader)
3032
```

docs/reference/source/ontograph/downloader.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ from ontograph.config.settings import DEFAULT_CACHE_DIR
1515
downloader = get_default_downloader(cache_dir=DEFAULT_CACHE_DIR)
1616
```
1717

18+
Note: String backends (e.g., `"pooch"`, `"download_manager"`) are accepted
19+
at the client layer (`ClientCatalog` / `ClientOntology`). Lower-level
20+
components expect a downloader adapter instance.
21+
1822
---
1923

2024
## API Reference

ontograph/client.py

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
NodesDataframe,
3434
CatalogOntologies,
3535
)
36-
from ontograph.downloader import DownloaderPort
36+
from ontograph.downloader import DownloaderPort, get_default_downloader
3737
from ontograph.config.settings import DEFAULT_CACHE_DIR
3838
from ontograph.queries.navigator import (
3939
NavigatorPronto,
@@ -58,6 +58,16 @@
5858
]
5959

6060

61+
def _resolve_downloader(
62+
cache_dir: Path, downloader: DownloaderPort | str | None
63+
) -> DownloaderPort:
64+
if isinstance(downloader, str):
65+
return get_default_downloader(cache_dir=cache_dir, backend=downloader)
66+
if downloader is None:
67+
return get_default_downloader(cache_dir=cache_dir, backend='pooch')
68+
return downloader
69+
70+
6171
# --------------------------------------------- #
6272
# ---- Client for Catalog --- #
6373
# --------------------------------------------- #
@@ -76,19 +86,22 @@ class ClientCatalog:
7686
def __init__(
7787
self,
7888
cache_dir: str = DEFAULT_CACHE_DIR,
79-
downloader: DownloaderPort | None = None,
89+
downloader: DownloaderPort | str | None = None,
8090
) -> None:
8191
"""Initialize the ClientCatalog.
8292
8393
Args:
8494
cache_dir (str, optional): Directory for caching catalog data. Defaults to DEFAULT_CACHE_DIR.
85-
downloader (DownloaderPort | None, optional): Downloader adapter for remote resources. Defaults to None.
95+
downloader (DownloaderPort | str | None, optional): Downloader adapter or backend name
96+
('pooch' or 'download_manager'). Defaults to 'pooch'.
8697
"""
98+
cache_path = Path(cache_dir)
99+
resolved_downloader = _resolve_downloader(cache_path, downloader)
87100
self.__catalog_adapter = CatalogOntologies(
88-
cache_dir=Path(cache_dir),
89-
downloader=downloader,
101+
cache_dir=cache_path,
102+
downloader=resolved_downloader,
90103
)
91-
self._downloader = downloader
104+
self._downloader = resolved_downloader
92105

93106
def load_catalog(self, force_download: bool = False) -> None:
94107
"""Load the ontology catalog.
@@ -231,17 +244,18 @@ class ClientOntology:
231244
def __init__(
232245
self,
233246
cache_dir: str = DEFAULT_CACHE_DIR,
234-
downloader: DownloaderPort | None = None,
247+
downloader: DownloaderPort | str | None = None,
235248
) -> None:
236249
"""Initialize the ClientOntology.
237250
238251
Args:
239252
cache_dir (str, optional): Directory for caching ontology data. Defaults to DEFAULT_CACHE_DIR.
240-
downloader (DownloaderPort | None, optional): Downloader adapter for remote resources. Defaults to None.
253+
downloader (DownloaderPort | str | None, optional): Downloader adapter or backend name
254+
('pooch' or 'download_manager'). Defaults to 'pooch'.
241255
"""
242256
self._cache_dir = Path(cache_dir)
257+
self._downloader = _resolve_downloader(self._cache_dir, downloader)
243258
self._ontology = None
244-
self._downloader = downloader
245259
self._lookup_tables = None
246260
self._navigator = None
247261
self._relations = None
@@ -331,7 +345,7 @@ def _detect_source_type(self, source: str) -> str:
331345
def load(
332346
self,
333347
source: str,
334-
downloader: DownloaderPort = None,
348+
downloader: DownloaderPort | str | None = None,
335349
include_obsolete: bool = False,
336350
backend: str = 'pronto',
337351
) -> None:
@@ -346,7 +360,8 @@ def load(
346360
347361
Args:
348362
source (str): Path to the ontology file, URL, or OBO Foundry identifier.
349-
downloader (DownloaderPort, optional): Downloader adapter for remote files. Defaults to None.
363+
downloader (DownloaderPort | str | None, optional): Downloader adapter or backend name
364+
('pooch' or 'download_manager'). Defaults to None.
350365
include_obsolete (bool, optional): If True, include obsolete terms when building GraphBLAS structures. Defaults to False.
351366
backend (str, optional): Backend for queries ('pronto' or 'graphblas'). Defaults to 'pronto'.
352367
@@ -362,12 +377,19 @@ def load(
362377
>>> client.load(source="./tests/resources/dummy_ontology.obo")
363378
"""
364379
logger.info(f'Loading ontology from source: {source} ...')
380+
resolved_downloader = (
381+
_resolve_downloader(self._cache_dir, downloader)
382+
if downloader is not None
383+
else self._downloader
384+
)
365385
logger.debug(
366386
'Using downloader: %s',
367-
type(downloader).__name__ if downloader else 'default',
387+
type(resolved_downloader).__name__
388+
if resolved_downloader
389+
else 'default',
368390
)
369391
loader = ProntoLoaderAdapter(
370-
cache_dir=self._cache_dir, downloader=self._downloader
392+
cache_dir=self._cache_dir, downloader=resolved_downloader
371393
)
372394

373395
path = Path(source)
@@ -388,14 +410,16 @@ def load(
388410
f'Detected URL source, downloading ontology from {source}'
389411
)
390412
filename = Path(source).name or 'ontology.obo'
391-
ontology = loader.load_from_url(source, filename, downloader)
413+
ontology = loader.load_from_url(
414+
source, filename, resolved_downloader
415+
)
392416

393417
# 3. Case 3: Try OBO catalog (if file missing or simple ID)
394418
else:
395419
logger.debug('Resolved source type: catalog')
396420
catalog_client = ClientCatalog(
397421
cache_dir=self._cache_dir,
398-
downloader=self._downloader,
422+
downloader=resolved_downloader,
399423
)
400424
catalog_client.load_catalog()
401425
available = [
@@ -410,7 +434,7 @@ def load(
410434
ontology = loader.load_from_catalog(
411435
name_id=name_id,
412436
format='obo',
413-
downloader=self._downloader,
437+
downloader=resolved_downloader,
414438
)
415439
else:
416440
msg = f"Ontology '{source}' not found as file, URL, or catalog entry."

ontograph/loader.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,7 @@ def _download_ontology(
410410
downloader = self._downloader
411411
if downloader is None:
412412
downloader = get_default_downloader(cache_dir=self.cache_dir)
413-
logger.debug(
414-
f'Created default downloader: {type(downloader).__name__}'
415-
)
413+
logger.debug(f'Created default downloader: {type(downloader).__name__}')
416414

417415
logger.info(
418416
'Downloading ontology %s.%s using %s (catalog)',
@@ -520,9 +518,7 @@ def load_from_url(
520518
downloader = self._downloader
521519
if downloader is None:
522520
downloader = get_default_downloader(cache_dir=self.cache_dir)
523-
logger.debug(
524-
f'Created default downloader: {type(downloader).__name__}'
525-
)
521+
logger.debug(f'Created default downloader: {type(downloader).__name__}')
526522

527523
logger.info(
528524
'Downloading ontology from URL using %s: %s',

sandbox/use_case_downloaders.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ def main():
3838
client = ClientOntology(cache_dir=cache_dir, downloader=downloader)
3939
client.load(source='go') # catalog download
4040

41+
# Print roots of GO ontology
42+
logger.info("Roots GO ontology: ")
43+
logger.info(f"{client.get_root()}")
44+
4145
if __name__ == '__main__':
4246

4347
main()

0 commit comments

Comments
 (0)