Source code for tooluniverse.obis_tool
import json
from typing import Any, Dict
from urllib.parse import urlencode
from urllib.request import Request, urlopen
from tooluniverse.tool_registry import register_tool
def _http_get(
url: str,
headers: Dict[str, str] | None = None,
timeout: int = 30,
) -> Dict[str, Any]:
req = Request(url, headers=headers or {})
with urlopen(req, timeout=timeout) as resp:
data = resp.read()
try:
return json.loads(data.decode("utf-8", errors="ignore"))
except Exception:
return {"raw": data.decode("utf-8", errors="ignore")}
[docs]
@register_tool(
"OBISTaxaTool",
config={
"name": "OBIS_search_taxa",
"type": "OBISTaxaTool",
"description": "Resolve marine taxa by scientific name via OBIS /v3/taxon",
"parameter": {
"type": "object",
"properties": {
"scientificname": {
"type": "string",
"description": "Scientific name to search, e.g., 'Gadus'",
},
"size": {
"type": "integer",
"default": 10,
"minimum": 1,
"maximum": 100,
},
},
"required": ["scientificname"],
},
"settings": {"base_url": "https://api.obis.org/v3", "timeout": 30},
},
)
class OBISTaxaTool:
[docs]
def run(self, arguments: Dict[str, Any]):
base = self.tool_config.get("settings", {}).get(
"base_url", "https://api.obis.org/v3"
)
timeout = int(self.tool_config.get("settings", {}).get("timeout", 30))
scientificname = arguments.get("scientificname")
size = int(arguments.get("size", 10))
# Note: OBIS v3 API does not have /taxon endpoint
# Use occurrence search with scientificname filter instead
# This returns occurrences which can be used to identify taxa
query = {
"scientificname": scientificname,
"size": size,
}
url = f"{base}/occurrence?{urlencode(query)}"
try:
data = _http_get(
url, headers={"Accept": "application/json"}, timeout=timeout
)
# Extract unique taxa from occurrences
if isinstance(data, dict) and "results" in data:
results = data.get("results", [])
# Extract unique scientific names and taxonomic info
taxa_list = []
seen_names = set()
for occ in results:
sci_name = occ.get("scientificName")
if sci_name and sci_name not in seen_names:
seen_names.add(sci_name)
taxa_list.append(
{
"scientificName": sci_name,
"aphiaID": occ.get("aphiaID"),
"rank": occ.get("taxonRank"),
"kingdom": occ.get("kingdom"),
"phylum": occ.get("phylum"),
"class": occ.get("class_"),
"order": occ.get("order"),
"family": occ.get("family"),
"genus": occ.get("genus"),
}
)
if len(taxa_list) >= size:
break
# Return in expected schema format
wrapped_data = {
"results": taxa_list,
"total": len(taxa_list),
}
else:
wrapped_data = {"results": [], "total": 0}
return {
"source": "OBIS",
"endpoint": "occurrence", # Note: taxon endpoint not available, using occurrence
"query": query,
"data": wrapped_data,
"success": True,
}
except Exception as e:
return {
"error": str(e),
"source": "OBIS",
"endpoint": "occurrence",
"success": False,
}
[docs]
@register_tool(
"OBISOccurrenceTool",
config={
"name": "OBIS_search_occurrences",
"type": "OBISOccurrenceTool",
"description": "Search OBIS occurrences via /v3/occurrence",
"parameter": {
"type": "object",
"properties": {
"scientificname": {
"type": "string",
"description": "Scientific name filter (optional)",
},
"areaid": {
"type": "string",
"description": "Area identifier filter (optional)",
},
"size": {
"type": "integer",
"default": 10,
"minimum": 1,
"maximum": 100,
},
},
},
"settings": {"base_url": "https://api.obis.org/v3", "timeout": 30},
},
)
class OBISOccurrenceTool:
[docs]
def run(self, arguments: Dict[str, Any]):
base = self.tool_config.get("settings", {}).get(
"base_url", "https://api.obis.org/v3"
)
timeout = int(self.tool_config.get("settings", {}).get("timeout", 30))
query: Dict[str, Any] = {}
for key in ("scientificname", "areaid", "size"):
if key in arguments and arguments[key] is not None:
query[key] = arguments[key]
if "size" not in query:
query["size"] = 10
url = f"{base}/occurrence?{urlencode(query)}"
try:
data = _http_get(
url, headers={"Accept": "application/json"}, timeout=timeout
)
return {
"source": "OBIS",
"endpoint": "occurrence",
"query": query,
"data": data,
"success": True,
}
except Exception as e:
return {
"error": str(e),
"source": "OBIS",
"endpoint": "occurrence",
"success": False,
}