Source code for tooluniverse.gbif_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( "GBIFTool", config={ "name": "GBIF_search_species", "type": "GBIFTool", "description": "Search species via GBIF species/search", "parameter": { "type": "object", "properties": { "query": { "type": "string", "description": "Query keyword, e.g., Homo", }, "limit": { "type": "integer", "default": 10, "minimum": 1, "maximum": 300, }, "offset": { "type": "integer", "default": 0, "minimum": 0, }, }, "required": ["query"], }, "settings": { "base_url": "https://api.gbif.org/v1", "timeout": 30, }, }, ) class GBIFTool:
[docs] def __init__(self, tool_config=None): self.tool_config = tool_config or {}
[docs] def run(self, arguments: Dict[str, Any]): base = self.tool_config.get("settings", {}).get( "base_url", "https://api.gbif.org/v1" ) timeout = int(self.tool_config.get("settings", {}).get("timeout", 30)) query_text = arguments.get("query") limit = int(arguments.get("limit", 10)) offset = int(arguments.get("offset", 0)) query = {"q": query_text, "limit": limit, "offset": offset} url = f"{base}/species/search?{urlencode(query)}" try: data = _http_get( url, headers={"Accept": "application/json"}, timeout=timeout ) return { "source": "GBIF", "endpoint": "species/search", "query": query, "data": data, "success": True, } except Exception as e: return { "error": str(e), "source": "GBIF", "endpoint": "species/search", "success": False, }
[docs] @register_tool( "GBIFOccurrenceTool", config={ "name": "GBIF_search_occurrences", "type": "GBIFOccurrenceTool", "description": "Search occurrences via GBIF occurrence/search", "parameter": { "type": "object", "properties": { "taxonKey": { "type": "integer", "description": "GBIF taxonKey filter", }, "country": { "type": "string", "description": "Country code, e.g., US", }, "hasCoordinate": {"type": "boolean", "default": True}, "limit": { "type": "integer", "default": 10, "minimum": 1, "maximum": 300, }, "offset": { "type": "integer", "default": 0, "minimum": 0, }, }, }, "settings": { "base_url": "https://api.gbif.org/v1", "timeout": 30, }, }, ) class GBIFOccurrenceTool:
[docs] def __init__(self, tool_config=None): self.tool_config = tool_config or {}
[docs] def run(self, arguments: Dict[str, Any]): base = self.tool_config.get("settings", {}).get( "base_url", "https://api.gbif.org/v1" ) timeout = int(self.tool_config.get("settings", {}).get("timeout", 30)) query = {} for key in ("taxonKey", "country", "hasCoordinate", "limit", "offset"): if key in arguments and arguments[key] is not None: query[key] = arguments[key] if "limit" not in query: query["limit"] = 10 if "offset" not in query: query["offset"] = 0 url = f"{base}/occurrence/search?{urlencode(query)}" try: data = _http_get( url, headers={"Accept": "application/json"}, timeout=timeout ) return { "source": "GBIF", "endpoint": "occurrence/search", "query": query, "data": data, "success": True, } except Exception as e: return { "error": str(e), "source": "GBIF", "endpoint": "occurrence/search", "success": False, }