INCATools / INCATools/ontology-access-kit

OLS adapter graph traversal lacks descendants() and reflexive keyword parity

Open
#886 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
198
Forks
35
Avg merge
3d 4h
Merged PRs (30d)
1

Description

Tested with `oaklib==0.7.0rc7` and Python 3.12.

The OLS adapter's graph traversal API differs from other OAK graph adapters in ways that make portable downstream traversal code harder:

1. `ancestors()` does not accept the `reflexive` keyword used by other adapters.
2. `descendants()` is not exposed, even though OLS4 has descendant endpoints.

## Reproducer

```python
from oaklib import get_adapter
import importlib.metadata as md

print(md.version("oaklib")) # 0.7.0rc7
adapter = get_adapter("ols:go")

list(adapter.ancestors(
"GO:0009987",
predicates=["rdfs:subClassOf"],
reflexive=False,
))
# TypeError: BaseOlsImplementation.ancestors() got an unexpected keyword argument 'reflexive'

print(hasattr(adapter, "descendants"))
# False
```

## Expected behavior

Ideally, OLS graph traversal would be API-compatible with other OAK graph adapters:

```python
adapter.ancestors(curie_or_curies, predicates=[...], reflexive=False)
adapter.descendants(curie_or_curies, predicates=[...], reflexive=False)
```

If exact parity is not feasible, it would help to have a documented shared traversal helper/contract for downstream code that needs to work across `simpleobo:`, `ols:`, `ubergraph:`, `sqlite:obo:`, and `owl:`/`funowl:`.

## Current downstream workaround

In `linkml-term-validator`, I had to:

- inspect traversal method signatures before passing `reflexive`
- normalize reflexive inclusion/exclusion after receiving results
- call the OLS4 `/descendants` endpoint directly as a fallback for greedy dynamic enum expansion

This seems like behavior OAK could centralize for the OLS adapter or graph interface.

Contributor guide

Open the contributing guide

Research direction

Start with the OLS adapter returned by get_adapter("ols:go") and inspect BaseOlsImplementation. Run the reproducer against the stated oaklib version, then compare OLS traversal behavior with the other adapters named in the issue. Done means ancestors() accepts reflexive and descendants() is available with compatible behavior, or the shared contract is documented if exact parity is not feasible.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.