Skip to content

Commit 1450cff

Browse files
committed
feat: address comments
1 parent 7f5b287 commit 1450cff

File tree

2 files changed

+328
-131
lines changed

2 files changed

+328
-131
lines changed

openfga_sdk/api/open_fga_api.py

Lines changed: 165 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,12 @@ async def _execute(
8686
headers: dict | None = None,
8787
options: dict | None = None,
8888
) -> Any:
89-
"""Shared executor for all API endpoint methods."""
89+
"""Shared executor for all API endpoint methods.
90+
91+
Delegates to _execute_api_request_internal (or
92+
_execute_streamed_api_request_internal when _streaming=True) so all
93+
API calls share one unified code path.
94+
"""
9095
if options is None:
9196
options = {}
9297

@@ -112,31 +117,30 @@ async def _execute(
112117
body=body, attributes=telemetry_attributes
113118
)
114119

115-
merged_response_types_map = {
116-
**self._COMMON_ERROR_RESPONSE_TYPES,
117-
**response_types_map,
118-
}
120+
if options.get("_streaming", False):
121+
return self._execute_streamed_api_request_internal(
122+
operation_name=operation_name,
123+
method=method,
124+
path=path,
125+
body=body,
126+
query_params=query_params or [],
127+
headers=header_params,
128+
options=options,
129+
response_types_map=response_types_map,
130+
telemetry_attributes=telemetry_attributes,
131+
)
119132

120-
return await self.api_client.call_api(
121-
path,
122-
method,
123-
{},
124-
query_params or [],
125-
header_params,
133+
return await self._execute_api_request_internal(
134+
operation_name=operation_name,
135+
method=method,
136+
path=path,
126137
body=body,
127-
post_params=[],
128-
files={},
129-
response_types_map=merged_response_types_map,
130-
auth_settings=[],
131-
async_req=options.get("async_req"),
132-
_return_http_data_only=True,
133-
_preload_content=True,
134-
_request_timeout=options.get("_request_timeout"),
135-
_retry_params=options.get("_retry_params"),
136-
collection_formats={},
137-
_oauth2_client=self._oauth2_client,
138-
_telemetry_attributes=telemetry_attributes,
139-
_streaming=options.get("_streaming", False),
138+
query_params=query_params or [],
139+
headers=header_params,
140+
options=options,
141+
response_types_map=response_types_map,
142+
telemetry_attributes=telemetry_attributes,
143+
_skip_builder=True,
140144
)
141145

142146
async def execute_api_request(
@@ -209,42 +213,90 @@ async def execute_streamed_api_request(
209213
:param headers: Custom headers (SDK enforces Content-Type and Accept)
210214
:param options: Extra options e.g. {"retry_params": RetryParams(max_retry=3)}
211215
"""
212-
from openfga_sdk.client.execute_api_request_builder import (
213-
ExecuteApiRequestBuilder,
214-
)
215-
216-
builder = ExecuteApiRequestBuilder(
216+
async for chunk in self._execute_streamed_api_request_internal(
217217
operation_name=operation_name,
218218
method=method,
219219
path=path,
220220
path_params=path_params,
221221
body=body,
222222
query_params=query_params,
223223
headers=headers,
224-
)
225-
builder.validate()
224+
options=options,
225+
):
226+
yield chunk
226227

227-
resource_path = builder.build_path()
228-
query_params_list = builder.build_query_params_list()
229-
final_headers = builder.build_headers()
228+
async def _execute_streamed_api_request_internal(
229+
self,
230+
*,
231+
operation_name: str,
232+
method: str,
233+
path: str,
234+
path_params: dict[str, str] | None = None,
235+
body: dict[str, Any] | list[Any] | str | bytes | None = None,
236+
query_params=None,
237+
headers=None,
238+
options: dict[str, Any] | None = None,
239+
response_types_map: dict | None = None,
240+
telemetry_attributes: dict | None = None,
241+
_skip_builder: bool = False,
242+
) -> AsyncIterator[dict[str, Any]]:
243+
"""Implementation for streaming API requests.
230244
231-
retry_params = options.get("retry_params") if options else None
245+
When _skip_builder=True, query_params must already be a list of tuples
246+
and headers must already be a fully-built dict (used when called from _execute).
247+
When response_types_map is provided, it is merged with _COMMON_ERROR_RESPONSE_TYPES.
248+
When telemetry_attributes is provided, it is used as-is instead of building minimal defaults.
249+
"""
250+
if _skip_builder:
251+
resource_path = path
252+
query_params_list = query_params if query_params is not None else []
253+
final_headers = headers or {}
254+
else:
255+
from openfga_sdk.client.execute_api_request_builder import (
256+
ExecuteApiRequestBuilder,
257+
)
232258

233-
telemetry_attributes: dict[TelemetryAttribute, str | bool | int | float] = {
234-
TelemetryAttributes.fga_client_request_method: operation_name.lower(),
235-
}
236-
if self.api_client.get_store_id():
237-
telemetry_attributes[TelemetryAttributes.fga_client_request_store_id] = (
238-
self.api_client.get_store_id()
259+
builder = ExecuteApiRequestBuilder(
260+
operation_name=operation_name,
261+
method=method,
262+
path=path,
263+
path_params=path_params,
264+
body=body,
265+
query_params=query_params,
266+
headers=headers,
239267
)
268+
builder.validate()
269+
270+
resource_path = builder.build_path()
271+
query_params_list = builder.build_query_params_list()
272+
final_headers = builder.build_headers()
273+
274+
retry_params = options.get("retry_params") if options else None
275+
276+
if telemetry_attributes is None:
277+
telemetry_attributes = {
278+
TelemetryAttributes.fga_client_request_method: operation_name.lower(),
279+
}
280+
if self.api_client.get_store_id():
281+
telemetry_attributes[
282+
TelemetryAttributes.fga_client_request_store_id
283+
] = self.api_client.get_store_id()
284+
285+
if response_types_map is not None:
286+
merged_response_types_map = {
287+
**self._COMMON_ERROR_RESPONSE_TYPES,
288+
**response_types_map,
289+
}
290+
else:
291+
merged_response_types_map = {}
240292

241293
stream = await self.api_client.call_api(
242294
resource_path=resource_path,
243295
method=method.upper(),
244296
query_params=query_params_list if query_params_list else None,
245297
header_params=final_headers,
246298
body=body,
247-
response_types_map={},
299+
response_types_map=merged_response_types_map,
248300
auth_settings=[],
249301
_return_http_data_only=True,
250302
_preload_content=True,
@@ -265,42 +317,89 @@ async def _execute_api_request_internal(
265317
path: str,
266318
path_params: dict[str, str] | None = None,
267319
body: dict[str, Any] | list[Any] | str | bytes | None = None,
268-
query_params: dict[str, str | int | list[str | int]] | None = None,
269-
headers: dict[str, str] | None = None,
320+
query_params=None,
321+
headers=None,
270322
options: dict[str, Any] | None = None,
271-
) -> RawResponse:
272-
"""Implementation for execute_api_request."""
323+
response_types_map: dict | None = None,
324+
telemetry_attributes: dict | None = None,
325+
_skip_builder: bool = False,
326+
) -> Any:
327+
"""Implementation for execute_api_request (and _execute delegation).
328+
329+
When _skip_builder=True, query_params must already be a list of tuples
330+
and headers must already be a fully-built dict (used when called from _execute).
331+
When response_types_map is provided, it is merged with _COMMON_ERROR_RESPONSE_TYPES
332+
and the deserialized typed result from call_api is returned directly.
333+
When telemetry_attributes is provided, it is used as-is instead of building minimal defaults.
334+
"""
273335
from openfga_sdk.client.execute_api_request_builder import (
274336
ExecuteApiRequestBuilder,
275337
ResponseParser,
276338
)
277339
from openfga_sdk.client.models.raw_response import RawResponse
278340

279-
builder = ExecuteApiRequestBuilder(
280-
operation_name=operation_name,
281-
method=method,
282-
path=path,
283-
path_params=path_params,
284-
body=body,
285-
query_params=query_params,
286-
headers=headers,
287-
)
288-
builder.validate()
341+
if _skip_builder:
342+
resource_path = path
343+
query_params_list = query_params if query_params is not None else []
344+
final_headers = headers or {}
345+
else:
346+
builder = ExecuteApiRequestBuilder(
347+
operation_name=operation_name,
348+
method=method,
349+
path=path,
350+
path_params=path_params,
351+
body=body,
352+
query_params=query_params,
353+
headers=headers,
354+
)
355+
builder.validate()
289356

290-
resource_path = builder.build_path()
291-
query_params_list = builder.build_query_params_list()
292-
final_headers = builder.build_headers()
357+
resource_path = builder.build_path()
358+
query_params_list = builder.build_query_params_list()
359+
final_headers = builder.build_headers()
293360

294361
retry_params = options.get("retry_params") if options else None
295-
296-
telemetry_attributes: dict[TelemetryAttribute, str | bool | int | float] = {
297-
TelemetryAttributes.fga_client_request_method: operation_name.lower(),
298-
}
299-
if self.api_client.get_store_id():
300-
telemetry_attributes[TelemetryAttributes.fga_client_request_store_id] = (
301-
self.api_client.get_store_id()
362+
request_timeout = options.get("_request_timeout") if options else None
363+
async_req = options.get("async_req") if options else None
364+
365+
if telemetry_attributes is None:
366+
telemetry_attributes = {
367+
TelemetryAttributes.fga_client_request_method: operation_name.lower(),
368+
}
369+
if self.api_client.get_store_id():
370+
telemetry_attributes[
371+
TelemetryAttributes.fga_client_request_store_id
372+
] = self.api_client.get_store_id()
373+
374+
if response_types_map is not None:
375+
merged_response_types_map = {
376+
**self._COMMON_ERROR_RESPONSE_TYPES,
377+
**response_types_map,
378+
}
379+
# call_api returns a deserialized typed model when response_types_map is non-empty
380+
return await self.api_client.call_api(
381+
resource_path=resource_path,
382+
method=method.upper(),
383+
path_params={},
384+
query_params=query_params_list if query_params_list else [],
385+
header_params=final_headers,
386+
body=body,
387+
post_params=[],
388+
files={},
389+
response_types_map=merged_response_types_map,
390+
auth_settings=[],
391+
async_req=async_req,
392+
_return_http_data_only=True,
393+
_preload_content=True,
394+
_request_timeout=request_timeout,
395+
_retry_params=retry_params,
396+
collection_formats={},
397+
_oauth2_client=self._oauth2_client,
398+
_telemetry_attributes=telemetry_attributes,
399+
_streaming=False,
302400
)
303401

402+
# No response_types_map: public execute_api_request path → return RawResponse
304403
await self.api_client.call_api(
305404
resource_path=resource_path,
306405
method=method.upper(),

0 commit comments

Comments
 (0)