Source code for tooluniverse.biogrid_tool
"""BioGRID Database REST API Tool for protein and genetic interaction data."""
import os
import requests
from typing import Any, Dict, List, Union
from .base_tool import BaseTool
from .tool_registry import register_tool
BIOGRID_BASE_URL = "https://webservice.thebiogrid.org"
def _join_pipe_delimited(value: Union[str, list]) -> str:
"""Convert a string or list to a pipe-delimited string for BioGRID parameters."""
if isinstance(value, list):
return "|".join(str(item) for item in value)
return str(value)
[docs]
@register_tool("BioGRIDRESTTool")
class BioGRIDRESTTool(BaseTool):
"""BioGRID Database REST API tool.
Generic wrapper for BioGRID API endpoints defined in ppi_tools.json.
"""
[docs]
def __init__(self, tool_config):
super().__init__(tool_config)
fields = tool_config.get("fields", {})
parameter = tool_config.get("parameter", {})
self.endpoint_template: str = fields.get("endpoint", "/interactions/")
self.required: List[str] = parameter.get("required", [])
self.output_format: str = fields.get("return_format", "JSON")
[docs]
def _build_url(self) -> str:
"""Build URL for BioGRID API request."""
return BIOGRID_BASE_URL + self.endpoint_template
_ORGANISM_MAP = {
"homo sapiens": 9606,
"mus musculus": 10090,
"saccharomyces cerevisiae": 559292,
}
# Maps argument keys to their BioGRID API parameter names (pipe-delimited).
_LIST_PARAM_MAP = {
"gene_names": "geneList",
"chemical_names": "chemicalList",
"pubmed_ids": "pubmedList",
"ptm_type": "ptmType",
"evidence_types": "evidenceList",
}
[docs]
def _build_params(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Build parameters for BioGRID API request."""
params = {"format": "json", "interSpeciesExcluded": "false"}
api_key = (
arguments.get("api_key")
or arguments.get("accesskey")
or arguments.get("access_key")
or os.getenv("BIOGRID_API_KEY")
or os.getenv("BIOGRID_ACCESS_KEY")
)
if not api_key:
raise ValueError(
"BioGRID API key is required. Please provide 'api_key' parameter "
"or set BIOGRID_ACCESS_KEY environment variable. "
"Register at: https://webservice.thebiogrid.org/"
)
params["accesskey"] = api_key
# Map list-or-string arguments to pipe-delimited BioGRID parameters
for arg_key, api_key_name in self._LIST_PARAM_MAP.items():
if arg_key in arguments and arguments[arg_key]:
params[api_key_name] = _join_pipe_delimited(arguments[arg_key])
if "organism" in arguments:
organism = arguments["organism"]
params["taxId"] = self._ORGANISM_MAP.get(organism.lower(), organism)
# Note: BioGRID API does not support filtering by "physical"/"genetic" via evidenceList.
# The interaction_type parameter is informational only; filtering must be done client-side
# using the EXPERIMENTAL_SYSTEM_TYPE field in the results.
# Handle residue filtering for PTMs
if arguments.get("residue"):
params["residue"] = arguments["residue"]
# Handle throughput filtering
if arguments.get("throughput"):
params["throughputTag"] = arguments["throughput"]
# Handle interaction action for chemical interactions
if arguments.get("interaction_action"):
params["action"] = arguments["interaction_action"]
# Boolean flags
if "include_evidence" in arguments:
params["includeEvidence"] = (
"true" if arguments["include_evidence"] else "false"
)
if "include_enzymes" in arguments:
params["includeInteractors"] = (
"true" if arguments["include_enzymes"] else "false"
)
if "limit" in arguments:
params["max"] = arguments["limit"]
params["searchNames"] = "true"
return params
[docs]
def _make_request(self, url: str, params: Dict[str, Any]) -> Dict[str, Any]:
"""Perform a GET request and handle common errors."""
try:
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
if self.output_format == "JSON":
return response.json()
else:
return {"data": response.text}
except requests.exceptions.RequestException as e:
return {"error": f"Request failed: {str(e)}"}
except Exception as e:
return {"error": f"Unexpected error: {str(e)}"}
[docs]
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Execute the tool with given arguments."""
for param in self.required:
if param not in arguments:
error_msg = f"Missing required parameter: {param}"
return {
"status": "error",
"data": {"error": error_msg},
"error": error_msg,
}
url = self._build_url()
try:
params = self._build_params(arguments)
except ValueError as e:
error_msg = f"Authentication failed: {e}"
return {"status": "error", "data": {"error": error_msg}, "error": error_msg}
api_response = self._make_request(url, params)
if "error" in api_response:
return {
"status": "error",
"data": api_response,
"error": api_response.get("error"),
}
return {"status": "success", "data": api_response}