INCATools / INCATools/ontology-access-kit
OLS adapter graph traversal lacks descendants() and reflexive keyword parity
- 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
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