Skip to content

Commit 54a13ab

Browse files
committed
python(feat): Add reports and tags types and clients + clean up rules as a result.
1 parent 7b54866 commit 54a13ab

17 files changed

Lines changed: 1385 additions & 32 deletions

File tree

python/lib/sift_client/_internal/low_level_wrappers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from sift_client._internal.low_level_wrappers.channels import ChannelsLowLevelClient
66
from sift_client._internal.low_level_wrappers.ingestion import IngestionLowLevelClient
77
from sift_client._internal.low_level_wrappers.ping import PingLowLevelClient
8+
from sift_client._internal.low_level_wrappers.reports import ReportsLowLevelClient
89
from sift_client._internal.low_level_wrappers.rules import RulesLowLevelClient
910
from sift_client._internal.low_level_wrappers.runs import RunsLowLevelClient
1011

@@ -14,6 +15,7 @@
1415
"ChannelsLowLevelClient",
1516
"IngestionLowLevelClient",
1617
"PingLowLevelClient",
18+
"ReportsLowLevelClient",
1719
"RulesLowLevelClient",
1820
"RunsLowLevelClient",
1921
]
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
from typing import TYPE_CHECKING, Any, cast
5+
6+
from sift.reports.v1.reports_pb2 import (
7+
CancelReportRequest,
8+
CreateReportFromReportTemplateRequest,
9+
CreateReportFromRulesRequest,
10+
CreateReportRequest,
11+
CreateReportRequestClientKeys,
12+
CreateReportRequestRuleIds,
13+
CreateReportResponse,
14+
GetReportRequest,
15+
GetReportResponse,
16+
ListReportsRequest,
17+
ListReportsResponse,
18+
RerunReportRequest,
19+
RerunReportResponse,
20+
)
21+
from sift.reports.v1.reports_pb2_grpc import ReportServiceStub
22+
23+
from sift_client._internal.low_level_wrappers.base import LowLevelClientBase
24+
from sift_client.sift_types.report import Report
25+
from sift_client.transport import WithGrpcClient
26+
27+
if TYPE_CHECKING:
28+
from sift_client.transport.grpc_transport import GrpcClient
29+
30+
# Configure logging
31+
logger = logging.getLogger(__name__)
32+
33+
34+
class ReportsLowLevelClient(LowLevelClientBase, WithGrpcClient):
35+
"""Low-level client for the ReportsAPI.
36+
37+
This class provides a thin wrapper around the autogenerated bindings for the ReportsAPI.
38+
"""
39+
40+
def __init__(self, grpc_client: GrpcClient):
41+
"""Initialize the ReportsLowLevelClient.
42+
43+
Args:
44+
grpc_client: The gRPC client to use for making API calls.
45+
"""
46+
super().__init__(grpc_client)
47+
48+
async def get_report(self, report_id: str) -> Report:
49+
"""Get a report by report_id.
50+
51+
Args:
52+
report_id: The report ID to get.
53+
54+
Returns:
55+
The Report.
56+
57+
Raises:
58+
ValueError: If report_id is not provided.
59+
"""
60+
if not report_id:
61+
raise ValueError("report_id must be provided")
62+
63+
request = GetReportRequest(report_id=report_id)
64+
response = await self._grpc_client.get_stub(ReportServiceStub).GetReport(request)
65+
grpc_report = cast("GetReportResponse", response).report
66+
return Report._from_proto(grpc_report)
67+
68+
async def list_reports(
69+
self,
70+
*,
71+
page_size: int | None = None,
72+
page_token: str | None = None,
73+
query_filter: str | None = None,
74+
organization_id: str | None = None,
75+
order_by: str | None = None,
76+
) -> tuple[list[Report], str]:
77+
"""List reports with optional filtering and pagination.
78+
79+
Args:
80+
page_size: The maximum number of reports to return.
81+
page_token: A page token for pagination.
82+
query_filter: A CEL filter string.
83+
organization_id: The organization ID to filter by.
84+
order_by: How to order the retrieved reports.
85+
86+
Returns:
87+
A tuple of (reports, next_page_token).
88+
"""
89+
request_kwargs: dict[str, Any] = {}
90+
if page_size is not None:
91+
request_kwargs["page_size"] = page_size
92+
if page_token is not None:
93+
request_kwargs["page_token"] = page_token
94+
if query_filter is not None:
95+
request_kwargs["filter"] = query_filter
96+
if organization_id is not None:
97+
request_kwargs["organization_id"] = organization_id
98+
if order_by is not None:
99+
request_kwargs["order_by"] = order_by
100+
101+
request = ListReportsRequest(**request_kwargs)
102+
response = await self._grpc_client.get_stub(ReportServiceStub).ListReports(request)
103+
response = cast("ListReportsResponse", response)
104+
105+
reports = [Report._from_proto(report) for report in response.reports]
106+
return reports, response.next_page_token
107+
108+
async def list_all_reports(
109+
self,
110+
*,
111+
query_filter: str | None = None,
112+
organization_id: str | None = None,
113+
order_by: str | None = None,
114+
max_results: int | None = None,
115+
) -> list[Report]:
116+
"""List all reports with optional filtering.
117+
118+
Args:
119+
query_filter: A CEL filter string.
120+
organization_id: The organization ID to filter by.
121+
order_by: How to order the retrieved reports.
122+
max_results: Maximum number of results to return.
123+
124+
Returns:
125+
A list of all matching reports.
126+
"""
127+
return await self._handle_pagination(
128+
self.list_reports,
129+
kwargs={
130+
"query_filter": query_filter,
131+
"organization_id": organization_id,
132+
},
133+
order_by=order_by,
134+
max_results=max_results,
135+
)
136+
137+
async def create_report_from_template(
138+
self,
139+
*,
140+
report_template_id: str,
141+
run_id: str,
142+
organization_id: str,
143+
name: str | None = None,
144+
) -> Report:
145+
"""Create a new report from a report template.
146+
147+
Args:
148+
report_template_id: The ID of the report template to use.
149+
run_id: The run ID to associate with the report.
150+
organization_id: The organization ID.
151+
name: Optional name for the report.
152+
153+
Returns:
154+
The created Report.
155+
"""
156+
template_request = CreateReportFromReportTemplateRequest(
157+
report_template_id=report_template_id
158+
)
159+
160+
request_kwargs: dict[str, Any] = {
161+
"report_from_report_template_request": template_request,
162+
"organization_id": organization_id,
163+
"run_id": run_id,
164+
}
165+
166+
if name is not None:
167+
request_kwargs["name"] = name
168+
169+
request = CreateReportRequest(**request_kwargs)
170+
response = await self._grpc_client.get_stub(ReportServiceStub).CreateReport(request)
171+
grpc_report = cast("CreateReportResponse", response).report
172+
return Report._from_proto(grpc_report)
173+
174+
async def create_report_from_rules(
175+
self,
176+
*,
177+
name: str,
178+
description: str | None = None,
179+
tag_names: list[str] | None = None,
180+
rule_ids: list[str] | None = None,
181+
rule_client_keys: list[str] | None = None,
182+
run_id: str,
183+
organization_id: str,
184+
) -> Report:
185+
"""Create a new report from rules.
186+
187+
Args:
188+
name: The name of the report.
189+
description: Optional description of the report.
190+
tag_names: List of tag names to associate with the report.
191+
rule_ids: List of rule IDs to include in the report.
192+
rule_client_keys: List of rule client keys to include in the report.
193+
run_id: The run ID to associate with the report.
194+
organization_id: The organization ID.
195+
196+
Returns:
197+
The created Report.
198+
199+
Raises:
200+
ValueError: If neither rule_ids nor rule_client_keys are provided.
201+
"""
202+
if not rule_ids and not rule_client_keys:
203+
raise ValueError("Either rule_ids or rule_client_keys must be provided")
204+
205+
rules_request_kwargs: dict[str, Any] = {
206+
"name": name,
207+
}
208+
209+
if description is not None:
210+
rules_request_kwargs["description"] = description
211+
212+
if tag_names is not None:
213+
rules_request_kwargs["tag_names"] = tag_names
214+
215+
if rule_ids is not None:
216+
rules_request_kwargs["rule_ids"] = CreateReportRequestRuleIds(rule_ids=rule_ids)
217+
elif rule_client_keys is not None:
218+
rules_request_kwargs["rule_client_keys"] = CreateReportRequestClientKeys(
219+
rule_client_keys=rule_client_keys
220+
)
221+
222+
rules_request = CreateReportFromRulesRequest(**rules_request_kwargs)
223+
224+
request_kwargs: dict[str, Any] = {
225+
"report_from_rules_request": rules_request,
226+
"organization_id": organization_id,
227+
"run_id": run_id,
228+
}
229+
230+
request = CreateReportRequest(**request_kwargs)
231+
response = await self._grpc_client.get_stub(ReportServiceStub).CreateReport(request)
232+
grpc_report = cast("CreateReportResponse", response).report
233+
return Report._from_proto(grpc_report)
234+
235+
async def rerun_report(self, report_id: str) -> tuple[str, str]:
236+
"""Rerun a report.
237+
238+
Args:
239+
report_id: The ID of the report to rerun.
240+
241+
Returns:
242+
A tuple of (job_id, new_report_id).
243+
244+
Raises:
245+
ValueError: If report_id is not provided.
246+
"""
247+
if not report_id:
248+
raise ValueError("report_id must be provided")
249+
250+
request = RerunReportRequest(report_id=report_id)
251+
response = await self._grpc_client.get_stub(ReportServiceStub).RerunReport(request)
252+
response = cast("RerunReportResponse", response)
253+
return response.job_id, response.report_id
254+
255+
async def cancel_report(self, report_id: str) -> None:
256+
"""Cancel a report.
257+
258+
Args:
259+
report_id: The ID of the report to cancel.
260+
261+
Raises:
262+
ValueError: If report_id is not provided.
263+
"""
264+
if not report_id:
265+
raise ValueError("report_id must be provided")
266+
267+
request = CancelReportRequest(report_id=report_id)
268+
await self._grpc_client.get_stub(ReportServiceStub).CancelReport(request)

0 commit comments

Comments
 (0)