databay-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. databay/__init__.py +5 -0
  2. databay/__main__.py +7 -0
  3. databay/agent_skill.py +184 -0
  4. databay/api.py +626 -0
  5. databay/cli/__init__.py +0 -0
  6. databay/cli/auth.py +377 -0
  7. databay/cli/build.py +89 -0
  8. databay/cli/commands/__init__.py +0 -0
  9. databay/cli/commands/alerting_webhook.py +19 -0
  10. databay/cli/commands/alerting_webhook_tag.py +14 -0
  11. databay/cli/commands/alerting_webhook_type.py +14 -0
  12. databay/cli/commands/alerting_webhook_undelivered.py +15 -0
  13. databay/cli/commands/announcement.py +17 -0
  14. databay/cli/commands/api_key.py +18 -0
  15. databay/cli/commands/api_key_project.py +16 -0
  16. databay/cli/commands/backfill_reason_code.py +14 -0
  17. databay/cli/commands/backfill_run.py +17 -0
  18. databay/cli/commands/canvas.py +16 -0
  19. databay/cli/commands/canvas_graph.py +15 -0
  20. databay/cli/commands/canvas_table_check.py +15 -0
  21. databay/cli/commands/dashboards.py +21 -0
  22. databay/cli/commands/dashboards_card.py +20 -0
  23. databay/cli/commands/dashboards_dataset.py +14 -0
  24. databay/cli/commands/dashboards_folder.py +16 -0
  25. databay/cli/commands/dashboards_home.py +17 -0
  26. databay/cli/commands/dashboards_placement.py +16 -0
  27. databay/cli/commands/db.py +19 -0
  28. databay/cli/commands/db_column.py +14 -0
  29. databay/cli/commands/docs_article.py +16 -0
  30. databay/cli/commands/dq_result.py +14 -0
  31. databay/cli/commands/dq_rule.py +16 -0
  32. databay/cli/commands/feature.py +14 -0
  33. databay/cli/commands/google_ads_source.py +14 -0
  34. databay/cli/commands/google_analytics_source.py +14 -0
  35. databay/cli/commands/instagram_account.py +14 -0
  36. databay/cli/commands/instagram_source.py +14 -0
  37. databay/cli/commands/linkedin_account.py +14 -0
  38. databay/cli/commands/linkedin_source.py +14 -0
  39. databay/cli/commands/me.py +14 -0
  40. databay/cli/commands/meta_ads_source.py +14 -0
  41. databay/cli/commands/metric_models.py +26 -0
  42. databay/cli/commands/metrics.py +14 -0
  43. databay/cli/commands/models.py +16 -0
  44. databay/cli/commands/nlq.py +15 -0
  45. databay/cli/commands/notebook_credential.py +16 -0
  46. databay/cli/commands/org.py +14 -0
  47. databay/cli/commands/org_member.py +17 -0
  48. databay/cli/commands/org_offboarding.py +14 -0
  49. databay/cli/commands/pipe.py +26 -0
  50. databay/cli/commands/pipe_backfill_run.py +14 -0
  51. databay/cli/commands/pipe_config_option.py +14 -0
  52. databay/cli/commands/pipe_destination.py +16 -0
  53. databay/cli/commands/pipe_leftover.py +16 -0
  54. databay/cli/commands/pipe_sink_type.py +14 -0
  55. databay/cli/commands/pipe_source_type.py +14 -0
  56. databay/cli/commands/pipe_status_bucket.py +14 -0
  57. databay/cli/commands/pipe_stuck_delete.py +14 -0
  58. databay/cli/commands/plan.py +14 -0
  59. databay/cli/commands/project.py +21 -0
  60. databay/cli/commands/project_budget.py +15 -0
  61. databay/cli/commands/project_member.py +18 -0
  62. databay/cli/commands/project_privilege.py +16 -0
  63. databay/cli/commands/project_share.py +16 -0
  64. databay/cli/commands/provision.py +14 -0
  65. databay/cli/commands/provisioning.py +14 -0
  66. databay/cli/commands/registry.py +14 -0
  67. databay/cli/commands/resource_home.py +14 -0
  68. databay/cli/commands/schema_change.py +18 -0
  69. databay/cli/commands/schema_history.py +17 -0
  70. databay/cli/commands/schema_version.py +16 -0
  71. databay/cli/commands/shopify_store.py +14 -0
  72. databay/cli/commands/sink_data_type.py +14 -0
  73. databay/cli/commands/source.py +24 -0
  74. databay/cli/commands/source_catalog.py +15 -0
  75. databay/cli/commands/source_check_run.py +17 -0
  76. databay/cli/commands/source_hidden_type.py +14 -0
  77. databay/cli/commands/source_name.py +14 -0
  78. databay/cli/commands/source_pipe.py +14 -0
  79. databay/cli/commands/source_publication.py +16 -0
  80. databay/cli/commands/source_readiness_override.py +15 -0
  81. databay/cli/commands/source_setup_choice.py +16 -0
  82. databay/cli/commands/source_stream.py +15 -0
  83. databay/cli/commands/source_table.py +14 -0
  84. databay/cli/commands/ssbi_job.py +18 -0
  85. databay/cli/commands/transform_type.py +14 -0
  86. databay/cli/commands/usage.py +14 -0
  87. databay/cli/commands/warehouse.py +21 -0
  88. databay/cli/commands/warehouse_access_assignment.py +16 -0
  89. databay/cli/commands/warehouse_access_role.py +22 -0
  90. databay/cli/commands/warehouse_access_settings.py +17 -0
  91. databay/cli/commands/warehouse_login.py +20 -0
  92. databay/cli/commands/warehouse_principal.py +17 -0
  93. databay/cli/commands/warehouse_service_account.py +17 -0
  94. databay/cli/commands/warehouse_service_account_credential.py +18 -0
  95. databay/cli/common.py +93 -0
  96. databay/cli/console.py +121 -0
  97. databay/cli/flags.py +183 -0
  98. databay/cli/handwritten.py +22 -0
  99. databay/cli/main.py +198 -0
  100. databay/cli/metrics.py +171 -0
  101. databay/cli/org.py +193 -0
  102. databay/cli/output.py +134 -0
  103. databay/cli/pipe_wait.py +357 -0
  104. databay/cli/profile.py +230 -0
  105. databay/cli/runner.py +432 -0
  106. databay/cli/skill.py +64 -0
  107. databay/cli/sql.py +84 -0
  108. databay/compat.py +161 -0
  109. databay/credentials.py +217 -0
  110. databay/error_catalog.py +226 -0
  111. databay/error_codes.py +3265 -0
  112. databay/errors.py +222 -0
  113. databay/feature_header.py +40 -0
  114. databay/invoke.py +225 -0
  115. databay/locks.py +41 -0
  116. databay/login_flow.py +245 -0
  117. databay/model_base.py +40 -0
  118. databay/models/__init__.py +0 -0
  119. databay/models/alerting_webhook.py +46 -0
  120. databay/models/alerting_webhook_tag.py +11 -0
  121. databay/models/alerting_webhook_type.py +11 -0
  122. databay/models/alerting_webhook_undelivered.py +23 -0
  123. databay/models/announcement.py +37 -0
  124. databay/models/api_key.py +81 -0
  125. databay/models/api_key_project.py +29 -0
  126. databay/models/backfill_reason_code.py +11 -0
  127. databay/models/backfill_run.py +41 -0
  128. databay/models/canvas.py +68 -0
  129. databay/models/canvas_graph.py +86 -0
  130. databay/models/canvas_table_check.py +181 -0
  131. databay/models/dashboards.py +79 -0
  132. databay/models/dashboards_card.py +37 -0
  133. databay/models/dashboards_dataset.py +27 -0
  134. databay/models/dashboards_folder.py +18 -0
  135. databay/models/dashboards_home.py +28 -0
  136. databay/models/db.py +34 -0
  137. databay/models/db_column.py +11 -0
  138. databay/models/docs_article.py +59 -0
  139. databay/models/dq_result.py +27 -0
  140. databay/models/dq_rule.py +43 -0
  141. databay/models/feature.py +15 -0
  142. databay/models/google_ads_source.py +11 -0
  143. databay/models/google_analytics_source.py +11 -0
  144. databay/models/instagram_source.py +11 -0
  145. databay/models/linkedin_source.py +11 -0
  146. databay/models/me.py +71 -0
  147. databay/models/meta_ads_source.py +11 -0
  148. databay/models/metric_models.py +274 -0
  149. databay/models/metrics.py +158 -0
  150. databay/models/models.py +73 -0
  151. databay/models/nlq.py +92 -0
  152. databay/models/notebook_credential.py +51 -0
  153. databay/models/org.py +44 -0
  154. databay/models/org_member.py +123 -0
  155. databay/models/org_offboarding.py +36 -0
  156. databay/models/pipe.py +340 -0
  157. databay/models/pipe_config_option.py +25 -0
  158. databay/models/pipe_destination.py +128 -0
  159. databay/models/pipe_leftover.py +51 -0
  160. databay/models/pipe_sink_type.py +11 -0
  161. databay/models/pipe_source_type.py +11 -0
  162. databay/models/pipe_status_bucket.py +13 -0
  163. databay/models/pipe_stuck_delete.py +25 -0
  164. databay/models/plan.py +37 -0
  165. databay/models/project.py +154 -0
  166. databay/models/project_budget.py +22 -0
  167. databay/models/project_member.py +67 -0
  168. databay/models/project_privilege.py +21 -0
  169. databay/models/project_share.py +76 -0
  170. databay/models/provision.py +12 -0
  171. databay/models/provisioning.py +20 -0
  172. databay/models/registry.py +18 -0
  173. databay/models/resource_home.py +35 -0
  174. databay/models/schema_change.py +96 -0
  175. databay/models/schema_history.py +32 -0
  176. databay/models/schema_version.py +23 -0
  177. databay/models/shared.py +875 -0
  178. databay/models/shopify_store.py +19 -0
  179. databay/models/sink_data_type.py +11 -0
  180. databay/models/source.py +263 -0
  181. databay/models/source_catalog.py +82 -0
  182. databay/models/source_check_run.py +63 -0
  183. databay/models/source_hidden_type.py +13 -0
  184. databay/models/source_name.py +18 -0
  185. databay/models/source_pipe.py +16 -0
  186. databay/models/source_publication.py +30 -0
  187. databay/models/source_readiness_override.py +13 -0
  188. databay/models/source_setup_choice.py +33 -0
  189. databay/models/source_stream.py +65 -0
  190. databay/models/source_table.py +27 -0
  191. databay/models/sql.py +31 -0
  192. databay/models/ssbi_job.py +97 -0
  193. databay/models/transform_type.py +40 -0
  194. databay/models/usage.py +112 -0
  195. databay/models/warehouse.py +38 -0
  196. databay/models/warehouse_access_assignment.py +70 -0
  197. databay/models/warehouse_access_role.py +148 -0
  198. databay/models/warehouse_access_settings.py +35 -0
  199. databay/models/warehouse_login.py +20 -0
  200. databay/models/warehouse_principal.py +49 -0
  201. databay/models/warehouse_service_account.py +35 -0
  202. databay/models/warehouse_service_account_credential.py +11 -0
  203. databay/oidc.py +205 -0
  204. databay/operation.py +191 -0
  205. databay/operations/__init__.py +0 -0
  206. databay/operations/alerting_webhook.py +317 -0
  207. databay/operations/alerting_webhook_tag.py +35 -0
  208. databay/operations/alerting_webhook_type.py +35 -0
  209. databay/operations/alerting_webhook_undelivered.py +74 -0
  210. databay/operations/announcement.py +135 -0
  211. databay/operations/api_key.py +198 -0
  212. databay/operations/api_key_project.py +130 -0
  213. databay/operations/backfill_reason_code.py +35 -0
  214. databay/operations/backfill_run.py +245 -0
  215. databay/operations/canvas.py +136 -0
  216. databay/operations/canvas_graph.py +102 -0
  217. databay/operations/canvas_table_check.py +101 -0
  218. databay/operations/dashboards.py +441 -0
  219. databay/operations/dashboards_card.py +406 -0
  220. databay/operations/dashboards_dataset.py +50 -0
  221. databay/operations/dashboards_folder.py +146 -0
  222. databay/operations/dashboards_home.py +176 -0
  223. databay/operations/dashboards_placement.py +152 -0
  224. databay/operations/db.py +337 -0
  225. databay/operations/db_column.py +57 -0
  226. databay/operations/docs_article.py +101 -0
  227. databay/operations/dq_result.py +43 -0
  228. databay/operations/dq_rule.py +155 -0
  229. databay/operations/feature.py +35 -0
  230. databay/operations/google_ads_source.py +40 -0
  231. databay/operations/google_analytics_source.py +40 -0
  232. databay/operations/instagram_account.py +47 -0
  233. databay/operations/instagram_source.py +40 -0
  234. databay/operations/linkedin_account.py +47 -0
  235. databay/operations/linkedin_source.py +40 -0
  236. databay/operations/me.py +57 -0
  237. databay/operations/meta_ads_source.py +40 -0
  238. databay/operations/metric_models.py +612 -0
  239. databay/operations/metrics.py +218 -0
  240. databay/operations/models.py +123 -0
  241. databay/operations/nlq.py +100 -0
  242. databay/operations/notebook_credential.py +95 -0
  243. databay/operations/org.py +79 -0
  244. databay/operations/org_member.py +192 -0
  245. databay/operations/org_offboarding.py +43 -0
  246. databay/operations/pipe.py +882 -0
  247. databay/operations/pipe_backfill_run.py +72 -0
  248. databay/operations/pipe_config_option.py +50 -0
  249. databay/operations/pipe_destination.py +178 -0
  250. databay/operations/pipe_leftover.py +110 -0
  251. databay/operations/pipe_sink_type.py +35 -0
  252. databay/operations/pipe_source_type.py +35 -0
  253. databay/operations/pipe_status_bucket.py +35 -0
  254. databay/operations/pipe_stuck_delete.py +52 -0
  255. databay/operations/plan.py +35 -0
  256. databay/operations/project.py +346 -0
  257. databay/operations/project_budget.py +135 -0
  258. databay/operations/project_member.py +226 -0
  259. databay/operations/project_privilege.py +143 -0
  260. databay/operations/project_share.py +160 -0
  261. databay/operations/provision.py +35 -0
  262. databay/operations/provisioning.py +35 -0
  263. databay/operations/registry.py +35 -0
  264. databay/operations/resource_home.py +80 -0
  265. databay/operations/schema_change.py +222 -0
  266. databay/operations/schema_history.py +136 -0
  267. databay/operations/schema_version.py +115 -0
  268. databay/operations/shopify_store.py +40 -0
  269. databay/operations/sink_data_type.py +43 -0
  270. databay/operations/source.py +1207 -0
  271. databay/operations/source_catalog.py +135 -0
  272. databay/operations/source_check_run.py +242 -0
  273. databay/operations/source_hidden_type.py +59 -0
  274. databay/operations/source_name.py +69 -0
  275. databay/operations/source_pipe.py +57 -0
  276. databay/operations/source_publication.py +139 -0
  277. databay/operations/source_readiness_override.py +96 -0
  278. databay/operations/source_setup_choice.py +161 -0
  279. databay/operations/source_stream.py +99 -0
  280. databay/operations/source_table.py +59 -0
  281. databay/operations/sql.py +54 -0
  282. databay/operations/ssbi_job.py +242 -0
  283. databay/operations/transform_type.py +35 -0
  284. databay/operations/usage.py +35 -0
  285. databay/operations/warehouse.py +343 -0
  286. databay/operations/warehouse_access_assignment.py +179 -0
  287. databay/operations/warehouse_access_role.py +473 -0
  288. databay/operations/warehouse_access_settings.py +172 -0
  289. databay/operations/warehouse_login.py +308 -0
  290. databay/operations/warehouse_principal.py +174 -0
  291. databay/operations/warehouse_service_account.py +206 -0
  292. databay/operations/warehouse_service_account_credential.py +285 -0
  293. databay/paths.py +32 -0
  294. databay/platform_check.py +20 -0
  295. databay/profiles.py +181 -0
  296. databay/redact.py +22 -0
  297. databay/reference.py +218 -0
  298. databay/resource.py +167 -0
  299. databay/resources/__init__.py +0 -0
  300. databay/resources/alerting_webhook.py +84 -0
  301. databay/resources/alerting_webhook_tag.py +21 -0
  302. databay/resources/alerting_webhook_type.py +21 -0
  303. databay/resources/alerting_webhook_undelivered.py +35 -0
  304. databay/resources/announcement.py +45 -0
  305. databay/resources/api_key.py +56 -0
  306. databay/resources/api_key_project.py +47 -0
  307. databay/resources/backfill_reason_code.py +21 -0
  308. databay/resources/backfill_run.py +78 -0
  309. databay/resources/canvas.py +43 -0
  310. databay/resources/canvas_graph.py +38 -0
  311. databay/resources/canvas_table_check.py +38 -0
  312. databay/resources/dashboards.py +105 -0
  313. databay/resources/dashboards_card.py +97 -0
  314. databay/resources/dashboards_dataset.py +27 -0
  315. databay/resources/dashboards_folder.py +47 -0
  316. databay/resources/dashboards_home.py +59 -0
  317. databay/resources/dashboards_placement.py +47 -0
  318. databay/resources/db.py +87 -0
  319. databay/resources/db_column.py +28 -0
  320. databay/resources/docs_article.py +37 -0
  321. databay/resources/dq_result.py +25 -0
  322. databay/resources/dq_rule.py +48 -0
  323. databay/resources/feature.py +21 -0
  324. databay/resources/google_ads_source.py +25 -0
  325. databay/resources/google_analytics_source.py +25 -0
  326. databay/resources/instagram_account.py +27 -0
  327. databay/resources/instagram_source.py +25 -0
  328. databay/resources/linkedin_account.py +27 -0
  329. databay/resources/linkedin_source.py +25 -0
  330. databay/resources/me.py +27 -0
  331. databay/resources/meta_ads_source.py +25 -0
  332. databay/resources/metric_models.py +154 -0
  333. databay/resources/metrics.py +57 -0
  334. databay/resources/models.py +42 -0
  335. databay/resources/nlq.py +34 -0
  336. databay/resources/notebook_credential.py +41 -0
  337. databay/resources/org.py +29 -0
  338. databay/resources/org_member.py +53 -0
  339. databay/resources/org_offboarding.py +25 -0
  340. databay/resources/pipe.py +208 -0
  341. databay/resources/pipe_backfill_run.py +28 -0
  342. databay/resources/pipe_config_option.py +26 -0
  343. databay/resources/pipe_destination.py +49 -0
  344. databay/resources/pipe_leftover.py +42 -0
  345. databay/resources/pipe_sink_type.py +21 -0
  346. databay/resources/pipe_source_type.py +21 -0
  347. databay/resources/pipe_status_bucket.py +21 -0
  348. databay/resources/pipe_stuck_delete.py +27 -0
  349. databay/resources/plan.py +21 -0
  350. databay/resources/project.py +92 -0
  351. databay/resources/project_budget.py +38 -0
  352. databay/resources/project_member.py +68 -0
  353. databay/resources/project_privilege.py +48 -0
  354. databay/resources/project_share.py +47 -0
  355. databay/resources/provision.py +21 -0
  356. databay/resources/provisioning.py +21 -0
  357. databay/resources/registry.py +21 -0
  358. databay/resources/resource_home.py +29 -0
  359. databay/resources/schema_change.py +62 -0
  360. databay/resources/schema_history.py +52 -0
  361. databay/resources/schema_version.py +43 -0
  362. databay/resources/shopify_store.py +25 -0
  363. databay/resources/sink_data_type.py +25 -0
  364. databay/resources/source.py +132 -0
  365. databay/resources/source_catalog.py +34 -0
  366. databay/resources/source_check_run.py +67 -0
  367. databay/resources/source_hidden_type.py +25 -0
  368. databay/resources/source_name.py +27 -0
  369. databay/resources/source_pipe.py +28 -0
  370. databay/resources/source_publication.py +47 -0
  371. databay/resources/source_readiness_override.py +37 -0
  372. databay/resources/source_setup_choice.py +50 -0
  373. databay/resources/source_stream.py +38 -0
  374. databay/resources/source_table.py +27 -0
  375. databay/resources/sql.py +27 -0
  376. databay/resources/ssbi_job.py +69 -0
  377. databay/resources/transform_type.py +21 -0
  378. databay/resources/usage.py +21 -0
  379. databay/resources/warehouse.py +136 -0
  380. databay/resources/warehouse_access_assignment.py +51 -0
  381. databay/resources/warehouse_access_role.py +118 -0
  382. databay/resources/warehouse_access_settings.py +56 -0
  383. databay/resources/warehouse_login.py +81 -0
  384. databay/resources/warehouse_principal.py +51 -0
  385. databay/resources/warehouse_service_account.py +61 -0
  386. databay/resources/warehouse_service_account_credential.py +78 -0
  387. databay/sdk.py +77 -0
  388. databay/settings.py +90 -0
  389. databay/skill/SKILL.md +357 -0
  390. databay/skill/references/commands.md +7025 -0
  391. databay/skill/references/errors.md +727 -0
  392. databay/spec.py +362 -0
  393. databay/stored_token.py +134 -0
  394. databay/tokens.py +108 -0
  395. databay/transport.py +357 -0
  396. databay/update_check.py +151 -0
  397. databay/version.py +6 -0
  398. databay/waits.py +330 -0
  399. databay_cli-0.1.0.dist-info/METADATA +42 -0
  400. databay_cli-0.1.0.dist-info/RECORD +403 -0
  401. databay_cli-0.1.0.dist-info/WHEEL +4 -0
  402. databay_cli-0.1.0.dist-info/entry_points.txt +2 -0
  403. databay_cli-0.1.0.dist-info/licenses/LICENSE +202 -0
databay/spec.py ADDED
@@ -0,0 +1,362 @@
1
+ """The API version this client speaks, and where each noun and operation is generated.
2
+
3
+ Generated by python/tools/gen_client.py from contract/core.json; do not edit.
4
+ """
5
+
6
+ API_VERSION = '1.0'
7
+
8
+ #: CLI noun -> (its module under ``databay.cli.commands``, the verbs it has).
9
+ NOUNS: dict[str, tuple[str, tuple[str, ...]]] = {
10
+ 'alerting-webhook': ('alerting_webhook', ('create', 'delete', 'get', 'list', 'notify', 'update')),
11
+ 'alerting-webhook-tag': ('alerting_webhook_tag', ('list',)),
12
+ 'alerting-webhook-type': ('alerting_webhook_type', ('list',)),
13
+ 'alerting-webhook-undelivered': ('alerting_webhook_undelivered', ('list', 'replay')),
14
+ 'announcement': ('announcement', ('list', 'mark-all-read', 'mark-read', 'mark-unread')),
15
+ 'api-key': ('api_key', ('create', 'get', 'list', 'revoke', 'rotate')),
16
+ 'api-key-project': ('api_key_project', ('add', 'bi-connection', 'remove')),
17
+ 'backfill-reason-code': ('backfill_reason_code', ('list',)),
18
+ 'backfill-run': ('backfill_run', ('cancel', 'create', 'get', 'list')),
19
+ 'canvas': ('canvas', ('activate', 'list', 'volumes')),
20
+ 'canvas-graph': ('canvas_graph', ('get', 'put')),
21
+ 'canvas-table-check': ('canvas_table_check', ('get', 'start')),
22
+ 'dashboards': ('dashboards', ('create', 'delete', 'duplicate', 'get', 'list', 'replace', 'run', 'update')),
23
+ 'dashboards-card': ('dashboards_card', ('create', 'delete', 'get', 'list', 'preview', 'run', 'update')),
24
+ 'dashboards-dataset': ('dashboards_dataset', ('list',)),
25
+ 'dashboards-folder': ('dashboards_folder', ('create', 'delete', 'update')),
26
+ 'dashboards-home': ('dashboards_home', ('get', 'pin', 'pin-many', 'set')),
27
+ 'dashboards-placement': ('dashboards_placement', ('create', 'delete', 'run')),
28
+ 'db': ('db', ('create', 'delete', 'get', 'get-by-name', 'list', 'test')),
29
+ 'db-column': ('db_column', ('list',)),
30
+ 'docs-article': ('docs_article', ('get', 'list', 'search')),
31
+ 'dq-result': ('dq_result', ('list',)),
32
+ 'dq-rule': ('dq_rule', ('create', 'dag', 'list')),
33
+ 'feature': ('feature', ('list',)),
34
+ 'google-ads-source': ('google_ads_source', ('list',)),
35
+ 'google-analytics-source': ('google_analytics_source', ('list',)),
36
+ 'instagram-account': ('instagram_account', ('list',)),
37
+ 'instagram-source': ('instagram_source', ('list',)),
38
+ 'linkedin-account': ('linkedin_account', ('list',)),
39
+ 'linkedin-source': ('linkedin_source', ('list',)),
40
+ 'me': ('me', ('get',)),
41
+ 'meta-ads-source': ('meta_ads_source', ('list',)),
42
+ 'metric-models': ('metric_models', ('changes', 'import-dbt', 'list', 'metric-add', 'metric-list', 'metric-remove', 'metric-update', 'publish', 'push', 'set-breakdowns', 'show-draft', 'show-published', 'validate')),
43
+ 'metrics': ('metrics', ('list',)),
44
+ 'models': ('models', ('check', 'sync', 'sync-status')),
45
+ 'nlq': ('nlq', ('ask', 'usage')),
46
+ 'notebook-credential': ('notebook_credential', ('get-binding', 'issue', 'renew')),
47
+ 'org': ('org', ('list',)),
48
+ 'org-member': ('org_member', ('add', 'list', 'remove', 'set-role')),
49
+ 'org-offboarding': ('org_offboarding', ('get',)),
50
+ 'pipe': ('pipe', ('create', 'delete', 'get', 'list', 'move', 'pause', 'rebuild', 'restart', 'resume', 'retry', 'rollup', 'status', 'update')),
51
+ 'pipe-backfill-run': ('pipe_backfill_run', ('list',)),
52
+ 'pipe-config-option': ('pipe_config_option', ('get',)),
53
+ 'pipe-destination': ('pipe_destination', ('check', 'get', 'preview')),
54
+ 'pipe-leftover': ('pipe_leftover', ('check', 'dismiss', 'list')),
55
+ 'pipe-sink-type': ('pipe_sink_type', ('list',)),
56
+ 'pipe-source-type': ('pipe_source_type', ('list',)),
57
+ 'pipe-status-bucket': ('pipe_status_bucket', ('list',)),
58
+ 'pipe-stuck-delete': ('pipe_stuck_delete', ('list',)),
59
+ 'plan': ('plan', ('list',)),
60
+ 'project': ('project', ('create', 'delete', 'delete-preview', 'delete-retry', 'get', 'list', 'my-access', 'update')),
61
+ 'project-budget': ('project_budget', ('list', 'set')),
62
+ 'project-member': ('project_member', ('list', 'people', 'remove', 'search', 'set')),
63
+ 'project-privilege': ('project_privilege', ('grant', 'list', 'revoke')),
64
+ 'project-share': ('project_share', ('create', 'list', 'revoke')),
65
+ 'provision': ('provision', ('ensure-defaults',)),
66
+ 'provisioning': ('provisioning', ('status',)),
67
+ 'registry': ('registry', ('get',)),
68
+ 'resource-home': ('resource_home', ('transfer',)),
69
+ 'schema-change': ('schema_change', ('apply', 'ignore', 'list', 'pending', 'state')),
70
+ 'schema-history': ('schema_history', ('create', 'get', 'list', 'summary')),
71
+ 'schema-version': ('schema_version', ('current', 'get', 'list')),
72
+ 'shopify-store': ('shopify_store', ('list',)),
73
+ 'sink-data-type': ('sink_data_type', ('list',)),
74
+ 'source': ('source', ('cascade-delete', 'create', 'delete', 'force-delete', 'get', 'list', 'precheck', 'recheck', 'renew-credentials', 'setup-script', 'update')),
75
+ 'source-catalog': ('source_catalog', ('list', 'setup-script')),
76
+ 'source-check-run': ('source_check_run', ('get', 'latest', 'start', 'tables')),
77
+ 'source-hidden-type': ('source_hidden_type', ('list',)),
78
+ 'source-name': ('source_name', ('check',)),
79
+ 'source-pipe': ('source_pipe', ('list',)),
80
+ 'source-publication': ('source_publication', ('check', 'get', 'set')),
81
+ 'source-readiness-override': ('source_readiness_override', ('delete', 'set')),
82
+ 'source-setup-choice': ('source_setup_choice', ('check', 'get', 'set')),
83
+ 'source-stream': ('source_stream', ('get', 'list')),
84
+ 'source-table': ('source_table', ('check',)),
85
+ 'ssbi-job': ('ssbi_job', ('create', 'delete', 'get', 'list', 'update')),
86
+ 'transform-type': ('transform_type', ('list',)),
87
+ 'usage': ('usage', ('get',)),
88
+ 'warehouse': ('warehouse', ('create', 'delete', 'get', 'impact', 'list', 'rename', 'retry', 'stats')),
89
+ 'warehouse-access-assignment': ('warehouse_access_assignment', ('list', 'preview', 'set')),
90
+ 'warehouse-access-role': ('warehouse_access_role', ('create', 'delete', 'get-metrics', 'list', 'list-tables', 'set-metrics', 'set-rules', 'set-scope-mode', 'update')),
91
+ 'warehouse-access-settings': ('warehouse_access_settings', ('get', 'get-default-role', 'set', 'set-default-role')),
92
+ 'warehouse-login': ('warehouse_login', ('create', 'delete', 'list', 'list-mine', 'policy', 'rotate', 'update')),
93
+ 'warehouse-principal': ('warehouse_principal', ('disable', 'enable', 'list', 'list-project')),
94
+ 'warehouse-service-account': ('warehouse_service_account', ('create', 'delete', 'list', 'update')),
95
+ 'warehouse-service-account-credential': ('warehouse_service_account_credential', ('create', 'delete', 'list', 'rotate', 'update')),
96
+ }
97
+
98
+ #: Operation id -> (its module under ``databay.operations``, its constant).
99
+ OPERATIONS = {
100
+ 'alerting_webhook_create': ('alerting_webhook', 'ALERTING_WEBHOOK_CREATE'),
101
+ 'alerting_webhook_delete': ('alerting_webhook', 'ALERTING_WEBHOOK_DELETE'),
102
+ 'alerting_webhook_get': ('alerting_webhook', 'ALERTING_WEBHOOK_GET'),
103
+ 'alerting_webhook_list': ('alerting_webhook', 'ALERTING_WEBHOOK_LIST'),
104
+ 'alerting_webhook_notify': ('alerting_webhook', 'ALERTING_WEBHOOK_NOTIFY'),
105
+ 'alerting_webhook_tag_list': ('alerting_webhook_tag', 'ALERTING_WEBHOOK_TAG_LIST'),
106
+ 'alerting_webhook_type_list': ('alerting_webhook_type', 'ALERTING_WEBHOOK_TYPE_LIST'),
107
+ 'alerting_webhook_undelivered_list': ('alerting_webhook_undelivered', 'ALERTING_WEBHOOK_UNDELIVERED_LIST'),
108
+ 'alerting_webhook_undelivered_replay': ('alerting_webhook_undelivered', 'ALERTING_WEBHOOK_UNDELIVERED_REPLAY'),
109
+ 'alerting_webhook_update': ('alerting_webhook', 'ALERTING_WEBHOOK_UPDATE'),
110
+ 'announcement_list': ('announcement', 'ANNOUNCEMENT_LIST'),
111
+ 'announcement_mark_all_read': ('announcement', 'ANNOUNCEMENT_MARK_ALL_READ'),
112
+ 'announcement_mark_read': ('announcement', 'ANNOUNCEMENT_MARK_READ'),
113
+ 'announcement_mark_unread': ('announcement', 'ANNOUNCEMENT_MARK_UNREAD'),
114
+ 'api_key_create': ('api_key', 'API_KEY_CREATE'),
115
+ 'api_key_get': ('api_key', 'API_KEY_GET'),
116
+ 'api_key_list': ('api_key', 'API_KEY_LIST'),
117
+ 'api_key_project_add': ('api_key_project', 'API_KEY_PROJECT_ADD'),
118
+ 'api_key_project_bi_connection': ('api_key_project', 'API_KEY_PROJECT_BI_CONNECTION'),
119
+ 'api_key_project_remove': ('api_key_project', 'API_KEY_PROJECT_REMOVE'),
120
+ 'api_key_revoke': ('api_key', 'API_KEY_REVOKE'),
121
+ 'api_key_rotate': ('api_key', 'API_KEY_ROTATE'),
122
+ 'backfill_reason_code_list': ('backfill_reason_code', 'BACKFILL_REASON_CODE_LIST'),
123
+ 'backfill_run_cancel': ('backfill_run', 'BACKFILL_RUN_CANCEL'),
124
+ 'backfill_run_create': ('backfill_run', 'BACKFILL_RUN_CREATE'),
125
+ 'backfill_run_get': ('backfill_run', 'BACKFILL_RUN_GET'),
126
+ 'backfill_run_list': ('backfill_run', 'BACKFILL_RUN_LIST'),
127
+ 'canvas_activate': ('canvas', 'CANVAS_ACTIVATE'),
128
+ 'canvas_graph_get': ('canvas_graph', 'CANVAS_GRAPH_GET'),
129
+ 'canvas_graph_put': ('canvas_graph', 'CANVAS_GRAPH_PUT'),
130
+ 'canvas_list': ('canvas', 'CANVAS_LIST'),
131
+ 'canvas_table_check_get': ('canvas_table_check', 'CANVAS_TABLE_CHECK_GET'),
132
+ 'canvas_table_check_start': ('canvas_table_check', 'CANVAS_TABLE_CHECK_START'),
133
+ 'canvas_volumes': ('canvas', 'CANVAS_VOLUMES'),
134
+ 'dashboards_card_create': ('dashboards_card', 'DASHBOARDS_CARD_CREATE'),
135
+ 'dashboards_card_delete': ('dashboards_card', 'DASHBOARDS_CARD_DELETE'),
136
+ 'dashboards_card_get': ('dashboards_card', 'DASHBOARDS_CARD_GET'),
137
+ 'dashboards_card_list': ('dashboards_card', 'DASHBOARDS_CARD_LIST'),
138
+ 'dashboards_card_preview': ('dashboards_card', 'DASHBOARDS_CARD_PREVIEW'),
139
+ 'dashboards_card_run': ('dashboards_card', 'DASHBOARDS_CARD_RUN'),
140
+ 'dashboards_card_update': ('dashboards_card', 'DASHBOARDS_CARD_UPDATE'),
141
+ 'dashboards_create': ('dashboards', 'DASHBOARDS_CREATE'),
142
+ 'dashboards_dataset_list': ('dashboards_dataset', 'DASHBOARDS_DATASET_LIST'),
143
+ 'dashboards_delete': ('dashboards', 'DASHBOARDS_DELETE'),
144
+ 'dashboards_duplicate': ('dashboards', 'DASHBOARDS_DUPLICATE'),
145
+ 'dashboards_folder_create': ('dashboards_folder', 'DASHBOARDS_FOLDER_CREATE'),
146
+ 'dashboards_folder_delete': ('dashboards_folder', 'DASHBOARDS_FOLDER_DELETE'),
147
+ 'dashboards_folder_update': ('dashboards_folder', 'DASHBOARDS_FOLDER_UPDATE'),
148
+ 'dashboards_get': ('dashboards', 'DASHBOARDS_GET'),
149
+ 'dashboards_home_get': ('dashboards_home', 'DASHBOARDS_HOME_GET'),
150
+ 'dashboards_home_pin': ('dashboards_home', 'DASHBOARDS_HOME_PIN'),
151
+ 'dashboards_home_pin_many': ('dashboards_home', 'DASHBOARDS_HOME_PIN_MANY'),
152
+ 'dashboards_home_set': ('dashboards_home', 'DASHBOARDS_HOME_SET'),
153
+ 'dashboards_list': ('dashboards', 'DASHBOARDS_LIST'),
154
+ 'dashboards_placement_create': ('dashboards_placement', 'DASHBOARDS_PLACEMENT_CREATE'),
155
+ 'dashboards_placement_delete': ('dashboards_placement', 'DASHBOARDS_PLACEMENT_DELETE'),
156
+ 'dashboards_placement_run': ('dashboards_placement', 'DASHBOARDS_PLACEMENT_RUN'),
157
+ 'dashboards_replace': ('dashboards', 'DASHBOARDS_REPLACE'),
158
+ 'dashboards_run': ('dashboards', 'DASHBOARDS_RUN'),
159
+ 'dashboards_update': ('dashboards', 'DASHBOARDS_UPDATE'),
160
+ 'db_column_list': ('db_column', 'DB_COLUMN_LIST'),
161
+ 'db_create': ('db', 'DB_CREATE'),
162
+ 'db_delete': ('db', 'DB_DELETE'),
163
+ 'db_get': ('db', 'DB_GET'),
164
+ 'db_get_by_name': ('db', 'DB_GET_BY_NAME'),
165
+ 'db_list': ('db', 'DB_LIST'),
166
+ 'db_test': ('db', 'DB_TEST'),
167
+ 'docs_article_get': ('docs_article', 'DOCS_ARTICLE_GET'),
168
+ 'docs_article_list': ('docs_article', 'DOCS_ARTICLE_LIST'),
169
+ 'docs_article_search': ('docs_article', 'DOCS_ARTICLE_SEARCH'),
170
+ 'dq_result_list': ('dq_result', 'DQ_RESULT_LIST'),
171
+ 'dq_rule_create': ('dq_rule', 'DQ_RULE_CREATE'),
172
+ 'dq_rule_dag': ('dq_rule', 'DQ_RULE_DAG'),
173
+ 'dq_rule_list': ('dq_rule', 'DQ_RULE_LIST'),
174
+ 'feature_list': ('feature', 'FEATURE_LIST'),
175
+ 'google_ads_source_list': ('google_ads_source', 'GOOGLE_ADS_SOURCE_LIST'),
176
+ 'google_analytics_source_list': ('google_analytics_source', 'GOOGLE_ANALYTICS_SOURCE_LIST'),
177
+ 'instagram_account_list': ('instagram_account', 'INSTAGRAM_ACCOUNT_LIST'),
178
+ 'instagram_source_list': ('instagram_source', 'INSTAGRAM_SOURCE_LIST'),
179
+ 'linkedin_account_list': ('linkedin_account', 'LINKEDIN_ACCOUNT_LIST'),
180
+ 'linkedin_source_list': ('linkedin_source', 'LINKEDIN_SOURCE_LIST'),
181
+ 'me_get': ('me', 'ME_GET'),
182
+ 'meta_ads_source_list': ('meta_ads_source', 'META_ADS_SOURCE_LIST'),
183
+ 'metric_models_changes': ('metric_models', 'METRIC_MODELS_CHANGES'),
184
+ 'metric_models_import_dbt': ('metric_models', 'METRIC_MODELS_IMPORT_DBT'),
185
+ 'metric_models_list': ('metric_models', 'METRIC_MODELS_LIST'),
186
+ 'metric_models_metric_add': ('metric_models', 'METRIC_MODELS_METRIC_ADD'),
187
+ 'metric_models_metric_list': ('metric_models', 'METRIC_MODELS_METRIC_LIST'),
188
+ 'metric_models_metric_remove': ('metric_models', 'METRIC_MODELS_METRIC_REMOVE'),
189
+ 'metric_models_metric_update': ('metric_models', 'METRIC_MODELS_METRIC_UPDATE'),
190
+ 'metric_models_publish': ('metric_models', 'METRIC_MODELS_PUBLISH'),
191
+ 'metric_models_push': ('metric_models', 'METRIC_MODELS_PUSH'),
192
+ 'metric_models_set_breakdowns': ('metric_models', 'METRIC_MODELS_SET_BREAKDOWNS'),
193
+ 'metric_models_show_draft': ('metric_models', 'METRIC_MODELS_SHOW_DRAFT'),
194
+ 'metric_models_show_published': ('metric_models', 'METRIC_MODELS_SHOW_PUBLISHED'),
195
+ 'metric_models_validate': ('metric_models', 'METRIC_MODELS_VALIDATE'),
196
+ 'metrics_describe': ('metrics', 'METRICS_DESCRIBE'),
197
+ 'metrics_list': ('metrics', 'METRICS_LIST'),
198
+ 'metrics_query': ('metrics', 'METRICS_QUERY'),
199
+ 'models_check': ('models', 'MODELS_CHECK'),
200
+ 'models_sync': ('models', 'MODELS_SYNC'),
201
+ 'models_sync_status': ('models', 'MODELS_SYNC_STATUS'),
202
+ 'nlq_ask': ('nlq', 'NLQ_ASK'),
203
+ 'nlq_usage': ('nlq', 'NLQ_USAGE'),
204
+ 'notebook_credential_get_binding': ('notebook_credential', 'NOTEBOOK_CREDENTIAL_GET_BINDING'),
205
+ 'notebook_credential_issue': ('notebook_credential', 'NOTEBOOK_CREDENTIAL_ISSUE'),
206
+ 'notebook_credential_renew': ('notebook_credential', 'NOTEBOOK_CREDENTIAL_RENEW'),
207
+ 'org_list': ('org', 'ORG_LIST'),
208
+ 'org_member_add': ('org_member', 'ORG_MEMBER_ADD'),
209
+ 'org_member_list': ('org_member', 'ORG_MEMBER_LIST'),
210
+ 'org_member_remove': ('org_member', 'ORG_MEMBER_REMOVE'),
211
+ 'org_member_set_role': ('org_member', 'ORG_MEMBER_SET_ROLE'),
212
+ 'org_offboarding_get': ('org_offboarding', 'ORG_OFFBOARDING_GET'),
213
+ 'org_switch': ('org', 'ORG_SWITCH'),
214
+ 'pipe_backfill_run_list': ('pipe_backfill_run', 'PIPE_BACKFILL_RUN_LIST'),
215
+ 'pipe_config_option_get': ('pipe_config_option', 'PIPE_CONFIG_OPTION_GET'),
216
+ 'pipe_create': ('pipe', 'PIPE_CREATE'),
217
+ 'pipe_delete': ('pipe', 'PIPE_DELETE'),
218
+ 'pipe_destination_check': ('pipe_destination', 'PIPE_DESTINATION_CHECK'),
219
+ 'pipe_destination_get': ('pipe_destination', 'PIPE_DESTINATION_GET'),
220
+ 'pipe_destination_preview': ('pipe_destination', 'PIPE_DESTINATION_PREVIEW'),
221
+ 'pipe_get': ('pipe', 'PIPE_GET'),
222
+ 'pipe_leftover_check': ('pipe_leftover', 'PIPE_LEFTOVER_CHECK'),
223
+ 'pipe_leftover_dismiss': ('pipe_leftover', 'PIPE_LEFTOVER_DISMISS'),
224
+ 'pipe_leftover_list': ('pipe_leftover', 'PIPE_LEFTOVER_LIST'),
225
+ 'pipe_list': ('pipe', 'PIPE_LIST'),
226
+ 'pipe_move': ('pipe', 'PIPE_MOVE'),
227
+ 'pipe_pause': ('pipe', 'PIPE_PAUSE'),
228
+ 'pipe_rebuild': ('pipe', 'PIPE_REBUILD'),
229
+ 'pipe_restart': ('pipe', 'PIPE_RESTART'),
230
+ 'pipe_resume': ('pipe', 'PIPE_RESUME'),
231
+ 'pipe_retry': ('pipe', 'PIPE_RETRY'),
232
+ 'pipe_rollup': ('pipe', 'PIPE_ROLLUP'),
233
+ 'pipe_sink_type_list': ('pipe_sink_type', 'PIPE_SINK_TYPE_LIST'),
234
+ 'pipe_source_type_list': ('pipe_source_type', 'PIPE_SOURCE_TYPE_LIST'),
235
+ 'pipe_status': ('pipe', 'PIPE_STATUS'),
236
+ 'pipe_status_bucket_list': ('pipe_status_bucket', 'PIPE_STATUS_BUCKET_LIST'),
237
+ 'pipe_stuck_delete_list': ('pipe_stuck_delete', 'PIPE_STUCK_DELETE_LIST'),
238
+ 'pipe_update': ('pipe', 'PIPE_UPDATE'),
239
+ 'plan_list': ('plan', 'PLAN_LIST'),
240
+ 'project_budget_list': ('project_budget', 'PROJECT_BUDGET_LIST'),
241
+ 'project_budget_set': ('project_budget', 'PROJECT_BUDGET_SET'),
242
+ 'project_create': ('project', 'PROJECT_CREATE'),
243
+ 'project_delete': ('project', 'PROJECT_DELETE'),
244
+ 'project_delete_preview': ('project', 'PROJECT_DELETE_PREVIEW'),
245
+ 'project_delete_retry': ('project', 'PROJECT_DELETE_RETRY'),
246
+ 'project_get': ('project', 'PROJECT_GET'),
247
+ 'project_list': ('project', 'PROJECT_LIST'),
248
+ 'project_member_list': ('project_member', 'PROJECT_MEMBER_LIST'),
249
+ 'project_member_people': ('project_member', 'PROJECT_MEMBER_PEOPLE'),
250
+ 'project_member_remove': ('project_member', 'PROJECT_MEMBER_REMOVE'),
251
+ 'project_member_search': ('project_member', 'PROJECT_MEMBER_SEARCH'),
252
+ 'project_member_set': ('project_member', 'PROJECT_MEMBER_SET'),
253
+ 'project_my_access': ('project', 'PROJECT_MY_ACCESS'),
254
+ 'project_privilege_grant': ('project_privilege', 'PROJECT_PRIVILEGE_GRANT'),
255
+ 'project_privilege_list': ('project_privilege', 'PROJECT_PRIVILEGE_LIST'),
256
+ 'project_privilege_revoke': ('project_privilege', 'PROJECT_PRIVILEGE_REVOKE'),
257
+ 'project_share_create': ('project_share', 'PROJECT_SHARE_CREATE'),
258
+ 'project_share_list': ('project_share', 'PROJECT_SHARE_LIST'),
259
+ 'project_share_revoke': ('project_share', 'PROJECT_SHARE_REVOKE'),
260
+ 'project_update': ('project', 'PROJECT_UPDATE'),
261
+ 'provision_ensure_defaults': ('provision', 'PROVISION_ENSURE_DEFAULTS'),
262
+ 'provisioning_status': ('provisioning', 'PROVISIONING_STATUS'),
263
+ 'registry_get': ('registry', 'REGISTRY_GET'),
264
+ 'resource_home_transfer': ('resource_home', 'RESOURCE_HOME_TRANSFER'),
265
+ 'schema_change_apply': ('schema_change', 'SCHEMA_CHANGE_APPLY'),
266
+ 'schema_change_ignore': ('schema_change', 'SCHEMA_CHANGE_IGNORE'),
267
+ 'schema_change_list': ('schema_change', 'SCHEMA_CHANGE_LIST'),
268
+ 'schema_change_pending': ('schema_change', 'SCHEMA_CHANGE_PENDING'),
269
+ 'schema_change_state': ('schema_change', 'SCHEMA_CHANGE_STATE'),
270
+ 'schema_history_create': ('schema_history', 'SCHEMA_HISTORY_CREATE'),
271
+ 'schema_history_get': ('schema_history', 'SCHEMA_HISTORY_GET'),
272
+ 'schema_history_list': ('schema_history', 'SCHEMA_HISTORY_LIST'),
273
+ 'schema_history_summary': ('schema_history', 'SCHEMA_HISTORY_SUMMARY'),
274
+ 'schema_version_current': ('schema_version', 'SCHEMA_VERSION_CURRENT'),
275
+ 'schema_version_get': ('schema_version', 'SCHEMA_VERSION_GET'),
276
+ 'schema_version_list': ('schema_version', 'SCHEMA_VERSION_LIST'),
277
+ 'shopify_store_list': ('shopify_store', 'SHOPIFY_STORE_LIST'),
278
+ 'sink_data_type_list': ('sink_data_type', 'SINK_DATA_TYPE_LIST'),
279
+ 'source_cascade_delete': ('source', 'SOURCE_CASCADE_DELETE'),
280
+ 'source_catalog_list': ('source_catalog', 'SOURCE_CATALOG_LIST'),
281
+ 'source_catalog_setup_script': ('source_catalog', 'SOURCE_CATALOG_SETUP_SCRIPT'),
282
+ 'source_check_run_get': ('source_check_run', 'SOURCE_CHECK_RUN_GET'),
283
+ 'source_check_run_latest': ('source_check_run', 'SOURCE_CHECK_RUN_LATEST'),
284
+ 'source_check_run_start': ('source_check_run', 'SOURCE_CHECK_RUN_START'),
285
+ 'source_check_run_tables': ('source_check_run', 'SOURCE_CHECK_RUN_TABLES'),
286
+ 'source_create': ('source', 'SOURCE_CREATE'),
287
+ 'source_delete': ('source', 'SOURCE_DELETE'),
288
+ 'source_force_delete': ('source', 'SOURCE_FORCE_DELETE'),
289
+ 'source_get': ('source', 'SOURCE_GET'),
290
+ 'source_hidden_type_list': ('source_hidden_type', 'SOURCE_HIDDEN_TYPE_LIST'),
291
+ 'source_list': ('source', 'SOURCE_LIST'),
292
+ 'source_name_check': ('source_name', 'SOURCE_NAME_CHECK'),
293
+ 'source_pipe_list': ('source_pipe', 'SOURCE_PIPE_LIST'),
294
+ 'source_precheck': ('source', 'SOURCE_PRECHECK'),
295
+ 'source_publication_check': ('source_publication', 'SOURCE_PUBLICATION_CHECK'),
296
+ 'source_publication_get': ('source_publication', 'SOURCE_PUBLICATION_GET'),
297
+ 'source_publication_set': ('source_publication', 'SOURCE_PUBLICATION_SET'),
298
+ 'source_readiness_override_delete': ('source_readiness_override', 'SOURCE_READINESS_OVERRIDE_DELETE'),
299
+ 'source_readiness_override_set': ('source_readiness_override', 'SOURCE_READINESS_OVERRIDE_SET'),
300
+ 'source_recheck': ('source', 'SOURCE_RECHECK'),
301
+ 'source_renew_credentials': ('source', 'SOURCE_RENEW_CREDENTIALS'),
302
+ 'source_setup_choice_check': ('source_setup_choice', 'SOURCE_SETUP_CHOICE_CHECK'),
303
+ 'source_setup_choice_get': ('source_setup_choice', 'SOURCE_SETUP_CHOICE_GET'),
304
+ 'source_setup_choice_set': ('source_setup_choice', 'SOURCE_SETUP_CHOICE_SET'),
305
+ 'source_setup_script': ('source', 'SOURCE_SETUP_SCRIPT'),
306
+ 'source_stream_get': ('source_stream', 'SOURCE_STREAM_GET'),
307
+ 'source_stream_list': ('source_stream', 'SOURCE_STREAM_LIST'),
308
+ 'source_table_check': ('source_table', 'SOURCE_TABLE_CHECK'),
309
+ 'source_update': ('source', 'SOURCE_UPDATE'),
310
+ 'sql_execute': ('sql', 'SQL_EXECUTE'),
311
+ 'ssbi_job_create': ('ssbi_job', 'SSBI_JOB_CREATE'),
312
+ 'ssbi_job_delete': ('ssbi_job', 'SSBI_JOB_DELETE'),
313
+ 'ssbi_job_get': ('ssbi_job', 'SSBI_JOB_GET'),
314
+ 'ssbi_job_list': ('ssbi_job', 'SSBI_JOB_LIST'),
315
+ 'ssbi_job_update': ('ssbi_job', 'SSBI_JOB_UPDATE'),
316
+ 'transform_type_list': ('transform_type', 'TRANSFORM_TYPE_LIST'),
317
+ 'usage_get': ('usage', 'USAGE_GET'),
318
+ 'warehouse_access_assignment_list': ('warehouse_access_assignment', 'WAREHOUSE_ACCESS_ASSIGNMENT_LIST'),
319
+ 'warehouse_access_assignment_preview': ('warehouse_access_assignment', 'WAREHOUSE_ACCESS_ASSIGNMENT_PREVIEW'),
320
+ 'warehouse_access_assignment_set': ('warehouse_access_assignment', 'WAREHOUSE_ACCESS_ASSIGNMENT_SET'),
321
+ 'warehouse_access_role_create': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_CREATE'),
322
+ 'warehouse_access_role_delete': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_DELETE'),
323
+ 'warehouse_access_role_get_metrics': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_GET_METRICS'),
324
+ 'warehouse_access_role_list': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_LIST'),
325
+ 'warehouse_access_role_list_tables': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_LIST_TABLES'),
326
+ 'warehouse_access_role_set_metrics': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_SET_METRICS'),
327
+ 'warehouse_access_role_set_rules': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_SET_RULES'),
328
+ 'warehouse_access_role_set_scope_mode': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_SET_SCOPE_MODE'),
329
+ 'warehouse_access_role_update': ('warehouse_access_role', 'WAREHOUSE_ACCESS_ROLE_UPDATE'),
330
+ 'warehouse_access_settings_get': ('warehouse_access_settings', 'WAREHOUSE_ACCESS_SETTINGS_GET'),
331
+ 'warehouse_access_settings_get_default_role': ('warehouse_access_settings', 'WAREHOUSE_ACCESS_SETTINGS_GET_DEFAULT_ROLE'),
332
+ 'warehouse_access_settings_set': ('warehouse_access_settings', 'WAREHOUSE_ACCESS_SETTINGS_SET'),
333
+ 'warehouse_access_settings_set_default_role': ('warehouse_access_settings', 'WAREHOUSE_ACCESS_SETTINGS_SET_DEFAULT_ROLE'),
334
+ 'warehouse_create': ('warehouse', 'WAREHOUSE_CREATE'),
335
+ 'warehouse_delete': ('warehouse', 'WAREHOUSE_DELETE'),
336
+ 'warehouse_get': ('warehouse', 'WAREHOUSE_GET'),
337
+ 'warehouse_impact': ('warehouse', 'WAREHOUSE_IMPACT'),
338
+ 'warehouse_list': ('warehouse', 'WAREHOUSE_LIST'),
339
+ 'warehouse_login_create': ('warehouse_login', 'WAREHOUSE_LOGIN_CREATE'),
340
+ 'warehouse_login_delete': ('warehouse_login', 'WAREHOUSE_LOGIN_DELETE'),
341
+ 'warehouse_login_list': ('warehouse_login', 'WAREHOUSE_LOGIN_LIST'),
342
+ 'warehouse_login_list_mine': ('warehouse_login', 'WAREHOUSE_LOGIN_LIST_MINE'),
343
+ 'warehouse_login_policy': ('warehouse_login', 'WAREHOUSE_LOGIN_POLICY'),
344
+ 'warehouse_login_rotate': ('warehouse_login', 'WAREHOUSE_LOGIN_ROTATE'),
345
+ 'warehouse_login_update': ('warehouse_login', 'WAREHOUSE_LOGIN_UPDATE'),
346
+ 'warehouse_principal_disable': ('warehouse_principal', 'WAREHOUSE_PRINCIPAL_DISABLE'),
347
+ 'warehouse_principal_enable': ('warehouse_principal', 'WAREHOUSE_PRINCIPAL_ENABLE'),
348
+ 'warehouse_principal_list': ('warehouse_principal', 'WAREHOUSE_PRINCIPAL_LIST'),
349
+ 'warehouse_principal_list_project': ('warehouse_principal', 'WAREHOUSE_PRINCIPAL_LIST_PROJECT'),
350
+ 'warehouse_rename': ('warehouse', 'WAREHOUSE_RENAME'),
351
+ 'warehouse_retry': ('warehouse', 'WAREHOUSE_RETRY'),
352
+ 'warehouse_service_account_create': ('warehouse_service_account', 'WAREHOUSE_SERVICE_ACCOUNT_CREATE'),
353
+ 'warehouse_service_account_credential_create': ('warehouse_service_account_credential', 'WAREHOUSE_SERVICE_ACCOUNT_CREDENTIAL_CREATE'),
354
+ 'warehouse_service_account_credential_delete': ('warehouse_service_account_credential', 'WAREHOUSE_SERVICE_ACCOUNT_CREDENTIAL_DELETE'),
355
+ 'warehouse_service_account_credential_list': ('warehouse_service_account_credential', 'WAREHOUSE_SERVICE_ACCOUNT_CREDENTIAL_LIST'),
356
+ 'warehouse_service_account_credential_rotate': ('warehouse_service_account_credential', 'WAREHOUSE_SERVICE_ACCOUNT_CREDENTIAL_ROTATE'),
357
+ 'warehouse_service_account_credential_update': ('warehouse_service_account_credential', 'WAREHOUSE_SERVICE_ACCOUNT_CREDENTIAL_UPDATE'),
358
+ 'warehouse_service_account_delete': ('warehouse_service_account', 'WAREHOUSE_SERVICE_ACCOUNT_DELETE'),
359
+ 'warehouse_service_account_list': ('warehouse_service_account', 'WAREHOUSE_SERVICE_ACCOUNT_LIST'),
360
+ 'warehouse_service_account_update': ('warehouse_service_account', 'WAREHOUSE_SERVICE_ACCOUNT_UPDATE'),
361
+ 'warehouse_stats': ('warehouse', 'WAREHOUSE_STATS'),
362
+ }
@@ -0,0 +1,134 @@
1
+ """
2
+ The token source of a profile that signed in: ``auth = "login"`` (a person) or ``auth = "api_key"``.
3
+
4
+ The access token is read from the profile's credential with its expiry. With less than
5
+ ``refresh_margin_s`` left it is renewed under the credential's file lock, so parallel commands
6
+ renew once: a process that waited for the lock reads the store again and finds the new token.
7
+ A login renews with its refresh token, an API key with the client-credentials grant, both at the
8
+ token endpoint the credential's issuer names in its discovery document.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import time
14
+ from dataclasses import dataclass
15
+ from typing import TYPE_CHECKING
16
+
17
+ from databay import oidc
18
+ from databay.credentials import Credential, key_sub, open_store
19
+ from databay.errors import DatabayProfileError
20
+ from databay.locks import locked
21
+ from databay.profiles import login_command
22
+ from databay.settings import SETTINGS
23
+
24
+ if TYPE_CHECKING:
25
+ import httpx
26
+
27
+ from databay.credentials import TokenStore
28
+ from databay.profiles import Profile
29
+
30
+ #: OAuth errors that mean the stored credential no longer works: only a new sign-in helps.
31
+ DEAD_CREDENTIAL = frozenset({"invalid_grant", "invalid_client", "unauthorized_client"})
32
+
33
+
34
+ def login_required(profile: Profile, why: str) -> DatabayProfileError:
35
+ return DatabayProfileError(
36
+ f"profile {profile.name}: {why}; sign in again", code="login_required", next_command=login_command(profile)
37
+ )
38
+
39
+
40
+ @dataclass
41
+ class StoredToken:
42
+ profile: Profile
43
+ key: str
44
+ store: TokenStore
45
+ http: httpx.Client | None = None
46
+ #: The access token this source last handed out: a 401 on it means it, not a newer one, is refused.
47
+ sent: str | None = None
48
+ #: The access token and its expiry as last read, so a command's requests read the store once.
49
+ _held: tuple[str, float] | None = None
50
+ #: The issuer's endpoints, discovered at this source's first renewal.
51
+ _endpoints: oidc.Endpoints | None = None
52
+
53
+ def _load(self) -> Credential:
54
+ record = self.store.get(self.key)
55
+ if record is None or record.sub != key_sub(self.key) or record.kind != self.profile.auth:
56
+ raise DatabayProfileError(
57
+ f"profile {self.profile.name} names credential {self.key}, which the {self.store.kind} store "
58
+ "does not hold for that user",
59
+ code="credential_missing",
60
+ next_command=login_command(self.profile),
61
+ )
62
+ return record
63
+
64
+ def token(self) -> str:
65
+ if self._held is not None and self._held[1] - time.time() > SETTINGS.refresh_margin_s:
66
+ return self._hand_out(self._held[0], self._held[1])
67
+ record = self._load()
68
+ if record.expires_at - time.time() <= SETTINGS.refresh_margin_s:
69
+ with locked(self.key):
70
+ record = self._load()
71
+ if record.expires_at - time.time() <= SETTINGS.refresh_margin_s:
72
+ record = self._renew(record)
73
+ return self._hand_out(record.access_token, record.expires_at)
74
+
75
+ def refreshed(self) -> str | None:
76
+ with locked(self.key):
77
+ record = self._load()
78
+ if record.access_token == self.sent:
79
+ record = self._renew(record)
80
+ return self._hand_out(record.access_token, record.expires_at)
81
+
82
+ def renewed(self) -> str:
83
+ """A token issued now, whatever the current one's expiry: it carries a change the server just stored."""
84
+ with locked(self.key):
85
+ record = self._renew(self._load())
86
+ return self._hand_out(record.access_token, record.expires_at)
87
+
88
+ def _hand_out(self, token: str, expires_at: float) -> str:
89
+ self.sent = token
90
+ self._held = (token, expires_at)
91
+ return token
92
+
93
+ def _renew(self, record: Credential) -> Credential:
94
+ # Credential.from_json refuses a login without its refresh token and a key without its secret.
95
+ if record.kind == "login":
96
+ data = {"grant_type": "refresh_token", "client_id": record.client_id, "refresh_token": record.refresh_token}
97
+ else:
98
+ data = {
99
+ "grant_type": "client_credentials",
100
+ "client_id": record.client_id,
101
+ "client_secret": record.client_secret,
102
+ }
103
+ try:
104
+ if self.http is not None:
105
+ issued = self._grant(self.http, record.issuer, data)
106
+ else:
107
+ from databay.transport import new_http_client # noqa: PLC0415
108
+
109
+ with new_http_client(SETTINGS) as http:
110
+ issued = self._grant(http, record.issuer, data)
111
+ except oidc.OAuthRefusal as exc:
112
+ if exc.error in DEAD_CREDENTIAL:
113
+ why = f"the identity provider refused the stored credential ({exc.error})"
114
+ raise login_required(self.profile, why) from None
115
+ raise
116
+ renewed = record.with_tokens(issued.access_token, issued.expires_at, issued.refresh_token)
117
+ self.store.put(self.key, renewed)
118
+ return renewed
119
+
120
+ def _grant(self, http: httpx.Client, issuer: str, data: dict[str, str]) -> oidc.Grant:
121
+ if self._endpoints is None:
122
+ self._endpoints = oidc.discover(http, issuer)
123
+ return oidc.grant(http, self._endpoints.token, data)
124
+
125
+
126
+ def stored_token(profile: Profile, http: httpx.Client | None) -> StoredToken:
127
+ """The source for a signed-in profile; one without a credential is ``credential_missing``."""
128
+ if profile.credential is None or profile.token_store is None:
129
+ raise DatabayProfileError(
130
+ f"profile {profile.name} is not signed in",
131
+ code="credential_missing",
132
+ next_command=login_command(profile),
133
+ )
134
+ return StoredToken(profile, profile.credential, open_store(profile.token_store), http)
databay/tokens.py ADDED
@@ -0,0 +1,108 @@
1
+ """
2
+ Where a request's bearer token comes from.
3
+
4
+ The profile alone decides, by its ``auth``; nothing else is consulted:
5
+
6
+ - ``login``: the credential ``databay login`` stored for a person, renewed with its refresh token;
7
+ - ``api_key``: the credential ``databay login --api-key-id`` stored for an org API key, renewed
8
+ with the client-credentials grant;
9
+ - ``env``: ``$DATABAY_TOKEN``, read on every request, for a token minted elsewhere.
10
+
11
+ ``$DATABAY_TOKEN`` set while the profile's ``auth`` is ``login`` or ``api_key`` is
12
+ ``token_source_conflict``: two token sources are in play and the CLI does not pick one.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import os
18
+ from dataclasses import dataclass
19
+ from typing import TYPE_CHECKING, Protocol
20
+
21
+ from databay.errors import DatabayProfileError, DatabayUsageError
22
+ from databay.settings import ENV_TOKEN
23
+
24
+ if TYPE_CHECKING:
25
+ from collections.abc import Callable
26
+
27
+ import httpx
28
+
29
+ from databay.profiles import Profile
30
+
31
+
32
+ class TokenProvider(Protocol):
33
+ def token(self) -> str | None:
34
+ """The access token to send now; ``None`` sends no ``Authorization`` header."""
35
+ ...
36
+
37
+ def refreshed(self) -> str | None:
38
+ """A new token after the server refused the current one, or ``None`` when this source cannot refresh."""
39
+ ...
40
+
41
+
42
+ @dataclass(frozen=True, slots=True)
43
+ class EnvToken:
44
+ """The token in ``$DATABAY_TOKEN``, read on each request; unset or empty is ``token_missing``."""
45
+
46
+ variable: str = ENV_TOKEN
47
+
48
+ def token(self) -> str:
49
+ value = os.environ.get(self.variable, "")
50
+ if not value:
51
+ raise DatabayProfileError(
52
+ f"the profile reads its token from ${self.variable}, which is not set",
53
+ code="token_missing",
54
+ )
55
+ return value
56
+
57
+ def refreshed(self) -> str | None:
58
+ return None
59
+
60
+
61
+ @dataclass(frozen=True, slots=True)
62
+ class StaticToken:
63
+ """A token the SDK caller already holds."""
64
+
65
+ value: str
66
+
67
+ def token(self) -> str:
68
+ return self.value
69
+
70
+ def refreshed(self) -> str | None:
71
+ return None
72
+
73
+
74
+ @dataclass(frozen=True, slots=True)
75
+ class NoToken:
76
+ """No ``Authorization`` header: the routes a client reads before it has a token (``client-config``)."""
77
+
78
+ def token(self) -> None:
79
+ return None
80
+
81
+ def refreshed(self) -> str | None:
82
+ return None
83
+
84
+
85
+ def _stored(profile: Profile, http: httpx.Client | None) -> TokenProvider:
86
+ from databay.stored_token import stored_token # noqa: PLC0415 — loads the OAuth code only when used
87
+
88
+ return stored_token(profile, http)
89
+
90
+
91
+ #: ``auth`` value in a profile -> the token source it builds.
92
+ TOKEN_SOURCES: dict[str, Callable[[Profile, httpx.Client | None], TokenProvider]] = {
93
+ "env": lambda _profile, _http: EnvToken(),
94
+ "login": _stored,
95
+ "api_key": _stored,
96
+ }
97
+
98
+
99
+ def token_provider(profile: Profile, http: httpx.Client | None = None) -> TokenProvider:
100
+ """The profile's token source; ``http`` is the client a renewal is sent with (a new one when ``None``)."""
101
+ if profile.auth != "env" and os.environ.get(ENV_TOKEN):
102
+ raise DatabayUsageError(
103
+ f"${ENV_TOKEN} is set, but profile {profile.name} signs in with auth = {profile.auth!r}: "
104
+ f"unset {ENV_TOKEN}, or use a profile whose auth is env",
105
+ code="token_source_conflict",
106
+ details={"profile": profile.name, "auth": profile.auth},
107
+ )
108
+ return TOKEN_SOURCES[profile.auth](profile, http)