-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add functions to call fast WoRMS API directly
- Loading branch information
1 parent
8e0d760
commit 21942b8
Showing
3 changed files
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
from typing import List | ||
|
||
from fathomnet.api import EndpointManager | ||
from fathomnet.dto import WormsNode | ||
|
||
|
||
class Worms(EndpointManager): | ||
ROOT = 'https://fathomnet.org' | ||
PATH = 'worms' | ||
|
||
|
||
def count_names() -> int: | ||
"""Get the total number of names available.""" | ||
return int(Worms.get('names/count')) | ||
|
||
|
||
def get_all_names(limit: int = 100, offset: int = 0) -> List[str]: | ||
"""Get all names.""" | ||
res_json = Worms.get('names', params={'limit': limit, 'offset': offset}) | ||
return res_json['items'] | ||
|
||
|
||
def get_ancestors_names(name: str) -> List[str]: | ||
"""Get all ancestors' names of a given name.""" | ||
return Worms.get(f'ancestors/{name}') | ||
|
||
|
||
def get_children_names(name: str) -> List[str]: | ||
"""Get all children's names of a given name.""" | ||
return Worms.get(f'children/{name}') | ||
|
||
|
||
def get_descendants_names(name: str) -> List[str]: | ||
"""Get all descendants' names of a given name.""" | ||
return Worms.get(f'descendants/{name}') | ||
|
||
|
||
def get_parent_name(name: str) -> str: | ||
"""Get the parent's name of a given name.""" | ||
return Worms.get(f'parent/{name}') | ||
|
||
|
||
def find_names_containing(fragment: str) -> List[str]: | ||
"""Get all names that contain a fragment.""" | ||
return Worms.get(f'query/contains/{fragment}') | ||
|
||
|
||
def find_names_by_prefix(prefix: str) -> List[str]: | ||
"""Get all names that start with a prefix.""" | ||
return Worms.get(f'query/startswith/{prefix}') | ||
|
||
|
||
def get_synonyms_for_name(name: str) -> List[str]: | ||
"""Get all synonyms for a name.""" | ||
return Worms.get(f'synonyms/{name}') | ||
|
||
|
||
def get_ancestors(name: str) -> WormsNode: | ||
"""Get a taxa tree from the root node to the node for the given name.""" | ||
res_json = Worms.get(f'taxa/ancestors/{name}') | ||
return WormsNode.from_dict(res_json) | ||
|
||
|
||
def get_children(name: str) -> List[WormsNode]: | ||
"""Get the child taxa nodes of a given name.""" | ||
res_json = Worms.get(f'taxa/children/{name}') | ||
return [WormsNode.from_dict(item) for item in res_json] | ||
|
||
|
||
def get_descendants(name: str) -> WormsNode: | ||
"""Get a taxa tree from the given name to the leaves.""" | ||
res_json = Worms.get(f'taxa/descendants/{name}') | ||
return WormsNode.from_dict(res_json) | ||
|
||
|
||
def get_parent(name: str) -> WormsNode: | ||
"""Get the parent taxa node of a given name.""" | ||
res_json = Worms.get(f'taxa/parent/{name}') | ||
return WormsNode.from_dict(res_json) | ||
|
||
|
||
def get_info(name: str) -> WormsNode: | ||
"""Get a taxa node for a given name.""" | ||
res_json = Worms.get(f'taxa/info/{name}') | ||
return WormsNode.from_dict(res_json) | ||
|
||
|
||
def find_taxa_by_prefix(prefix: str, rank: str = None, parent: str = None) -> List[WormsNode]: | ||
"""Get all taxa nodes that start with a prefix.""" | ||
params = {} | ||
if rank is not None: | ||
params['rank'] = rank | ||
if parent is not None: | ||
params['parent'] = parent | ||
|
||
res_json = Worms.get(f'taxa/query/startswith/{prefix}', params=params) | ||
return [WormsNode.from_dict(item) for item in res_json] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
from unittest import TestCase | ||
|
||
from fathomnet.api import worms | ||
from fathomnet.dto import WormsNode | ||
|
||
|
||
def check_for_name(node: WormsNode, name: str) -> bool: | ||
"""Recursively check if a node or one of its descendants has a given name.""" | ||
def recurse_check(node: WormsNode) -> bool: | ||
print(node.name, name) | ||
if node.name == name: | ||
return True | ||
if not node.children: | ||
return False | ||
return any(recurse_check(child) for child in node.children) | ||
return recurse_check(node) | ||
|
||
|
||
class TestWormsAPI(TestCase): | ||
|
||
def test_count_names(self): | ||
count = worms.count_names() | ||
self.assertIsNotNone(count) | ||
self.assertGreater(count, 0) | ||
|
||
def test_get_all_names(self): | ||
names = worms.get_all_names() | ||
self.assertIsNotNone(names) | ||
|
||
def test_get_ancestors_names(self): | ||
ancestors = worms.get_ancestors_names('Animalia') | ||
self.assertIsNotNone(ancestors) | ||
self.assertIn('object', ancestors) | ||
|
||
def test_get_children_names(self): | ||
children = worms.get_children_names('Bathochordaeus') | ||
self.assertIsNotNone(children) | ||
self.assertIn('Bathochordaeus charon', children) | ||
|
||
def test_get_descendants_names(self): | ||
descendants = worms.get_descendants_names('Bathochordaeus') | ||
self.assertIsNotNone(descendants) | ||
self.assertIn('Bathochordaeus charon', descendants) | ||
|
||
def test_get_parent_name(self): | ||
parent = worms.get_parent_name('Bathochordaeus charon') | ||
self.assertIsNotNone(parent) | ||
self.assertEqual('Bathochordaeus', parent) | ||
|
||
def test_find_names_containing(self): | ||
names = worms.find_names_containing('pendicula') | ||
self.assertIsNotNone(names) | ||
self.assertIn('Appendicularia', names) | ||
|
||
def test_find_names_by_prefix(self): | ||
names = worms.find_names_by_prefix('Appendicula') | ||
self.assertIsNotNone(names) | ||
self.assertIn('Appendicularia', names) | ||
|
||
def test_get_synonyms_for_name(self): | ||
synonyms = worms.get_synonyms_for_name('Appendicularia') | ||
self.assertIsNotNone(synonyms) | ||
self.assertIn('larvaceans', synonyms) | ||
|
||
def test_get_ancestors(self): | ||
root_node = worms.get_ancestors('Animalia') | ||
self.assertIsNotNone(root_node) | ||
self.assertTrue(check_for_name(root_node, 'object'), 'No "object" node found in ancestors') | ||
|
||
def test_get_children(self): | ||
children = worms.get_children('Bathochordaeus') | ||
self.assertIsNotNone(children) | ||
for child in children: | ||
if child.name == 'Bathochordaeus charon': | ||
return | ||
self.fail('No "Bathochordaeus charon" child found') | ||
|
||
def test_get_descendants(self): | ||
taxa_node = worms.get_descendants('Bathochordaeus') | ||
self.assertIsNotNone(taxa_node) | ||
self.assertTrue(check_for_name(taxa_node, 'Bathochordaeus charon'), 'No "Bathochordaeus charon" descendant found') | ||
|
||
def test_get_parent(self): | ||
parent = worms.get_parent('Bathochordaeus charon') | ||
self.assertIsNotNone(parent) | ||
self.assertEqual('Bathochordaeus', parent.name) | ||
|
||
def test_get_info(self): | ||
info = worms.get_info('Bathochordaeus charon') | ||
self.assertIsNotNone(info) | ||
self.assertEqual('Bathochordaeus charon', info.name) | ||
|
||
def test_find_taxa_by_prefix(self): | ||
taxa = worms.find_taxa_by_prefix('Appendicula') | ||
self.assertIsNotNone(taxa) | ||
for taxon in taxa: | ||
if taxon.name == 'Appendicularia': | ||
return | ||
self.fail('No "Appendicularia" taxon found') |