Coverage for mindsdb / integrations / handlers / lightdash_handler / api.py: 0%

95 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-21 00:36 +0000

1import requests 

2from urllib.parse import urljoin 

3 

4 

5class Lightdash: 

6 

7 def __init__(self, url: str, api_key: str) -> None: 

8 self.base_url = urljoin(url, "/api/v1/") 

9 self.api_key = api_key 

10 

11 def _request(self, method: str, relative_endpoint: str, data=None): 

12 kwargs = { 

13 "method": method, 

14 "url": urljoin(self.base_url, relative_endpoint), 

15 "headers": { 

16 "Authorization": "ApiKey " + self.api_key, 

17 } 

18 } 

19 if data is not None: 

20 kwargs["data"] = data 

21 return requests.request(**kwargs) 

22 

23 def is_connected(self) -> bool: 

24 if self.get_user() is not None: 

25 return True 

26 return False 

27 

28 def get_user(self): 

29 """ 

30 Get user's details 

31 Return format: 

32 {'userUuid': '831b6c26-bdc2-4a56-9818-fd8ebaa406ac', 

33 'email': 'test@test.com', 

34 'firstName': 'Test', 

35 'lastName': 'User', 

36 'organizationUuid': 'd00805a0-b0b4-400d-a136-66f620493f11', 

37 'organizationName': 'testing-comp', 

38 'organizationCreatedAt': '2023-10-20T17:46:10.005Z', 

39 'isTrackingAnonymized': False, 

40 'isMarketingOptedIn': True, 

41 'isSetupComplete': True, 

42 'role': 'admin', 

43 'isActive': True, 

44 'abilityRules': [{'action': 'view', 

45 'subject': 'OrganizationMemberProfile', 

46 'conditions': {'organizationUuid': 'd00805a0-b0b4-400d-a136-66f620493f11'}}, 

47 {'action': ... 

48 """ 

49 resp = self._request("get", "user") 

50 if resp.ok: 

51 return resp.json()["results"] 

52 return {} 

53 

54 def get_org(self): 

55 """ 

56 Get user's organization details 

57 Return format: 

58 {'organizationUuid': 'd00805a0-b0b4-400d-a136-66f620493f11', 

59 'name': 'testing-comp', 

60 'defaultProjectUuid': 'string', 

61 'chartColors': ['string'], 

62 'needsProject': False} 

63 """ 

64 resp = self._request("get", "org") 

65 if resp.ok: 

66 return resp.json()["results"] 

67 return {} 

68 

69 def get_projects(self): 

70 """ 

71 Get user organization's pojects' details 

72 Return format: 

73 [{'name': 'Jaffle shop', 

74 'projectUuid': '95dfda3b-02e2-4708-a014-5967966020f3', 

75 'type': 'DEFAULT'}] 

76 """ 

77 resp = self._request("get", "org/projects") 

78 if resp.ok: 

79 return resp.json()["results"] 

80 return [] 

81 

82 def get_org_members(self): 

83 """ 

84 Get all the members in user's organization 

85 Return format: 

86 [{'userUuid': '831b6c26-bdc2-4a56-9818-fd8ebaa406ac', 

87 'firstName': 'TestName', 

88 'lastName': 'TestLastName', 

89 'email': 'test@test.com', 

90 'organizationUuid': 'd00805a0-b0b4-400d-a136-66f620493f11', 

91 'role': 'admin', 

92 'isActive': True, 

93 'isInviteExpired': False}] 

94 """ 

95 resp = self._request("get", "org/users") 

96 if resp.ok: 

97 return resp.json()["results"] 

98 return [] 

99 

100 def get_project(self, project_uuid: str): 

101 """ 

102 Get details of a project in user's organization 

103 Return format: 

104 { "dbtVersion": "v1.4", 

105 "copiedFromProjectUuid": "string", 

106 "pinnedListUuid": "string", 

107 "warehouseConnection": { 

108 "role": "string", 

109 "type": "snowflake", 

110 "account": "string", 

111 "database": "string", 

112 "warehouse": "string", 

113 "schema": "string", 

114 "threads": 0, 

115 "clientSessionKeepAlive": true, 

116 "queryTag": "string", 

117 "accessUrl": "string", 

118 "startOfWeek": 0 }, 

119 "dbtConnection": { 

120 "type": "dbt", 

121 "target": "string", 

122 "environment": [ { 

123 "value": "string", 

124 "key": "string" } ], 

125 "profiles_dir": "string", 

126 "project_dir": "string" }, 

127 "type": "DEFAULT", 

128 "name": "string", 

129 "projectUuid": "string", 

130 "organizationUuid": "string" } 

131 """ 

132 resp = self._request("get", f"projects/{project_uuid}") 

133 if resp.ok: 

134 return resp.json()["results"] 

135 return {} 

136 

137 def get_charts_in_project(self, project_uuid: str): 

138 """ 

139 List all charts in a project 

140 Return format: 

141 [{"name": "string", 

142 "organizationUuid": "string", 

143 "uuid": "string", 

144 "description": "string", 

145 "projectUuid": "string", 

146 "spaceUuid": "string", 

147 "pinnedListUuid": "string", 

148 "spaceName": "string", 

149 "dashboardUuid": "string", 

150 "dashboardName": "string", 

151 "chartType": "string"}] 

152 """ 

153 resp = self._request("get", f"projects/{project_uuid}/charts") 

154 if resp.ok: 

155 return resp.json()["results"] 

156 return [] 

157 

158 def get_spaces_in_project(self, project_uuid: str): 

159 """ 

160 List all spaces in a project 

161 Return format: 

162 [{"name": "string", 

163 "organizationUuid": "string", 

164 "uuid": "string", 

165 "projectUuid": "string", 

166 "pinnedListUuid": "string", 

167 "pinnedListOrder": 0, 

168 "isPrivate": true, 

169 "dashboardCount": 0, 

170 "chartCount": 0, 

171 "access": [ 

172 "string" ]}] 

173 """ 

174 resp = self._request("get", f"projects/{project_uuid}/spaces") 

175 if resp.ok: 

176 return resp.json()["results"] 

177 return [] 

178 

179 def get_project_access_list(self, project_uuid: str): 

180 """ 

181 Get access list for a project. This is a list of users that have been explictly granted access to the project. There may be other users that have access to the project via their organization membership 

182 Return format: 

183 [{"lastName": "string", 

184 "firstName": "string", 

185 "email": "string", 

186 "role": "viewer", 

187 "projectUuid": "string", 

188 "userUuid": "string" }] 

189 """ 

190 resp = self._request("get", f"projects/{project_uuid}/access") 

191 if resp.ok: 

192 return resp.json()["results"] 

193 return [] 

194 

195 def get_validation_results(self, project_uuid: str): 

196 """ 

197 Get validation results for a project. This will return the results of the latest validation job 

198 Return format: 

199 [{"source": "chart", 

200 "spaceUuid": "string", 

201 "projectUuid": "string", 

202 "errorType": "chart", 

203 "error": "string", 

204 "name": "string", 

205 "createdAt": "2019-08-24T14:15:22Z", 

206 "validationId": 0, 

207 "chartName": "string", 

208 "chartViews": 0, 

209 "lastUpdatedAt": "2019-08-24T14:15:22Z", 

210 "lastUpdatedBy": "string", 

211 "fieldName": "string", 

212 "chartType": "line", 

213 "chartUuid": "string"}] 

214 """ 

215 resp = self._request("get", f"projects/{project_uuid}/validate") 

216 if resp.ok: 

217 return resp.json()["results"] 

218 return [] 

219 

220 def get_space(self, project_uuid: str, space_uuid: str): 

221 """ 

222 Get details for a space in a project 

223 Return format: 

224 { "pinnedListOrder": 0, 

225 "pinnedListUuid": "string", 

226 "access": [ { 

227 "role": "viewer", 

228 "lastName": "string", 

229 "firstName": "string", 

230 "userUuid": "string" } ], 

231 "dashboards": [ { 

232 "name": "string", 

233 "organizationUuid": "string", 

234 "uuid": "string", 

235 "description": "string", 

236 "updatedAt": "2019-08-24T14:15:22Z", 

237 "projectUuid": "string", 

238 "updatedByUser": { 

239 "userUuid": "string", 

240 "firstName": "string", 

241 "lastName": "string" }, 

242 "spaceUuid": "string", 

243 "views": 0, 

244 "firstViewedAt": "2019-08-24T14:15:22Z", 

245 "pinnedListUuid": "string", 

246 "pinnedListOrder": 0, 

247 "validationErrors": [ { 

248 "validationId": 0, 

249 "createdAt": "2019-08-24T14:15:22Z", 

250 "error": "string" } ] } ], 

251 "projectUuid": "string", 

252 "queries": [ { 

253 "name": "string", 

254 "uuid": "string", 

255 "description": "string", 

256 "updatedAt": "2019-08-24T14:15:22Z", 

257 "updatedByUser": { 

258 "userUuid": "string", 

259 "firstName": "string", 

260 "lastName": "string" }, 

261 "spaceUuid": "string", 

262 "pinnedListUuid": "string", 

263 "pinnedListOrder": 0, 

264 "firstViewedAt": "2019-08-24T14:15:22Z", 

265 "views": 0, 

266 "validationErrors": [ { 

267 "validationId": 0, 

268 "createdAt": "2019-08-24T14:15:22Z", 

269 "error": "string" } ], 

270 "chartType": "line" } ], 

271 "isPrivate": true, 

272 "name": "string", 

273 "uuid": "string", 

274 "organizationUuid": "string" } 

275 """ 

276 resp = self._request("get", f"projects/{project_uuid}/spaces/{space_uuid}") 

277 if resp.ok: 

278 return resp.json()["results"] 

279 return {} 

280 

281 def get_chart_version_history(self, chart_uuid: str): 

282 """ 

283 Get chart version history from last 30 days 

284 Return format: 

285 [{"createdAt": "2019-08-24T14:15:22Z", 

286 "chartUuid": "string", 

287 "versionUuid": "string", 

288 "createdBy": { 

289 "userUuid": "string", 

290 "firstName": "string", 

291 "lastName": "string" }}] 

292 """ 

293 resp = self._request("get", f"saved/{chart_uuid}/history") 

294 if resp.ok: 

295 return resp.json()["results"]["history"] 

296 return [] 

297 

298 def get_chart(self, chart_uuid: str, version_uuid: str): 

299 """ 

300 Get chart details 

301 Return format: 

302 { "chart": { 

303 "dashboardName": "string", 

304 "dashboardUuid": "string", 

305 "pinnedListOrder": 0, 

306 "pinnedListUuid": "string", 

307 "spaceName": "string", 

308 "spaceUuid": "string", 

309 "organizationUuid": "string", 

310 "updatedByUser": { 

311 "userUuid": "string", 

312 "firstName": "string", 

313 "lastName": "string" }, 

314 "updatedAt": "2019-08-24T14:15:22Z", 

315 "tableConfig": { 

316 "columnOrder": [ 

317 "string" ] }, 

318 "chartConfig": { 

319 "config": { 

320 "legendPosition": "horizontal", 

321 "showLegend": true, 

322 "groupSortOverrides": [ 

323 "string" ], 

324 "groupValueOptionOverrides": {}, 

325 "groupColorOverrides": {}, 

326 "groupLabelOverrides": {}, 

327 "showPercentage": true, 

328 "showValue": true, 

329 "valueLabel": "hidden", 

330 "isDonut": true, 

331 "metricId": "string", 

332 "groupFieldIds": [ 

333 "string" ] }, 

334 "type": "pie" }, 

335 "pivotConfig": { 

336 "columns": [ 

337 "string" ] }, 

338 "metricQuery": { 

339 "additionalMetrics": [ { 

340 "label": "string", 

341 "type": "percentile", 

342 "description": "string", 

343 "sql": "string", 

344 "hidden": true, 

345 "round": 0, 

346 "compact": "thousands", 

347 "format": "km", 

348 "table": "string", 

349 "name": "string", 

350 "index": 0, 

351 "filters": [ { 

352 "values": [ 

353 null ], 

354 "operator": "isNull", 

355 "id": "string", 

356 "target": { 

357 "fieldRef": "string" }, 

358 "settings": null, 

359 "disabled": true } ], 

360 "baseDimensionName": "string", 

361 "uuid": "string", 

362 "percentile": 0 } ], 

363 "tableCalculations": [ { 

364 "format": { 

365 "suffix": "string", 

366 "prefix": "string", 

367 "compact": "thousands", 

368 "currency": "string", 

369 "separator": "default", 

370 "round": 0, 

371 "type": "default" }, 

372 "sql": "string", 

373 "displayName": "string", 

374 "name": "string", 

375 "index": 0 } ], 

376 "limit": 0, 

377 "sorts": [ { 

378 "descending": true, 

379 "fieldId": "string" } ], 

380 "filters": { 

381 "metrics": { 

382 "or": [ 

383 null ], 

384 "id": "string" }, 

385 "dimensions": { 

386 "or": [ 

387 null ], 

388 "id": "string" } }, 

389 "metrics": [ 

390 "string" ], 

391 "dimensions": [ 

392 "string" ] }, 

393 "tableName": "string", 

394 "description": "string", 

395 "name": "string", 

396 "projectUuid": "string", 

397 "uuid": "string" }, 

398 "createdBy": { 

399 "userUuid": "string", 

400 "firstName": "string", 

401 "lastName": "string" }, 

402 "createdAt": "2019-08-24T14:15:22Z", 

403 "versionUuid": "string", 

404 "chartUuid": "string" } 

405 """ 

406 resp = self._request("get", f"saved/{chart_uuid}/version/{version_uuid}") 

407 if resp.ok: 

408 return resp.json()["results"] 

409 return {} 

410 

411 def get_scheduler_logs(self, project_uuid: str): 

412 """ 

413 Get scheduled logs 

414 Return format: 

415 { "logs": [ { 

416 "details": {}, 

417 "targetType": "email", 

418 "target": "string", 

419 "status": "scheduled", 

420 "createdAt": "2019-08-24T14:15:22Z", 

421 "scheduledTime": "2019-08-24T14:15:22Z", 

422 "jobGroup": "string", 

423 "jobId": "string", 

424 "schedulerUuid": "string", 

425 "task": "handleScheduledDelivery" 

426 } ], 

427 "dashboards": [ { 

428 "dashboardUuid": "string", 

429 "name": "string" } ], 

430 "charts": [ { 

431 "savedChartUuid": "string", 

432 "name": "string" } ], 

433 "users": [ { 

434 "userUuid": "string", 

435 "lastName": "string", 

436 "firstName": "string" } ], 

437 "schedulers": [ { 

438 "options": { 

439 "limit": 0, 

440 "formatted": true }, 

441 "dashboardUuid": null, 

442 "savedChartUuid": "string", 

443 "cron": "string", 

444 "format": "csv", 

445 "createdBy": "string", 

446 "updatedAt": "2019-08-24T14:15:22Z", 

447 "createdAt": "2019-08-24T14:15:22Z", 

448 "message": "string", 

449 "name": "string", 

450 "schedulerUuid": "string", 

451 "targets": [ { 

452 "channel": "string", 

453 "schedulerUuid": "string", 

454 "updatedAt": "2019-08-24T14:15:22Z", 

455 "createdAt": "2019-08-24T14:15:22Z", 

456 "schedulerSlackTargetUuid": "string" } ] } ] } 

457 """ 

458 resp = self._request("get", f"schedulers/{project_uuid}/logs") 

459 if resp.ok: 

460 return resp.json()["results"] 

461 return {} 

462 

463 def get_scheduler(self, scheduler_uuid: str): 

464 """ 

465 Get details of a scheduler 

466 Return format: 

467 { "options": { 

468 "limit": 0, 

469 "formatted": true }, 

470 "dashboardUuid": null, 

471 "savedChartUuid": "string", 

472 "cron": "string", 

473 "format": "csv", 

474 "createdBy": "string", 

475 "updatedAt": "2019-08-24T14:15:22Z", 

476 "createdAt": "2019-08-24T14:15:22Z", 

477 "message": "string", 

478 "name": "string", 

479 "schedulerUuid": "string", 

480 "targets": [ { 

481 "channel": "string", 

482 "schedulerUuid": "string", 

483 "updatedAt": "2019-08-24T14:15:22Z", 

484 "createdAt": "2019-08-24T14:15:22Z", 

485 "schedulerSlackTargetUuid": "string" } ] } 

486 """ 

487 resp = self._request("get", f"schedulers/{scheduler_uuid}") 

488 if resp.ok: 

489 return resp.json()["results"] 

490 return {} 

491 

492 def get_scheduler_jobs(self, scheduler_uuid: str): 

493 """ 

494 Get jobs scheduled by a scheduler 

495 Return format: 

496 [ { "id": "string", 

497 "date": "2019-08-24T14:15:22Z" } ] 

498 """ 

499 resp = self._request("get", f"schedulers/{scheduler_uuid}/jobs") 

500 if resp.ok: 

501 return resp.json()["results"] 

502 return [] 

503 

504 def get_scheduler_job_status(self, job_id: str): 

505 """ 

506 Get a generic job status 

507 Return format: 

508 { "status": "string" } 

509 """ 

510 resp = self._request("get", f"schedulers/job/{job_id}/status") 

511 if resp.ok: 

512 return resp.json()["results"] 

513 return {}