Source code for veupath_chatbot.integrations.veupathdb.strategy_api.reports

"""Core report and answer methods for the Strategy API.

Provides :class:`ReportsMixin` with methods to run reports, fetch step
answers and records, and get step counts.
"""

from typing import cast

from veupath_chatbot.integrations.veupathdb.strategy_api.base import StrategyAPIBase
from veupath_chatbot.platform.types import JSONObject, JSONValue


[docs] class ReportsMixin(StrategyAPIBase): """Mixin providing report, answer, and step count methods."""
[docs] async def run_step_report( self, step_id: int, report_name: str, config: JSONObject | None = None ) -> JSONValue: """Run a report on a step.""" await self._ensure_session() # reportConfig is a nested JSONObject, which is valid JSONValue report_config: JSONValue = config or {} payload: JSONObject = {"reportConfig": report_config} return await self.client.run_step_report( self.user_id, step_id, report_name, payload )
[docs] async def get_step_answer( self, step_id: int, attributes: list[str] | None = None, pagination: dict[str, int] | None = None, ) -> JSONObject: """Get answer records for a step via the standard report endpoint. Convenience wrapper around :meth:`get_step_records`. :param step_id: Step ID. :param attributes: Attributes to include in response. :param pagination: Offset and numRecords. :returns: Answer data with records. """ return await self.get_step_records( step_id, attributes=attributes, pagination=pagination )
[docs] async def get_step_records( self, step_id: int, attributes: list[str] | None = None, tables: list[str] | None = None, pagination: dict[str, int] | None = None, sorting: list[JSONObject] | None = None, ) -> JSONObject: """Get paginated records for a step with configurable attributes and sorting. :param step_id: WDK step ID (must be part of a strategy). :param attributes: Attribute names to include. :param tables: Table names to include. :param pagination: ``{offset, numRecords}`` for server-side paging. :param sorting: List of ``{attributeName, direction}`` dicts. :returns: Standard report response with ``records`` and ``meta``. """ report_config: JSONObject = {} if attributes: report_config["attributes"] = cast(JSONValue, attributes) if tables: report_config["tables"] = cast(JSONValue, tables) if pagination: report_config["pagination"] = cast(JSONValue, pagination) if sorting: report_config["sorting"] = cast(JSONValue, sorting) await self._ensure_session() return await self._standard_report(step_id, report_config)
[docs] async def get_step_count(self, step_id: int) -> int: """Get result count for a step. Uses the standard report endpoint and reads ``meta.totalCount`` (``JsonKeys.TOTAL_COUNT``). """ await self._ensure_session() answer = await self._standard_report( step_id, {"pagination": {"offset": 0, "numRecords": 0}} ) meta_raw = answer.get("meta") if not isinstance(meta_raw, dict): raise ValueError("Step count: response missing 'meta' dict") total_count_raw = meta_raw.get("totalCount") if not isinstance(total_count_raw, int): raise ValueError( f"Step count: 'meta.totalCount' is not an int " f"(got {type(total_count_raw).__name__}: {total_count_raw!r})" ) return total_count_raw