mage-ai 0.9.45__py3-none-any.whl → 0.9.46__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.

Potentially problematic release.


This version of mage-ai might be problematic. Click here for more details.

Files changed (497) hide show
  1. mage_ai/api/constants.py +2 -0
  2. mage_ai/api/operations/base.py +208 -12
  3. mage_ai/api/policies/BasePolicy.py +3 -3
  4. mage_ai/api/policies/ComputeClusterPolicy.py +96 -0
  5. mage_ai/api/policies/ComputeConnectionPolicy.py +74 -0
  6. mage_ai/api/policies/ComputeServicePolicy.py +50 -0
  7. mage_ai/api/policies/DownloadPolicy.py +29 -0
  8. mage_ai/api/policies/GlobalHookPolicy.py +126 -0
  9. mage_ai/api/policies/OauthPolicy.py +56 -4
  10. mage_ai/api/policies/ProjectPolicy.py +1 -0
  11. mage_ai/api/presenters/ComputeClusterPresenter.py +19 -0
  12. mage_ai/api/presenters/ComputeConnectionPresenter.py +26 -0
  13. mage_ai/api/presenters/ComputeServicePresenter.py +15 -0
  14. mage_ai/api/presenters/DownloadPresenter.py +13 -0
  15. mage_ai/api/presenters/GlobalHookPresenter.py +74 -0
  16. mage_ai/api/presenters/PipelinePresenter.py +1 -0
  17. mage_ai/api/presenters/ProjectPresenter.py +1 -0
  18. mage_ai/api/presenters/SparkApplicationPresenter.py +2 -0
  19. mage_ai/api/presenters/WorkspacePresenter.py +22 -22
  20. mage_ai/api/resources/AsyncBaseResource.py +39 -0
  21. mage_ai/api/resources/ClusterResource.py +1 -1
  22. mage_ai/api/resources/ComputeClusterResource.py +109 -0
  23. mage_ai/api/resources/ComputeConnectionResource.py +103 -0
  24. mage_ai/api/resources/ComputeServiceResource.py +35 -0
  25. mage_ai/api/resources/DownloadResource.py +56 -0
  26. mage_ai/api/resources/ExecutionStateResource.py +1 -1
  27. mage_ai/api/resources/GlobalHookResource.py +192 -0
  28. mage_ai/api/resources/KernelResource.py +10 -0
  29. mage_ai/api/resources/OauthResource.py +28 -33
  30. mage_ai/api/resources/PipelineResource.py +4 -4
  31. mage_ai/api/resources/PipelineScheduleResource.py +37 -16
  32. mage_ai/api/resources/ProjectResource.py +5 -3
  33. mage_ai/api/resources/SessionResource.py +0 -9
  34. mage_ai/api/resources/SparkApplicationResource.py +5 -5
  35. mage_ai/api/resources/SparkEnvironmentResource.py +1 -2
  36. mage_ai/api/resources/SparkExecutorResource.py +1 -2
  37. mage_ai/api/resources/SparkJobResource.py +3 -6
  38. mage_ai/api/resources/SparkSqlResource.py +6 -11
  39. mage_ai/api/resources/SparkStageAttemptResource.py +2 -3
  40. mage_ai/api/resources/SparkStageAttemptTaskResource.py +1 -2
  41. mage_ai/api/resources/SparkStageAttemptTaskSummaryResource.py +1 -2
  42. mage_ai/api/resources/SparkStageResource.py +3 -6
  43. mage_ai/api/resources/SparkThreadResource.py +1 -2
  44. mage_ai/api/resources/mixins/spark.py +25 -4
  45. mage_ai/authentication/oauth2.py +1 -3
  46. mage_ai/authentication/permissions/constants.py +4 -0
  47. mage_ai/authentication/providers/active_directory.py +136 -0
  48. mage_ai/authentication/providers/constants.py +3 -0
  49. mage_ai/authentication/providers/ghe.py +24 -25
  50. mage_ai/authentication/providers/google.py +25 -26
  51. mage_ai/authentication/providers/oauth.py +2 -2
  52. mage_ai/authentication/providers/okta.py +28 -29
  53. mage_ai/authentication/providers/sso.py +2 -2
  54. mage_ai/cluster_manager/aws/emr_cluster_manager.py +2 -1
  55. mage_ai/cluster_manager/workspace/base.py +7 -3
  56. mage_ai/data_integrations/destinations/constants.py +1 -0
  57. mage_ai/data_preparation/executors/pipeline_executor.py +9 -0
  58. mage_ai/data_preparation/models/block/__init__.py +57 -5
  59. mage_ai/data_preparation/models/block/data_integration/data.py +1 -1
  60. mage_ai/data_preparation/models/block/spark/mixins.py +82 -34
  61. mage_ai/data_preparation/models/download/__init__.py +8 -0
  62. mage_ai/data_preparation/models/global_hooks/__init__.py +0 -0
  63. mage_ai/data_preparation/models/global_hooks/constants.py +44 -0
  64. mage_ai/data_preparation/models/global_hooks/models.py +928 -0
  65. mage_ai/data_preparation/models/global_hooks/utils.py +21 -0
  66. mage_ai/data_preparation/models/pipeline.py +82 -6
  67. mage_ai/data_preparation/models/pipelines/models.py +16 -0
  68. mage_ai/data_preparation/models/project/__init__.py +6 -0
  69. mage_ai/data_preparation/models/project/constants.py +1 -0
  70. mage_ai/data_preparation/models/project/models.py +12 -0
  71. mage_ai/data_preparation/repo_manager.py +23 -1
  72. mage_ai/data_preparation/templates/data_loaders/streaming/activemq.yaml +6 -0
  73. mage_ai/data_preparation/templates/data_loaders/streaming/nats.yaml +20 -0
  74. mage_ai/orchestration/db/models/schedules.py +2 -2
  75. mage_ai/orchestration/queue/process_queue.py +9 -1
  76. mage_ai/orchestration/triggers/api.py +11 -3
  77. mage_ai/orchestration/triggers/constants.py +1 -0
  78. mage_ai/server/active_kernel.py +37 -4
  79. mage_ai/server/api/downloads.py +76 -1
  80. mage_ai/server/constants.py +1 -1
  81. mage_ai/server/frontend_dist/404.html +2 -2
  82. mage_ai/server/frontend_dist/_next/static/9jB4XPuz6BzxBcG9VNao5/_buildManifest.js +1 -0
  83. mage_ai/server/frontend_dist/_next/static/chunks/1749-9a6276b2918fdae1.js +1 -0
  84. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/7519-8c29bbb92e03cc77.js → frontend_dist/_next/static/chunks/1845-5ce774d5ab81ed57.js} +1 -1
  85. mage_ai/server/frontend_dist/_next/static/chunks/1952-ac7722e8b1ab88fe.js +1 -0
  86. mage_ai/server/frontend_dist/_next/static/chunks/3419-f8d518d024e7b5c8.js +1 -0
  87. mage_ai/server/frontend_dist/_next/static/chunks/4267-fd4d8049e83178de.js +1 -0
  88. mage_ai/server/frontend_dist/_next/static/chunks/4366-93e09e5a4a7e182c.js +1 -0
  89. mage_ai/server/frontend_dist/_next/static/chunks/5457-949640f4037bf12f.js +1 -0
  90. mage_ai/server/frontend_dist/_next/static/chunks/5499-76cf8f023c6b0985.js +1 -0
  91. mage_ai/server/frontend_dist/_next/static/chunks/553-7f7919e14392ca67.js +1 -0
  92. mage_ai/server/frontend_dist/_next/static/chunks/5638-a65610405a70961c.js +1 -0
  93. mage_ai/server/frontend_dist/_next/static/chunks/5810-12eadc488265d55b.js +1 -0
  94. mage_ai/server/frontend_dist/_next/static/chunks/5820-28adeabb5cda2b96.js +1 -0
  95. mage_ai/server/frontend_dist/_next/static/chunks/595-0d174b1f9fbfce4f.js +1 -0
  96. mage_ai/server/frontend_dist/_next/static/chunks/600-705fe234320ec5de.js +1 -0
  97. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/3122-f27de34d0b5426af.js → frontend_dist/_next/static/chunks/6285-e9b45335bfb9ccaf.js} +1 -1
  98. mage_ai/server/frontend_dist/_next/static/chunks/6333-bc1b433b428a9095.js +1 -0
  99. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/5397-b5f2e477acc6bd6b.js → frontend_dist/_next/static/chunks/6965-c613d1834c8ed92d.js} +1 -1
  100. mage_ai/server/frontend_dist/_next/static/chunks/{7022-18fde36eb46e1d65.js → 7022-070ec0144a4d029c.js} +1 -1
  101. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/722-2a171fe616310f60.js → frontend_dist/_next/static/chunks/722-a1584445357a276c.js} +1 -1
  102. mage_ai/server/frontend_dist/_next/static/chunks/{7858-c83d25349d0e980f.js → 7858-d9df72e95e438284.js} +1 -1
  103. mage_ai/server/frontend_dist/_next/static/chunks/8264-0d582a6ca33c3dfa.js +1 -0
  104. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/3684-cbda680fd8927d07.js → frontend_dist/_next/static/chunks/8432-f191e39f9b5893f2.js} +1 -1
  105. mage_ai/server/frontend_dist/_next/static/chunks/90-a7308bae028d7001.js +1 -0
  106. mage_ai/server/frontend_dist/_next/static/chunks/9264-1d4f0327d42fed91.js +1 -0
  107. mage_ai/server/frontend_dist/_next/static/chunks/9618-2c5045255ac5a6e7.js +1 -0
  108. mage_ai/server/frontend_dist/_next/static/chunks/framework-22b71764bf44ede4.js +1 -0
  109. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-ebef928183f9a3bb.js +1 -0
  110. mage_ai/server/frontend_dist/_next/static/chunks/pages/block-layout-a24cb24b6f08bbc9.js +1 -0
  111. mage_ai/server/frontend_dist/_next/static/chunks/pages/compute-419775ca1293b354.js +1 -0
  112. mage_ai/server/frontend_dist/_next/static/chunks/pages/files-0f2d4be6fdca86ca.js +1 -0
  113. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/{[...slug]-3f6fc312f67ff72e.js → [...slug]-cfd68e760ae00958.js} +1 -1
  114. mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-data-products-f4cd03036c3e8723.js → global-data-products-c3b79ef31007f95b.js} +1 -1
  115. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-77edfa32d000e88b.js +1 -0
  116. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks-e561ae38cf5592e8.js +1 -0
  117. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/files-449a022f2f0f2d94.js +1 -0
  118. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/settings-60845f0b59142f32.js +1 -0
  119. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/[user]-1d9b298fdceabbf1.js → frontend_dist/_next/static/chunks/pages/manage/users/[user]-9384c5f1efa2ac18.js} +1 -1
  120. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/new-abd8571907664fdf.js +1 -0
  121. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{users-a7c970122a10afdc.js → users-28a930b148d99766.js} +1 -1
  122. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-f83deb790548693b.js +1 -0
  123. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/overview-a4647a274cf4dffa.js → frontend_dist/_next/static/chunks/pages/overview-f0c40645f385f23f.js} +1 -1
  124. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-c79819d6826e5416.js → frontend_dist/_next/static/chunks/pages/pipeline-runs-b35d37bfba8fbccc.js} +1 -1
  125. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-b4c0a36c69c346a4.js → [...slug]-10e9a2d19541caa2.js} +1 -1
  126. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c8d3a5289ab93f88.js +1 -0
  127. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-571c0962333b92f0.js +1 -0
  128. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-ff7e9108502f5716.js +1 -0
  129. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{logs-a52d2d3e0c2978f4.js → logs-ef680455ae54ccbe.js} +1 -1
  130. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-ddddcddd2f74b4f6.js +1 -0
  131. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-4a238307feddb522.js +1 -0
  132. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e051057d9fe94f23.js +1 -0
  133. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-b0a508aa52914dad.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-0691711636fa95c7.js} +1 -1
  134. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-ce717786f31e8f04.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-2d20b2cd08907afd.js} +1 -1
  135. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-2914e326a5f1ffe0.js +1 -0
  136. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-b75bf17498e87354.js +1 -0
  137. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-3a7500e6e53084d3.js +1 -0
  138. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-95394769a783c6c7.js → triggers-c0e551d265a8d467.js} +1 -1
  139. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/{[pipeline]-35fe7762cb83a733.js → [pipeline]-02c843b9c8418bb5.js} +1 -1
  140. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-e47db5c3eaf683af.js +1 -0
  141. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-55ac955dfa9a5a8d.js +1 -0
  142. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-d6a62284c7c99cb3.js → [...slug]-b78b1be5b9ed84b9.js} +1 -1
  143. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{permissions-b1389695f758c32b.js → permissions-37b78a436eeab258.js} +1 -1
  144. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-29c92a9bc54ae5cd.js +1 -0
  145. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-0bdb66265286ab22.js → [...slug]-db05a80d18c168e5.js} +1 -1
  146. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{roles-e04e18fc295ca76a.js → roles-f55c77e4f46c8d33.js} +1 -1
  147. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-2a1f8737561fdd94.js +1 -0
  148. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/{[...slug]-0267358c91122109.js → [...slug]-e3bf6e5d8bb250c4.js} +1 -1
  149. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{users-50fed18bb9b8d142.js → users-20f0a050a42a015d.js} +1 -1
  150. mage_ai/server/frontend_dist/_next/static/chunks/pages/{settings-56f83205752b1323.js → settings-0f0121db7f5ff93d.js} +1 -1
  151. mage_ai/server/frontend_dist/_next/static/chunks/pages/sign-in-99e2748e3c1d57a3.js +1 -0
  152. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/templates/[...slug]-9370551ffa462144.js → frontend_dist/_next/static/chunks/pages/templates/[...slug]-f44ccd1499ffd23a.js} +1 -1
  153. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/templates-3cff90df13a1a755.js → frontend_dist/_next/static/chunks/pages/templates-1bfaa1c50e844813.js} +1 -1
  154. mage_ai/server/frontend_dist/_next/static/chunks/pages/terminal-ed121e305169cf1c.js +1 -0
  155. mage_ai/server/frontend_dist/_next/static/chunks/pages/test-9ae68758102cc843.js +1 -0
  156. mage_ai/server/frontend_dist/_next/static/chunks/pages/{triggers-ffaab4c013e62ba1.js → triggers-572d82d6eb7a5d43.js} +1 -1
  157. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-2d26d80370a2e481.js +1 -0
  158. mage_ai/server/frontend_dist/_next/static/chunks/{webpack-8af2b89c5a3779fc.js → webpack-fea697dd168c6d0c.js} +1 -1
  159. mage_ai/server/frontend_dist/block-layout.html +2 -2
  160. mage_ai/server/frontend_dist/compute.html +2 -2
  161. mage_ai/server/frontend_dist/files.html +2 -2
  162. mage_ai/server/frontend_dist/global-data-products/[...slug].html +2 -2
  163. mage_ai/server/frontend_dist/global-data-products.html +2 -2
  164. mage_ai/server/frontend_dist/global-hooks/[...slug].html +24 -0
  165. mage_ai/server/frontend_dist/global-hooks.html +24 -0
  166. mage_ai/server/frontend_dist/index.html +2 -2
  167. mage_ai/server/frontend_dist/manage/files.html +2 -2
  168. mage_ai/server/frontend_dist/manage/settings.html +2 -2
  169. mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
  170. mage_ai/server/frontend_dist/manage/users/new.html +2 -2
  171. mage_ai/server/frontend_dist/manage/users.html +2 -2
  172. mage_ai/server/frontend_dist/manage.html +2 -2
  173. mage_ai/server/frontend_dist/oauth.html +3 -3
  174. mage_ai/server/frontend_dist/overview.html +2 -2
  175. mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
  176. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  177. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
  178. mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +2 -2
  179. mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
  180. mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
  181. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  182. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  183. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
  184. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
  185. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
  186. mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
  187. mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
  188. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  189. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
  190. mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
  191. mage_ai/server/frontend_dist/pipelines.html +2 -2
  192. mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
  193. mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +2 -2
  194. mage_ai/server/frontend_dist/settings/workspace/permissions.html +2 -2
  195. mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
  196. mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +2 -2
  197. mage_ai/server/frontend_dist/settings/workspace/roles.html +2 -2
  198. mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
  199. mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +2 -2
  200. mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
  201. mage_ai/server/frontend_dist/settings.html +2 -2
  202. mage_ai/server/frontend_dist/sign-in.html +10 -11
  203. mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
  204. mage_ai/server/frontend_dist/templates.html +2 -2
  205. mage_ai/server/frontend_dist/terminal.html +2 -2
  206. mage_ai/server/frontend_dist/test.html +14 -14
  207. mage_ai/server/frontend_dist/triggers.html +2 -2
  208. mage_ai/server/frontend_dist/version-control.html +2 -2
  209. mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
  210. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1749-9a6276b2918fdae1.js +1 -0
  211. mage_ai/server/{frontend_dist/_next/static/chunks/7519-8c29bbb92e03cc77.js → frontend_dist_base_path_template/_next/static/chunks/1845-5ce774d5ab81ed57.js} +1 -1
  212. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1952-ac7722e8b1ab88fe.js +1 -0
  213. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3419-f8d518d024e7b5c8.js +1 -0
  214. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4267-fd4d8049e83178de.js +1 -0
  215. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4366-93e09e5a4a7e182c.js +1 -0
  216. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5457-949640f4037bf12f.js +1 -0
  217. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5499-76cf8f023c6b0985.js +1 -0
  218. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/553-7f7919e14392ca67.js +1 -0
  219. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5638-a65610405a70961c.js +1 -0
  220. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5810-12eadc488265d55b.js +1 -0
  221. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5820-28adeabb5cda2b96.js +1 -0
  222. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/595-0d174b1f9fbfce4f.js +1 -0
  223. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/600-705fe234320ec5de.js +1 -0
  224. mage_ai/server/{frontend_dist/_next/static/chunks/3122-f27de34d0b5426af.js → frontend_dist_base_path_template/_next/static/chunks/6285-e9b45335bfb9ccaf.js} +1 -1
  225. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6333-bc1b433b428a9095.js +1 -0
  226. mage_ai/server/{frontend_dist/_next/static/chunks/5397-b5f2e477acc6bd6b.js → frontend_dist_base_path_template/_next/static/chunks/6965-c613d1834c8ed92d.js} +1 -1
  227. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{7022-18fde36eb46e1d65.js → 7022-070ec0144a4d029c.js} +1 -1
  228. mage_ai/server/{frontend_dist/_next/static/chunks/722-2a171fe616310f60.js → frontend_dist_base_path_template/_next/static/chunks/722-a1584445357a276c.js} +1 -1
  229. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{7858-c83d25349d0e980f.js → 7858-d9df72e95e438284.js} +1 -1
  230. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8264-0d582a6ca33c3dfa.js +1 -0
  231. mage_ai/server/{frontend_dist/_next/static/chunks/3684-cbda680fd8927d07.js → frontend_dist_base_path_template/_next/static/chunks/8432-f191e39f9b5893f2.js} +1 -1
  232. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/90-a7308bae028d7001.js +1 -0
  233. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-1d4f0327d42fed91.js +1 -0
  234. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9618-2c5045255ac5a6e7.js +1 -0
  235. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/framework-22b71764bf44ede4.js +1 -0
  236. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-ebef928183f9a3bb.js +1 -0
  237. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/block-layout-a24cb24b6f08bbc9.js +1 -0
  238. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/compute-419775ca1293b354.js +1 -0
  239. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-0f2d4be6fdca86ca.js +1 -0
  240. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/{[...slug]-3f6fc312f67ff72e.js → [...slug]-cfd68e760ae00958.js} +1 -1
  241. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-data-products-f4cd03036c3e8723.js → global-data-products-c3b79ef31007f95b.js} +1 -1
  242. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-77edfa32d000e88b.js +1 -0
  243. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks-e561ae38cf5592e8.js +1 -0
  244. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/files-449a022f2f0f2d94.js +1 -0
  245. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/settings-60845f0b59142f32.js +1 -0
  246. mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage/users/[user]-1d9b298fdceabbf1.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/[user]-9384c5f1efa2ac18.js} +1 -1
  247. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-abd8571907664fdf.js +1 -0
  248. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{users-a7c970122a10afdc.js → users-28a930b148d99766.js} +1 -1
  249. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-f83deb790548693b.js +1 -0
  250. mage_ai/server/{frontend_dist/_next/static/chunks/pages/overview-a4647a274cf4dffa.js → frontend_dist_base_path_template/_next/static/chunks/pages/overview-f0c40645f385f23f.js} +1 -1
  251. mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipeline-runs-c79819d6826e5416.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-b35d37bfba8fbccc.js} +1 -1
  252. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-b4c0a36c69c346a4.js → [...slug]-10e9a2d19541caa2.js} +1 -1
  253. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c8d3a5289ab93f88.js +1 -0
  254. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-571c0962333b92f0.js +1 -0
  255. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-ff7e9108502f5716.js +1 -0
  256. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{logs-a52d2d3e0c2978f4.js → logs-ef680455ae54ccbe.js} +1 -1
  257. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-ddddcddd2f74b4f6.js +1 -0
  258. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-4a238307feddb522.js +1 -0
  259. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e051057d9fe94f23.js +1 -0
  260. mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-b0a508aa52914dad.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-0691711636fa95c7.js} +1 -1
  261. mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-ce717786f31e8f04.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-2d20b2cd08907afd.js} +1 -1
  262. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-2914e326a5f1ffe0.js +1 -0
  263. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-b75bf17498e87354.js +1 -0
  264. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-3a7500e6e53084d3.js +1 -0
  265. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-95394769a783c6c7.js → triggers-c0e551d265a8d467.js} +1 -1
  266. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/{[pipeline]-35fe7762cb83a733.js → [pipeline]-02c843b9c8418bb5.js} +1 -1
  267. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-e47db5c3eaf683af.js +1 -0
  268. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-55ac955dfa9a5a8d.js +1 -0
  269. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-d6a62284c7c99cb3.js → [...slug]-b78b1be5b9ed84b9.js} +1 -1
  270. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{permissions-b1389695f758c32b.js → permissions-37b78a436eeab258.js} +1 -1
  271. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-29c92a9bc54ae5cd.js +1 -0
  272. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-0bdb66265286ab22.js → [...slug]-db05a80d18c168e5.js} +1 -1
  273. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{roles-e04e18fc295ca76a.js → roles-f55c77e4f46c8d33.js} +1 -1
  274. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-2a1f8737561fdd94.js +1 -0
  275. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/{[...slug]-0267358c91122109.js → [...slug]-e3bf6e5d8bb250c4.js} +1 -1
  276. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{users-50fed18bb9b8d142.js → users-20f0a050a42a015d.js} +1 -1
  277. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{settings-56f83205752b1323.js → settings-0f0121db7f5ff93d.js} +1 -1
  278. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-99e2748e3c1d57a3.js +1 -0
  279. mage_ai/server/{frontend_dist/_next/static/chunks/pages/templates/[...slug]-9370551ffa462144.js → frontend_dist_base_path_template/_next/static/chunks/pages/templates/[...slug]-f44ccd1499ffd23a.js} +1 -1
  280. mage_ai/server/{frontend_dist/_next/static/chunks/pages/templates-3cff90df13a1a755.js → frontend_dist_base_path_template/_next/static/chunks/pages/templates-1bfaa1c50e844813.js} +1 -1
  281. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/terminal-ed121e305169cf1c.js +1 -0
  282. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/test-9ae68758102cc843.js +1 -0
  283. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{triggers-ffaab4c013e62ba1.js → triggers-572d82d6eb7a5d43.js} +1 -1
  284. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-2d26d80370a2e481.js +1 -0
  285. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-074f3eb2281fba79.js → webpack-d30cb09c85b4c4f0.js} +1 -1
  286. mage_ai/server/frontend_dist_base_path_template/_next/static/uPDjJYpJMst1q6psbRyte/_buildManifest.js +1 -0
  287. mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
  288. mage_ai/server/frontend_dist_base_path_template/compute.html +5 -5
  289. mage_ai/server/frontend_dist_base_path_template/files.html +5 -5
  290. mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +5 -5
  291. mage_ai/server/frontend_dist_base_path_template/global-data-products.html +5 -5
  292. mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +24 -0
  293. mage_ai/server/frontend_dist_base_path_template/global-hooks.html +24 -0
  294. mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
  295. mage_ai/server/frontend_dist_base_path_template/manage/files.html +5 -5
  296. mage_ai/server/frontend_dist_base_path_template/manage/settings.html +5 -5
  297. mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +5 -5
  298. mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +5 -5
  299. mage_ai/server/frontend_dist_base_path_template/manage/users.html +5 -5
  300. mage_ai/server/frontend_dist_base_path_template/manage.html +5 -5
  301. mage_ai/server/frontend_dist_base_path_template/oauth.html +4 -4
  302. mage_ai/server/frontend_dist_base_path_template/overview.html +5 -5
  303. mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +5 -5
  304. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +5 -5
  305. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +5 -5
  306. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +5 -5
  307. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
  308. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +5 -5
  309. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +5 -5
  310. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +5 -5
  311. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +5 -5
  312. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +5 -5
  313. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +5 -5
  314. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +5 -5
  315. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +5 -5
  316. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +5 -5
  317. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +5 -5
  318. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
  319. mage_ai/server/frontend_dist_base_path_template/pipelines.html +5 -5
  320. mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +5 -5
  321. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +5 -5
  322. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +5 -5
  323. mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +5 -5
  324. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +5 -5
  325. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +5 -5
  326. mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +5 -5
  327. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +5 -5
  328. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +5 -5
  329. mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
  330. mage_ai/server/frontend_dist_base_path_template/sign-in.html +18 -19
  331. mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +5 -5
  332. mage_ai/server/frontend_dist_base_path_template/templates.html +5 -5
  333. mage_ai/server/frontend_dist_base_path_template/terminal.html +5 -5
  334. mage_ai/server/frontend_dist_base_path_template/test.html +15 -15
  335. mage_ai/server/frontend_dist_base_path_template/triggers.html +5 -5
  336. mage_ai/server/frontend_dist_base_path_template/version-control.html +5 -5
  337. mage_ai/server/server.py +35 -9
  338. mage_ai/server/utils/output_display.py +6 -0
  339. mage_ai/server/websocket_server.py +14 -0
  340. mage_ai/services/aws/emr/config.py +1 -0
  341. mage_ai/services/aws/emr/constants.py +1 -0
  342. mage_ai/services/aws/emr/emr.py +20 -7
  343. mage_ai/services/compute/__init__.py +0 -0
  344. mage_ai/services/compute/aws/__init__.py +0 -0
  345. mage_ai/services/compute/aws/constants.py +21 -0
  346. mage_ai/services/compute/aws/models.py +459 -0
  347. mage_ai/services/compute/aws/steps.py +482 -0
  348. mage_ai/services/compute/constants.py +27 -0
  349. mage_ai/services/compute/models.py +212 -0
  350. mage_ai/services/k8s/job_manager.py +3 -0
  351. mage_ai/services/spark/api/aws_emr.py +38 -0
  352. mage_ai/services/spark/api/base.py +7 -4
  353. mage_ai/services/spark/api/constants.py +4 -0
  354. mage_ai/services/spark/api/local.py +25 -24
  355. mage_ai/services/spark/api/service.py +15 -5
  356. mage_ai/services/spark/constants.py +1 -1
  357. mage_ai/services/spark/models/applications.py +45 -3
  358. mage_ai/services/spark/models/base.py +3 -19
  359. mage_ai/services/spark/models/environments.py +16 -11
  360. mage_ai/services/spark/models/executors.py +2 -2
  361. mage_ai/services/spark/models/sqls.py +46 -15
  362. mage_ai/services/spark/models/stages.py +55 -32
  363. mage_ai/services/spark/models/threads.py +2 -2
  364. mage_ai/services/spark/utils.py +22 -6
  365. mage_ai/services/ssh/__init__.py +0 -0
  366. mage_ai/services/ssh/aws/__init__.py +0 -0
  367. mage_ai/services/ssh/aws/emr/__init__.py +0 -0
  368. mage_ai/services/ssh/aws/emr/constants.py +10 -0
  369. mage_ai/services/ssh/aws/emr/models.py +326 -0
  370. mage_ai/services/ssh/aws/emr/utils.py +151 -0
  371. mage_ai/settings/__init__.py +8 -1
  372. mage_ai/settings/secret_generation.py +7 -0
  373. mage_ai/settings/sso.py +8 -0
  374. mage_ai/shared/hash.py +16 -0
  375. mage_ai/shared/models.py +253 -0
  376. mage_ai/streaming/constants.py +2 -0
  377. mage_ai/streaming/sources/activemq.py +89 -0
  378. mage_ai/streaming/sources/nats_js.py +182 -0
  379. mage_ai/streaming/sources/source_factory.py +8 -0
  380. mage_ai/tests/ai/test_ai_functions.py +53 -8
  381. mage_ai/tests/api/endpoints/test_oauths.py +33 -0
  382. mage_ai/tests/api/endpoints/test_projects.py +1 -0
  383. mage_ai/tests/api/endpoints/test_workspaces.py +55 -0
  384. mage_ai/tests/api/operations/test_base.py +7 -5
  385. mage_ai/tests/api/operations/test_operations.py +0 -1
  386. mage_ai/tests/api/operations/test_operations_with_hooks.py +577 -0
  387. mage_ai/tests/api/operations/test_syncs.py +0 -1
  388. mage_ai/tests/api/operations/test_users.py +13 -2
  389. mage_ai/tests/data_preparation/models/global_hooks/__init__.py +0 -0
  390. mage_ai/tests/data_preparation/models/global_hooks/test_global_hooks.py +575 -0
  391. mage_ai/tests/data_preparation/models/global_hooks/test_hook.py +760 -0
  392. mage_ai/tests/data_preparation/models/global_hooks/test_utils.py +33 -0
  393. mage_ai/tests/data_preparation/models/test_pipeline.py +5 -0
  394. mage_ai/tests/data_preparation/test_repo_manager.py +11 -0
  395. mage_ai/tests/factory.py +65 -3
  396. mage_ai/tests/orchestration/queue/test_process_queue.py +15 -2
  397. mage_ai/tests/services/k8s/test_job_manager.py +22 -1
  398. mage_ai/tests/shared/mixins.py +291 -0
  399. mage_ai/tests/shared/test_hash.py +17 -1
  400. mage_ai/tests/streaming/sources/test_activemq.py +32 -0
  401. mage_ai/tests/streaming/sources/test_nats_js.py +32 -0
  402. mage_ai/tests/streaming/sources/test_source_factory.py +26 -1
  403. {mage_ai-0.9.45.dist-info → mage_ai-0.9.46.dist-info}/METADATA +8 -1
  404. {mage_ai-0.9.45.dist-info → mage_ai-0.9.46.dist-info}/RECORD +410 -343
  405. mage_ai/authentication/oauth/active_directory.py +0 -17
  406. mage_ai/server/frontend_dist/_next/static/chunks/1125-91d3ce33140ef041.js +0 -1
  407. mage_ai/server/frontend_dist/_next/static/chunks/1749-607014ecf28268bf.js +0 -1
  408. mage_ai/server/frontend_dist/_next/static/chunks/1952-573c7fc7ad84da6e.js +0 -1
  409. mage_ai/server/frontend_dist/_next/static/chunks/3004-231cad9039ae5dcb.js +0 -1
  410. mage_ai/server/frontend_dist/_next/static/chunks/3419-0873e170ef7d6303.js +0 -1
  411. mage_ai/server/frontend_dist/_next/static/chunks/3932-0ceca9599d6e6d00.js +0 -1
  412. mage_ai/server/frontend_dist/_next/static/chunks/4267-335766a915ee2fa9.js +0 -1
  413. mage_ai/server/frontend_dist/_next/static/chunks/5457-8be2e0a3fe0ba64b.js +0 -1
  414. mage_ai/server/frontend_dist/_next/static/chunks/5499-bca977f466e259e1.js +0 -1
  415. mage_ai/server/frontend_dist/_next/static/chunks/553-edf533e634e85192.js +0 -1
  416. mage_ai/server/frontend_dist/_next/static/chunks/5810-37c6091b29a1fe53.js +0 -1
  417. mage_ai/server/frontend_dist/_next/static/chunks/600-0733eb84f0a0a9e0.js +0 -1
  418. mage_ai/server/frontend_dist/_next/static/chunks/6333-95ad799d13326dce.js +0 -1
  419. mage_ai/server/frontend_dist/_next/static/chunks/8224-39a93ee1058b6069.js +0 -1
  420. mage_ai/server/frontend_dist/_next/static/chunks/8264-6ef8fdb195694807.js +0 -1
  421. mage_ai/server/frontend_dist/_next/static/chunks/9264-1b5c4b071ed544c3.js +0 -1
  422. mage_ai/server/frontend_dist/_next/static/chunks/framework-7c365855dab1bf41.js +0 -1
  423. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-1203afde83fa2d6e.js +0 -1
  424. mage_ai/server/frontend_dist/_next/static/chunks/pages/block-layout-c465c14d48392b11.js +0 -1
  425. mage_ai/server/frontend_dist/_next/static/chunks/pages/compute-b1f8d5a7a9a30f2d.js +0 -1
  426. mage_ai/server/frontend_dist/_next/static/chunks/pages/files-93c094bad0f299fb.js +0 -1
  427. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/files-891e5bd5935f7473.js +0 -1
  428. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/settings-d2e4ee4e68d36807.js +0 -1
  429. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/new-4a49126fcfe8ced0.js +0 -1
  430. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-5f8c5d0bc6ad1113.js +0 -1
  431. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a9266d353f288e8c.js +0 -1
  432. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-b5c29c852262312e.js +0 -1
  433. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-9f233917aa72ad82.js +0 -1
  434. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-5af599da035252a7.js +0 -1
  435. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-8597f8e13d80ee48.js +0 -1
  436. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-5e0d047a6c9cb1fc.js +0 -1
  437. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-074c32397d341de9.js +0 -1
  438. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-50f5d8706ed0bc73.js +0 -1
  439. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-e151c1552fcb67bd.js +0 -1
  440. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-8336c4326f1e7d96.js +0 -1
  441. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-01dd679e4a21e0d9.js +0 -1
  442. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-4d9051c073a9b2ff.js +0 -1
  443. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-5a306deca6717862.js +0 -1
  444. mage_ai/server/frontend_dist/_next/static/chunks/pages/sign-in-0dbc5b11019e78a0.js +0 -1
  445. mage_ai/server/frontend_dist/_next/static/chunks/pages/terminal-578d862f3e56e6e6.js +0 -1
  446. mage_ai/server/frontend_dist/_next/static/chunks/pages/test-1c0588d685b909b9.js +0 -1
  447. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-114000e84313994f.js +0 -1
  448. mage_ai/server/frontend_dist/_next/static/icIDjCezcfhiKL87kgeSY/_buildManifest.js +0 -1
  449. mage_ai/server/frontend_dist_base_path_template/_next/static/_O1kJQLGtZmoBMyWpQrea/_buildManifest.js +0 -1
  450. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1125-91d3ce33140ef041.js +0 -1
  451. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1749-607014ecf28268bf.js +0 -1
  452. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1952-573c7fc7ad84da6e.js +0 -1
  453. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3004-231cad9039ae5dcb.js +0 -1
  454. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3419-0873e170ef7d6303.js +0 -1
  455. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3932-0ceca9599d6e6d00.js +0 -1
  456. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4267-335766a915ee2fa9.js +0 -1
  457. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5457-8be2e0a3fe0ba64b.js +0 -1
  458. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5499-bca977f466e259e1.js +0 -1
  459. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/553-edf533e634e85192.js +0 -1
  460. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5810-37c6091b29a1fe53.js +0 -1
  461. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/600-0733eb84f0a0a9e0.js +0 -1
  462. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6333-95ad799d13326dce.js +0 -1
  463. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8224-39a93ee1058b6069.js +0 -1
  464. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8264-6ef8fdb195694807.js +0 -1
  465. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-1b5c4b071ed544c3.js +0 -1
  466. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/framework-7c365855dab1bf41.js +0 -1
  467. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-1203afde83fa2d6e.js +0 -1
  468. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/block-layout-c465c14d48392b11.js +0 -1
  469. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/compute-b1f8d5a7a9a30f2d.js +0 -1
  470. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-93c094bad0f299fb.js +0 -1
  471. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/files-891e5bd5935f7473.js +0 -1
  472. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/settings-d2e4ee4e68d36807.js +0 -1
  473. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-4a49126fcfe8ced0.js +0 -1
  474. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-5f8c5d0bc6ad1113.js +0 -1
  475. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a9266d353f288e8c.js +0 -1
  476. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-b5c29c852262312e.js +0 -1
  477. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-9f233917aa72ad82.js +0 -1
  478. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-5af599da035252a7.js +0 -1
  479. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-8597f8e13d80ee48.js +0 -1
  480. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-5e0d047a6c9cb1fc.js +0 -1
  481. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-074c32397d341de9.js +0 -1
  482. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-50f5d8706ed0bc73.js +0 -1
  483. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-e151c1552fcb67bd.js +0 -1
  484. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-8336c4326f1e7d96.js +0 -1
  485. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-01dd679e4a21e0d9.js +0 -1
  486. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-4d9051c073a9b2ff.js +0 -1
  487. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-5a306deca6717862.js +0 -1
  488. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-0dbc5b11019e78a0.js +0 -1
  489. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/terminal-578d862f3e56e6e6.js +0 -1
  490. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/test-1c0588d685b909b9.js +0 -1
  491. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-114000e84313994f.js +0 -1
  492. /mage_ai/server/frontend_dist/_next/static/{icIDjCezcfhiKL87kgeSY → 9jB4XPuz6BzxBcG9VNao5}/_ssgManifest.js +0 -0
  493. /mage_ai/server/frontend_dist_base_path_template/_next/static/{_O1kJQLGtZmoBMyWpQrea → uPDjJYpJMst1q6psbRyte}/_ssgManifest.js +0 -0
  494. {mage_ai-0.9.45.dist-info → mage_ai-0.9.46.dist-info}/LICENSE +0 -0
  495. {mage_ai-0.9.45.dist-info → mage_ai-0.9.46.dist-info}/WHEEL +0 -0
  496. {mage_ai-0.9.45.dist-info → mage_ai-0.9.46.dist-info}/entry_points.txt +0 -0
  497. {mage_ai-0.9.45.dist-info → mage_ai-0.9.46.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Dict
2
+ from typing import Awaitable, Dict
3
3
 
4
4
 
5
5
  class OauthProvider(ABC):
@@ -38,7 +38,7 @@ class OauthProvider(ABC):
38
38
  pass
39
39
 
40
40
  @abstractmethod
41
- async def get_access_token_response(self, code: str, **kwargs) -> Dict:
41
+ async def get_access_token_response(self, code: str, **kwargs) -> Awaitable[Dict]:
42
42
  """
43
43
  This method should call the oauth provider with the authorization code and return
44
44
  a dictionary containing an access token for the user.
@@ -1,6 +1,6 @@
1
1
  import urllib.parse
2
2
  import uuid
3
- from typing import Dict, Optional
3
+ from typing import Awaitable, Dict
4
4
 
5
5
  import aiohttp
6
6
  from aiohttp import BasicAuth
@@ -17,11 +17,11 @@ class OktaProvider(SsoProvider, OauthProvider):
17
17
 
18
18
  def __init__(self):
19
19
  self.hostname = OKTA_DOMAIN_URL
20
+ self.__validate()
21
+
20
22
  if not self.hostname.startswith('https'):
21
23
  self.hostname = f'https://{self.hostname}'
22
24
 
23
- self.__validate()
24
-
25
25
  def __validate(self):
26
26
  if not self.hostname:
27
27
  raise Exception(
@@ -36,33 +36,32 @@ class OktaProvider(SsoProvider, OauthProvider):
36
36
  'Okta client secret is empty. '
37
37
  'Make sure the OKTA_CLIENT_SECRET environment variable is set.')
38
38
 
39
- def get_auth_url_response(self, redirect_uri: str = None, **kwargs) -> Optional[Dict]:
40
- if OKTA_CLIENT_ID:
41
- base_url = get_base_url(redirect_uri)
42
- redirect_uri_query = dict(
43
- provider=self.provider,
44
- redirect_uri=redirect_uri,
45
- )
46
- query = dict(
47
- client_id=OKTA_CLIENT_ID,
48
- redirect_uri=urllib.parse.quote_plus(
49
- f'{base_url}/oauth',
50
- ),
51
- response_mode='query',
52
- response_type='code',
53
- scope='openid email profile',
54
- state=uuid.uuid4().hex,
55
- )
56
- query_strings = []
57
- for k, v in query.items():
58
- query_strings.append(f'{k}={v}')
39
+ def get_auth_url_response(self, redirect_uri: str = None, **kwargs) -> Dict:
40
+ base_url = get_base_url(redirect_uri)
41
+ redirect_uri_query = dict(
42
+ provider=self.provider,
43
+ redirect_uri=redirect_uri,
44
+ )
45
+ query = dict(
46
+ client_id=OKTA_CLIENT_ID,
47
+ redirect_uri=urllib.parse.quote_plus(
48
+ f'{base_url}/oauth',
49
+ ),
50
+ response_mode='query',
51
+ response_type='code',
52
+ scope='openid email profile',
53
+ state=uuid.uuid4().hex,
54
+ )
55
+ query_strings = []
56
+ for k, v in query.items():
57
+ query_strings.append(f'{k}={v}')
59
58
 
60
- return dict(
61
- url=f"{self.hostname}/oauth2/default/v1/authorize?{'&'.join(query_strings)}",
62
- redirect_query_params=redirect_uri_query,
63
- )
59
+ return dict(
60
+ url=f"{self.hostname}/oauth2/default/v1/authorize?{'&'.join(query_strings)}",
61
+ redirect_query_params=redirect_uri_query,
62
+ )
64
63
 
65
- async def get_access_token_response(self, code: str, **kwargs) -> Dict:
64
+ async def get_access_token_response(self, code: str, **kwargs) -> Awaitable[Dict]:
66
65
  base_url = get_base_url(kwargs.get('redirect_uri'))
67
66
  data = dict()
68
67
  async with aiohttp.ClientSession() as session:
@@ -83,7 +82,7 @@ class OktaProvider(SsoProvider, OauthProvider):
83
82
 
84
83
  return data
85
84
 
86
- async def get_user_info(self, access_token: str = None, **kwargs) -> Dict:
85
+ async def get_user_info(self, access_token: str = None, **kwargs) -> Awaitable[Dict]:
87
86
  if access_token is None:
88
87
  raise Exception('Access token is required to fetch user info.')
89
88
  async with aiohttp.ClientSession() as session:
@@ -1,5 +1,5 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Dict
2
+ from typing import Awaitable, Dict
3
3
 
4
4
 
5
5
  class SsoProvider(ABC):
@@ -7,7 +7,7 @@ class SsoProvider(ABC):
7
7
  Base class for single sign on providers. Can be used in conjunction with OauthProvider.
8
8
  """
9
9
  @abstractmethod
10
- async def get_user_info(self, **kwargs) -> Dict:
10
+ async def get_user_info(self, **kwargs) -> Awaitable[Dict]:
11
11
  """
12
12
  This method should return a dictionary containing the user's information.
13
13
 
@@ -51,6 +51,7 @@ class EmrClusterManager(ClusterManager):
51
51
 
52
52
  def set_active_cluster(
53
53
  self,
54
+ auto_creation: bool = True,
54
55
  auto_selection: bool = False,
55
56
  cluster_id=None,
56
57
  emr_config: Dict = None,
@@ -59,7 +60,7 @@ class EmrClusterManager(ClusterManager):
59
60
  clusters = self.list_clusters()
60
61
  if len(clusters) > 0:
61
62
  cluster_id = clusters[0]['id']
62
- else:
63
+ elif auto_creation:
63
64
  self.create_cluster(emr_config=emr_config)
64
65
  if cluster_id is None:
65
66
  return
@@ -10,6 +10,7 @@ from mage_ai.data_preparation.repo_manager import ProjectType, get_project_type
10
10
  from mage_ai.orchestration.constants import Entity
11
11
  from mage_ai.orchestration.db.models.oauth import User
12
12
  from mage_ai.settings.repo import get_repo_path
13
+ from mage_ai.shared.hash import merge_dict
13
14
 
14
15
 
15
16
  class classproperty(property):
@@ -25,7 +26,7 @@ class Workspace(abc.ABC):
25
26
  self._config = None
26
27
 
27
28
  @classproperty
28
- def project_folder(cls) -> str:
29
+ def project_folder(self) -> str:
29
30
  return os.path.join(get_repo_path(), 'projects')
30
31
 
31
32
  @property
@@ -48,7 +49,7 @@ class Workspace(abc.ABC):
48
49
 
49
50
  @property
50
51
  def project_uuid(self) -> Optional[str]:
51
- self.config.get('project_uuid')
52
+ return self.config.project_uuid
52
53
 
53
54
  def get_access(self, user: User) -> int:
54
55
  return user.get_access(Entity.PROJECT, self.project_uuid)
@@ -114,8 +115,11 @@ class Workspace(abc.ABC):
114
115
  data['project_uuid'] = project_uuid
115
116
 
116
117
  workspace_class = cls.workspace_class_from_type(cluster_type)
118
+
117
119
  try:
118
- return workspace_class.initialize(name, config_path, **payload, **data)
120
+ return workspace_class.initialize(
121
+ name, config_path, **merge_dict(payload, data)
122
+ )
119
123
  except Exception:
120
124
  if config_path and os.path.exists(config_path):
121
125
  os.remove(config_path)
@@ -6,6 +6,7 @@ DESTINATIONS = [
6
6
  dict(name='Delta Lake S3'),
7
7
  dict(name='Elasticsearch'),
8
8
  dict(name='Google Cloud Storage'),
9
+ dict(name='Kafka'),
9
10
  dict(name='MongoDB'),
10
11
  dict(
11
12
  module_name='MSSQL',
@@ -1,6 +1,9 @@
1
1
  import asyncio
2
+ from datetime import datetime
2
3
  from typing import Dict, List
3
4
 
5
+ import pytz
6
+
4
7
  from mage_ai.data_preparation.executors.block_executor import BlockExecutor
5
8
  from mage_ai.data_preparation.logging.logger import DictLogger
6
9
  from mage_ai.data_preparation.logging.logger_manager_factory import LoggerManagerFactory
@@ -93,6 +96,12 @@ class PipelineExecutor:
93
96
  block_uuid=block_run.block_uuid,
94
97
  execution_partition=self.execution_partition,
95
98
  )
99
+ block_run_data = dict(status=BlockRun.BlockRunStatus.RUNNING)
100
+ if not block_run.started_at or \
101
+ (block_run.metrics and not block_run.metrics.get('controller')):
102
+ block_run_data['started_at'] = datetime.now(tz=pytz.UTC)
103
+
104
+ block_run.update(**block_run_data)
96
105
  BlockExecutor(**executor_kwargs).execute(
97
106
  block_run_id=block_run.id,
98
107
  global_vars=global_vars,
@@ -189,6 +189,7 @@ def run_blocks_sync(
189
189
  run_sensors: bool = True,
190
190
  run_tests: bool = True,
191
191
  selected_blocks: Set[str] = None,
192
+ update_status: bool = True,
192
193
  ) -> None:
193
194
  tries_by_block_uuid = {}
194
195
  tasks = dict()
@@ -243,6 +244,7 @@ def run_blocks_sync(
243
244
  from_notebook=not run_sensors,
244
245
  global_vars=global_vars,
245
246
  run_all_blocks=True,
247
+ update_status=update_status,
246
248
  )
247
249
 
248
250
  if run_tests:
@@ -278,6 +280,7 @@ class Block(DataIntegrationMixin, SparkBlock):
278
280
  language: BlockLanguage = BlockLanguage.PYTHON,
279
281
  configuration: Dict = None,
280
282
  has_callback: bool = False,
283
+ repo_config=None,
281
284
  timeout: int = None,
282
285
  ) -> None:
283
286
  if configuration is None:
@@ -339,12 +342,26 @@ class Block(DataIntegrationMixin, SparkBlock):
339
342
 
340
343
  self.execution_timestamp_start = None
341
344
  self.execution_timestamp_end = None
345
+ self.execution_uuid = None
346
+ self._compute_service_uuid = None
347
+ self._repo_config = repo_config
342
348
  self._spark_session_current = None
349
+ self.global_vars = None
343
350
 
344
351
  @property
345
352
  def uuid(self) -> str:
346
353
  return self._uuid
347
354
 
355
+ @property
356
+ def repo_config(self):
357
+ if self._repo_config:
358
+ return self._repo_config
359
+
360
+ if self.pipeline:
361
+ self._repo_config = self.pipeline.repo_config
362
+
363
+ return self._repo_config
364
+
348
365
  @property
349
366
  def uuid_replicated(self) -> str:
350
367
  if self.replicated_block:
@@ -874,6 +891,7 @@ class Block(DataIntegrationMixin, SparkBlock):
874
891
  global_vars: Dict = None,
875
892
  logger: Logger = None,
876
893
  logging_tags: Dict = None,
894
+ execution_uuid: str = None,
877
895
  from_notebook: bool = False,
878
896
  **kwargs
879
897
  ) -> Dict:
@@ -883,6 +901,9 @@ class Block(DataIntegrationMixin, SparkBlock):
883
901
  websocket as a way to test the code in the callback. To run a block in a pipeline
884
902
  run, use a BlockExecutor.
885
903
  """
904
+ if execution_uuid:
905
+ self.execution_uuid = execution_uuid
906
+
886
907
  if logging_tags is None:
887
908
  logging_tags = dict()
888
909
 
@@ -1406,8 +1427,7 @@ class Block(DataIntegrationMixin, SparkBlock):
1406
1427
  if logger and 'logger' not in global_vars:
1407
1428
  global_vars['logger'] = logger
1408
1429
 
1409
- track_spark = from_notebook and self.is_using_spark() and \
1410
- self.compute_management_enabled()
1430
+ track_spark = from_notebook and self.should_track_spark()
1411
1431
 
1412
1432
  if track_spark:
1413
1433
  self.clear_spark_jobs_cache()
@@ -1490,7 +1510,8 @@ class Block(DataIntegrationMixin, SparkBlock):
1490
1510
  self.module = module
1491
1511
 
1492
1512
  return block_function_updated
1493
- except Exception:
1513
+ except Exception as err:
1514
+ print(f'[WARNING] Block.initialize_decorator_modules: {err}')
1494
1515
  print('Falling back to default block execution...')
1495
1516
 
1496
1517
  return block_function
@@ -2475,6 +2496,31 @@ df = get_variable('{self.pipeline.uuid}', '{block_uuid}', 'df')
2475
2496
  return variable_mapping
2476
2497
 
2477
2498
  def __enrich_global_vars(self, global_vars: Dict = None) -> Dict:
2499
+ """
2500
+ Enriches the provided global variables dictionary with additional context, Spark session,
2501
+ environment, configuration, and an empty context dictionary.
2502
+
2503
+ Args:
2504
+ global_vars (Optional[Dict]): A dictionary of global variables to be enriched.
2505
+ If not provided, an empty dictionary is created.
2506
+
2507
+ Returns:
2508
+ Dict: The enriched global variables dictionary.
2509
+
2510
+ This method checks if the pipeline type is DATABRICKS or if the environment is a Spark
2511
+ environment. If true, it adds the Spark session to the global variables if not already
2512
+ present.
2513
+
2514
+ If 'env' is not in the global variables, it adds the environment information using the
2515
+ 'get_env()' function.
2516
+
2517
+ Adds the block configuration to the global variables.
2518
+
2519
+ If 'context' is not in global_vars, it adds an empty context dictionary.
2520
+
2521
+ The final enriched global variables dictionary is assigned to the object's 'global_vars'
2522
+ attribute and returned.
2523
+ """
2478
2524
  if global_vars is None:
2479
2525
  global_vars = dict()
2480
2526
  if ((self.pipeline is not None and self.pipeline.type == PipelineType.DATABRICKS) or
@@ -2485,16 +2531,19 @@ df = get_variable('{self.pipeline.uuid}', '{block_uuid}', 'df')
2485
2531
  global_vars['spark'] = spark
2486
2532
  if 'env' not in global_vars:
2487
2533
  global_vars['env'] = get_env()
2488
- if 'configuration' not in global_vars:
2489
- global_vars['configuration'] = self.configuration
2534
+ global_vars['configuration'] = self.configuration
2490
2535
  if 'context' not in global_vars:
2491
2536
  global_vars['context'] = dict()
2537
+
2538
+ self.global_vars = global_vars
2539
+
2492
2540
  return global_vars
2493
2541
 
2494
2542
  def get_spark_session(self):
2495
2543
  if self.spark_init and (not self.pipeline or
2496
2544
  not self.pipeline.spark_config):
2497
2545
  return self.spark
2546
+
2498
2547
  try:
2499
2548
  if self.pipeline and self.pipeline.spark_config:
2500
2549
  spark_config = SparkConfig.load(
@@ -2507,6 +2556,9 @@ df = get_variable('{self.pipeline.uuid}', '{block_uuid}', 'df')
2507
2556
  except Exception:
2508
2557
  self.spark = None
2509
2558
 
2559
+ if not self.spark and self.global_vars and self.global_vars.get('spark'):
2560
+ self.spark = self.global_vars.get('spark')
2561
+
2510
2562
  self.spark_init = True
2511
2563
  return self.spark
2512
2564
 
@@ -75,7 +75,7 @@ def convert_dataframe_to_output(
75
75
  if log_message:
76
76
  log_message(
77
77
  f'Writing {len(records_in_batch)} records from stream {stream} to {file_path} '
78
- f'for batch index {index} ({index + 1 } out of {batches} batch(s)).',
78
+ f'for batch index {index} ({index + 1} out of {batches} batch(s)).',
79
79
  )
80
80
 
81
81
  output_file_paths.append(file_path)
@@ -12,6 +12,7 @@ from mage_ai.data_preparation.models.block.spark.constants import (
12
12
  from mage_ai.data_preparation.models.project import Project
13
13
  from mage_ai.data_preparation.models.project.constants import FeatureUUID
14
14
  from mage_ai.services.spark.api.service import API
15
+ from mage_ai.services.spark.constants import ComputeServiceUUID
15
16
  from mage_ai.services.spark.models.applications import Application
16
17
  from mage_ai.services.spark.models.jobs import Job
17
18
  from mage_ai.services.spark.models.sqls import Sql
@@ -30,6 +31,16 @@ class SparkBlock:
30
31
 
31
32
  return self._spark_session_current
32
33
 
34
+ @property
35
+ def compute_service_uuid(self) -> ComputeServiceUUID:
36
+ if self._compute_service_uuid:
37
+ return self._compute_service_uuid
38
+ self._compute_service_uuid = get_compute_service(
39
+ ignore_active_kernel=True,
40
+ repo_config=self.repo_config,
41
+ )
42
+ return self._compute_service_uuid
43
+
33
44
  def spark_session_application(self) -> Application:
34
45
  if not self.spark_session:
35
46
  return
@@ -40,7 +51,7 @@ class SparkBlock:
40
51
  if value_tup:
41
52
  application_id = value_tup[1]
42
53
 
43
- return Application(
54
+ return Application.load(
44
55
  id=application_id,
45
56
  spark_ui_url=self.spark_session.sparkContext.uiWebUrl,
46
57
  )
@@ -51,7 +62,13 @@ class SparkBlock:
51
62
  )
52
63
 
53
64
  def is_using_spark(self) -> bool:
54
- return get_compute_service()
65
+ return self.compute_service_uuid in [
66
+ ComputeServiceUUID.AWS_EMR,
67
+ ComputeServiceUUID.STANDALONE_CLUSTER,
68
+ ]
69
+
70
+ def should_track_spark(self) -> bool:
71
+ return self.is_using_spark() and self.compute_management_enabled()
55
72
 
56
73
  def execution_states(self, cache: bool = False) -> Dict:
57
74
  jobs_cache = self.__load_cache()
@@ -82,33 +99,40 @@ class SparkBlock:
82
99
  def jobs_during_execution(self) -> List[Job]:
83
100
  self.__load_spark_job_submission_timestamps()
84
101
 
85
- if self.execution_timestamp_start:
86
- jobs = self.__get_jobs(application=self.execution_start_application)
87
-
88
- def _filter(
89
- job: Job,
90
- execution_timestamp_start: float = self.execution_timestamp_start,
91
- execution_timestamp_end: float = self.execution_timestamp_end,
92
- ) -> bool:
93
- if not job.submission_time:
94
- return False
95
-
96
- if isinstance(job.submission_time, str):
97
- submission_timestamp = dateutil.parser.parse(job.submission_time).timestamp()
98
- elif isinstance(job.submission_time, float) or isinstance(job.submission_time, int):
99
- submission_timestamp = datetime.fromtimestamp(job.submission_time)
100
-
101
- return execution_timestamp_start and \
102
- execution_timestamp_end and \
103
- submission_timestamp >= execution_timestamp_start and \
104
- (
105
- not execution_timestamp_end or
106
- submission_timestamp <= execution_timestamp_end
107
- )
102
+ if not self.execution_timestamp_start and self.execution_uuid_start:
103
+ return []
104
+
105
+ def _filter(
106
+ job: Job,
107
+ block_uuid=self.uuid,
108
+ compute_service_uuid=self.compute_service_uuid,
109
+ execution_timestamp_end: float = self.execution_timestamp_end,
110
+ execution_timestamp_start: float = self.execution_timestamp_start,
111
+ execution_uuid_start=self.execution_uuid_start,
112
+ ) -> bool:
113
+ if ComputeServiceUUID.AWS_EMR == compute_service_uuid:
114
+ key = self.execution_uuid_start or self.execution_timestamp_start
115
+ return job.name == f'{block_uuid}:{key}'
116
+
117
+ if not job.submission_time:
118
+ return False
119
+
120
+ if isinstance(job.submission_time, str):
121
+ submission_timestamp = dateutil.parser.parse(job.submission_time).timestamp()
122
+ elif isinstance(job.submission_time, float) or isinstance(job.submission_time, int):
123
+ submission_timestamp = datetime.fromtimestamp(job.submission_time)
124
+
125
+ return execution_timestamp_start and \
126
+ execution_timestamp_end and \
127
+ submission_timestamp >= execution_timestamp_start and \
128
+ (
129
+ not execution_timestamp_end or
130
+ submission_timestamp <= execution_timestamp_end
131
+ )
108
132
 
109
- return list(filter(_filter, jobs))
133
+ jobs = self.__get_jobs(application=self.execution_start_application)
110
134
 
111
- return []
135
+ return list(filter(_filter, jobs or []))
112
136
 
113
137
  def stages_during_execution(self, jobs: List[Job]):
114
138
  if not jobs:
@@ -122,7 +146,7 @@ class SparkBlock:
122
146
 
123
147
  stages = self.__get_stages(application=self.execution_start_application)
124
148
 
125
- return list(filter(_filter, stages))
149
+ return list(filter(_filter, stages or []))
126
150
 
127
151
  def sqls_during_execution(self, jobs: List[Job]):
128
152
  if not jobs:
@@ -140,7 +164,7 @@ class SparkBlock:
140
164
 
141
165
  sqls = self.__get_sqls(application=self.execution_start_application)
142
166
 
143
- return list(filter(_filter, sqls))
167
+ return list(filter(_filter, sqls or []))
144
168
 
145
169
  def clear_spark_jobs_cache(self) -> None:
146
170
  if os.path.exists(self.spark_jobs_full_path):
@@ -155,13 +179,24 @@ class SparkBlock:
155
179
  for application in applications:
156
180
  Application.cache_application(application)
157
181
 
158
- def set_spark_job_execution_start(self) -> None:
182
+ def set_spark_job_execution_start(self, execution_uuid: str = None) -> None:
159
183
  self.execution_timestamp_start = datetime.utcnow().timestamp()
160
184
  application = self.spark_session_application()
161
185
 
186
+ if execution_uuid:
187
+ self.execution_uuid = execution_uuid
188
+
189
+ if self.spark_session and self.spark_session.sparkContext:
190
+ key = f'{self.uuid}:{self.execution_uuid or self.execution_timestamp_start}'
191
+ # For jobs
192
+ self.spark_session.sparkContext.setLocalProperty('callSite.short', key)
193
+ # For stages
194
+ self.spark_session.sparkContext.setLocalProperty('callSite.long', key)
195
+
162
196
  self.__update_spark_jobs_cache(
163
197
  dict(
164
198
  application=application.to_dict() if application else None,
199
+ execution_uuid=self.execution_uuid,
165
200
  submission_timestamp=self.execution_timestamp_start,
166
201
  ),
167
202
  'before',
@@ -187,7 +222,7 @@ class SparkBlock:
187
222
 
188
223
  if application:
189
224
  build_options.update(dict(
190
- application_id=application.id,
225
+ application_id=application.calculated_id(),
191
226
  application_spark_ui_url=application.spark_ui_url,
192
227
  ))
193
228
  else:
@@ -207,7 +242,7 @@ class SparkBlock:
207
242
  else:
208
243
  applications = api.applications_sync()
209
244
  if applications:
210
- jobs = api.jobs_sync(applications[0].id)
245
+ jobs = api.jobs_sync(applications[0].calculated_id())
211
246
 
212
247
  return sorted(
213
248
  jobs,
@@ -231,7 +266,7 @@ class SparkBlock:
231
266
  applications = api.applications_sync()
232
267
 
233
268
  if applications:
234
- stages = api.stages_sync(applications[0].id, dict(
269
+ stages = api.stages_sync(applications[0].calculated_id(), dict(
235
270
  quantiles='0.01,0.25,0.5,0.75,0.99',
236
271
  withSummaries=True,
237
272
  ))
@@ -253,7 +288,7 @@ class SparkBlock:
253
288
 
254
289
  sqls = []
255
290
  if applications:
256
- sqls = api.sqls_sync(applications[0].id, dict(
291
+ sqls = api.sqls_sync(applications[0].calculated_id(), dict(
257
292
  length=9999,
258
293
  ))
259
294
 
@@ -304,6 +339,13 @@ class SparkBlock:
304
339
  f.write(json.dumps(data))
305
340
 
306
341
  def __load_spark_job_submission_timestamps(self) -> None:
342
+ self.execution_end_application = None
343
+ self.execution_start_application = None
344
+ self.execution_timestamp_end = None
345
+ self.execution_timestamp_start = None
346
+ self.execution_uuid_end = None
347
+ self.execution_uuid_start = None
348
+
307
349
  jobs_cache = self.__load_cache()
308
350
  if jobs_cache:
309
351
  before = jobs_cache.get('before')
@@ -311,6 +353,9 @@ class SparkBlock:
311
353
  self.execution_timestamp_start = (before or {}).get(
312
354
  'submission_timestamp',
313
355
  )
356
+ self.execution_uuid_start = (before or {}).get(
357
+ 'execution_uuid',
358
+ )
314
359
  self.execution_start_application = (before or {}).get(
315
360
  'application',
316
361
  )
@@ -324,6 +369,9 @@ class SparkBlock:
324
369
  self.execution_timestamp_end = (after or {}).get(
325
370
  'submission_timestamp',
326
371
  )
372
+ self.execution_uuid_end = (after or {}).get(
373
+ 'execution_uuid',
374
+ )
327
375
  self.execution_end_application = (after or {}).get(
328
376
  'application',
329
377
  )
@@ -0,0 +1,8 @@
1
+ class Download():
2
+ def __init__(self, token):
3
+ self.token = token
4
+
5
+ def to_dict(self, **kwargs):
6
+ data = {}
7
+ data['token'] = self.token
8
+ return data
@@ -0,0 +1,44 @@
1
+ from enum import Enum
2
+
3
+ from mage_ai.authentication.permissions.constants import EntityName
4
+
5
+ DISABLED_RESOURCE_TYPES = [
6
+ EntityName.ALL,
7
+ EntityName.ALL_EXCEPT_RESERVED,
8
+ ]
9
+
10
+ RESTRICTED_RESOURCE_TYPES = [
11
+ EntityName.File,
12
+ EntityName.FileContent,
13
+ EntityName.Folder,
14
+ EntityName.GlobalHook,
15
+ EntityName.Oauth,
16
+ EntityName.OauthAccessToken,
17
+ EntityName.OauthApplication,
18
+ EntityName.Permission,
19
+ EntityName.Role,
20
+ EntityName.RolePermission,
21
+ EntityName.Secret,
22
+ EntityName.Session,
23
+ EntityName.User,
24
+ EntityName.UserRole,
25
+ EntityName.Workspace,
26
+ ]
27
+
28
+ RESOURCE_TYPES = [en for en in EntityName if en not in DISABLED_RESOURCE_TYPES]
29
+
30
+
31
+ class HookOutputKey(str, Enum):
32
+ ERROR = 'error'
33
+ META = 'meta'
34
+ METADATA = 'metadata'
35
+ PAYLOAD = 'payload'
36
+ QUERY = 'query'
37
+ RESOURCE = 'resource'
38
+ RESOURCES = 'resources'
39
+
40
+
41
+ VALID_KEYS_FOR_INPUT_OUTPUT_DATA_RESTRICTED = [key.value for key in HookOutputKey]
42
+ VALID_KEYS_FOR_INPUT_OUTPUT_DATA_UNRESTRICTED = ['hook']
43
+ VALID_KEYS_FOR_INPUT_OUTPUT_DATA_ALL = \
44
+ VALID_KEYS_FOR_INPUT_OUTPUT_DATA_RESTRICTED + VALID_KEYS_FOR_INPUT_OUTPUT_DATA_UNRESTRICTED