Skip to content

Commit 0535b1c

Browse files
committed
feat: address comments
1 parent 88b86fb commit 0535b1c

File tree

10 files changed

+320
-1022
lines changed

10 files changed

+320
-1022
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
- feat: add `execute_api_request` and `execute_streamed_api_request` methods to `OpenFgaClient` and `OpenFgaApi` for making arbitrary HTTP requests to any OpenFGA API endpoint with full auth, retry, and telemetry support (#252) - thanks @kcbiradar
66

7+
### Breaking Changes
8+
9+
- The `_return_http_data_only`, `_request_auth`, and `_preload_content` kwargs have been removed from all `OpenFgaApi` and `SyncOpenFgaApi` endpoint methods. These were internal implementation details not intended for external use. `_return_http_data_only` is now hardcoded to `True` internally, meaning all endpoint methods always return the deserialized response object directly. Users relying on `_with_http_info` methods returning a `(data, status, headers)` tuple should use `execute_api_request` instead.
10+
711
### [0.9.9](https://github.com/openfga/python-sdk/compare/v0.9.8...v0.9.9) (2025-12-09)
812
- feat: improve error messaging (#245)
913

README.md

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,10 +1317,9 @@ print("Stores:", stores)
13171317

13181318
#### Example: Using Path Parameters
13191319

1320-
Path parameters are specified in the path using `{param_name}` syntax and are replaced with URL-encoded values from the `path_params` dictionary. If `{store_id}` is present in the path and not provided in `path_params`, it will be automatically replaced with the configured store_id:
1320+
Path parameters are specified in the path using `{param_name}` syntax and must all be provided explicitly via `path_params` (URL-encoded automatically):
13211321

13221322
```python
1323-
# Using explicit path parameters
13241323
response = await fga_client.execute_api_request(
13251324
operation_name="GetAuthorizationModel",
13261325
method="GET",
@@ -1330,16 +1329,6 @@ response = await fga_client.execute_api_request(
13301329
"model_id": "your-model-id",
13311330
},
13321331
)
1333-
1334-
# Using automatic store_id substitution
1335-
response = await fga_client.execute_api_request(
1336-
operation_name="GetAuthorizationModel",
1337-
method="GET",
1338-
path="/stores/{store_id}/authorization-models/{model_id}",
1339-
path_params={
1340-
"model_id": "your-model-id",
1341-
},
1342-
)
13431332
```
13441333

13451334
### Retries

example/execute-api-request/execute_api_request_example.py

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ async def main():
4747
)
4848

4949
async with OpenFgaClient(configuration) as fga_client:
50-
# ─── Setup: create a store, model, and tuple ─────────────
5150
print("=== Setup ===")
5251

5352
# Create a test store via the SDK
@@ -116,10 +115,8 @@ async def main():
116115
)
117116
print("Wrote tuple: user:anne → writer → document:roadmap")
118117

119-
# ─── Tests ────────────────────────────────────────────────
120-
print("\n=== execute_api_request tests ===\n")
118+
print("\n=== execute_api_request ===\n")
121119

122-
# ── 1. GET /stores ────────────────────────────────────────
123120
print("1. ListStores (GET /stores)")
124121
raw = await fga_client.execute_api_request(
125122
operation_name="ListStores",
@@ -136,12 +133,12 @@ async def main():
136133
)
137134
print(f" ✅ {len(body['stores'])} stores (status {raw.status})")
138135

139-
# ── 2. GET /stores/{store_id} (auto-substitution) ────────
140136
print("2. GetStore (GET /stores/{store_id})")
141137
raw = await fga_client.execute_api_request(
142138
operation_name="GetStore",
143139
method="GET",
144140
path="/stores/{store_id}",
141+
path_params={"store_id": store.id},
145142
)
146143
sdk = await fga_client.get_store()
147144
body = raw.json()
@@ -150,27 +147,27 @@ async def main():
150147
assert body["name"] == sdk.name
151148
print(f" ✅ id={body['id']}, name={body['name']}")
152149

153-
# ── 3. GET /stores/{store_id}/authorization-models ────────
154150
print(
155151
"3. ReadAuthorizationModels (GET /stores/{store_id}/authorization-models)"
156152
)
157153
raw = await fga_client.execute_api_request(
158154
operation_name="ReadAuthorizationModels",
159155
method="GET",
160156
path="/stores/{store_id}/authorization-models",
157+
path_params={"store_id": store.id},
161158
)
162159
sdk = await fga_client.read_authorization_models()
163160
body = raw.json()
164161
assert raw.status == 200
165162
assert len(body["authorization_models"]) == len(sdk.authorization_models)
166163
print(f" ✅ {len(body['authorization_models'])} models")
167164

168-
# ── 4. POST /stores/{store_id}/check ──────────────────────
169165
print("4. Check (POST /stores/{store_id}/check)")
170166
raw = await fga_client.execute_api_request(
171167
operation_name="Check",
172168
method="POST",
173169
path="/stores/{store_id}/check",
170+
path_params={"store_id": store.id},
174171
body={
175172
"tuple_key": {
176173
"user": "user:anne",
@@ -192,12 +189,12 @@ async def main():
192189
assert body["allowed"] == sdk.allowed
193190
print(f" ✅ allowed={body['allowed']}")
194191

195-
# ── 5. POST /stores/{store_id}/read ───────────────────────
196192
print("5. Read (POST /stores/{store_id}/read)")
197193
raw = await fga_client.execute_api_request(
198194
operation_name="Read",
199195
method="POST",
200196
path="/stores/{store_id}/read",
197+
path_params={"store_id": store.id},
201198
body={
202199
"tuple_key": {
203200
"user": "user:anne",
@@ -211,7 +208,6 @@ async def main():
211208
assert len(body["tuples"]) >= 1
212209
print(f" ✅ {len(body['tuples'])} tuples returned")
213210

214-
# ── 6. POST /stores — create store via raw request ────────
215211
print("6. CreateStore (POST /stores)")
216212
raw = await fga_client.execute_api_request(
217213
operation_name="CreateStore",
@@ -225,7 +221,6 @@ async def main():
225221
new_store_id = body["id"]
226222
print(f" ✅ created store: {new_store_id}")
227223

228-
# ── 7. DELETE /stores/{store_id} — clean up ───────────────
229224
print("7. DeleteStore (DELETE /stores/{store_id})")
230225
raw = await fga_client.execute_api_request(
231226
operation_name="DeleteStore",
@@ -236,36 +231,22 @@ async def main():
236231
assert raw.status == 204, f"Expected 204, got {raw.status}"
237232
print(f" ✅ deleted store: {new_store_id} (status 204 No Content)")
238233

239-
# ── 8. Custom headers ─────────────────────────────────────
240234
print("8. Custom headers (GET /stores/{store_id})")
241235
raw = await fga_client.execute_api_request(
242236
operation_name="GetStoreWithHeaders",
243237
method="GET",
244238
path="/stores/{store_id}",
239+
path_params={"store_id": store.id},
245240
headers={"X-Custom-Header": "test-value"},
246241
)
247242
assert raw.status == 200
248243
print(f" ✅ custom headers accepted (status {raw.status})")
249244

250-
# ── 9. Explicit path_params override for store_id ─────────
251-
print("9. Explicit store_id in path_params")
252-
raw = await fga_client.execute_api_request(
253-
operation_name="GetStore",
254-
method="GET",
255-
path="/stores/{store_id}",
256-
path_params={"store_id": store.id},
257-
)
258-
body = raw.json()
259-
assert raw.status == 200
260-
assert body["id"] == store.id
261-
print(f" ✅ explicit store_id matched: {body['id']}")
262-
263-
# ─── Cleanup ─────────────────────────────────────────────
264245
print("\n=== Cleanup ===")
265246
await fga_client.delete_store()
266247
print(f"Deleted test store: {store.id}")
267248

268-
print("\n All execute_api_request integration tests passed!\n")
249+
print("\nAll execute_api_request examples completed successfully.\n")
269250

270251

271252
asyncio.run(main())

0 commit comments

Comments
 (0)