mage-ai 0.9.46__py3-none-any.whl → 0.9.47__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 (309) hide show
  1. mage_ai/api/operations/base.py +27 -5
  2. mage_ai/api/policies/GlobalHookPolicy.py +1 -1
  3. mage_ai/api/policies/IntegrationSourcePolicy.py +62 -0
  4. mage_ai/api/policies/OauthPolicy.py +6 -6
  5. mage_ai/api/presenters/GlobalHookPresenter.py +1 -1
  6. mage_ai/api/presenters/IntegrationSourcePresenter.py +9 -2
  7. mage_ai/api/presenters/PipelinePresenter.py +2 -0
  8. mage_ai/api/presenters/PipelineRunPresenter.py +8 -3
  9. mage_ai/api/presenters/PipelineSchedulePresenter.py +22 -1
  10. mage_ai/api/resources/BlockResource.py +5 -0
  11. mage_ai/api/resources/DataProviderResource.py +2 -0
  12. mage_ai/api/resources/IntegrationSourceResource.py +149 -2
  13. mage_ai/data_integrations/sources/constants.py +5 -0
  14. mage_ai/data_integrations/utils/scheduler.py +57 -2
  15. mage_ai/data_preparation/executors/block_executor.py +9 -1
  16. mage_ai/data_preparation/models/block/__init__.py +25 -12
  17. mage_ai/data_preparation/models/block/data_integration/constants.py +3 -0
  18. mage_ai/data_preparation/models/block/data_integration/utils.py +196 -37
  19. mage_ai/data_preparation/models/block/sql/utils/shared.py +18 -1
  20. mage_ai/data_preparation/models/block/utils.py +28 -13
  21. mage_ai/data_preparation/models/global_hooks/constants.py +50 -1
  22. mage_ai/data_preparation/models/global_hooks/models.py +148 -84
  23. mage_ai/data_preparation/models/global_hooks/predicates.py +316 -0
  24. mage_ai/data_preparation/models/pipeline.py +2 -0
  25. mage_ai/data_preparation/models/pipelines/integration_pipeline.py +0 -1
  26. mage_ai/data_preparation/preferences.py +29 -18
  27. mage_ai/data_preparation/repo_manager.py +12 -2
  28. mage_ai/data_preparation/sync/__init__.py +2 -0
  29. mage_ai/data_preparation/templates/constants.py +14 -0
  30. mage_ai/data_preparation/templates/data_exporters/chroma.py +24 -0
  31. mage_ai/data_preparation/templates/data_exporters/streaming/rabbitmq.yaml +7 -0
  32. mage_ai/data_preparation/templates/data_loaders/chroma.py +27 -0
  33. mage_ai/data_preparation/templates/repo/io_config.yaml +3 -0
  34. mage_ai/io/base.py +1 -0
  35. mage_ai/io/chroma.py +153 -0
  36. mage_ai/io/config.py +8 -0
  37. mage_ai/orchestration/db/models/schedules.py +98 -34
  38. mage_ai/orchestration/pipeline_scheduler.py +58 -19
  39. mage_ai/server/constants.py +1 -1
  40. mage_ai/server/frontend_dist/404.html +2 -2
  41. mage_ai/server/frontend_dist/_next/static/N3FS4bHv0jpYeeg672uYK/_buildManifest.js +1 -0
  42. mage_ai/server/frontend_dist/_next/static/chunks/{1749-9a6276b2918fdae1.js → 1749-bf512b4dabbab7fa.js} +1 -1
  43. mage_ai/server/frontend_dist/_next/static/chunks/{1952-ac7722e8b1ab88fe.js → 1952-57858e7445d24413.js} +1 -1
  44. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/2714-1e79e9f2e998b544.js → frontend_dist/_next/static/chunks/2714-68fef54789d7eaeb.js} +1 -1
  45. mage_ai/server/frontend_dist/_next/static/chunks/2717-92cdffd87b6f6e05.js +1 -0
  46. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/3419-f8d518d024e7b5c8.js → frontend_dist/_next/static/chunks/3419-715ca383fa15a5ef.js} +1 -1
  47. mage_ai/server/frontend_dist/_next/static/chunks/3437-b4d6a037cf5781f8.js +1 -0
  48. mage_ai/server/frontend_dist/_next/static/chunks/3943-c9fb980f03df6450.js +1 -0
  49. mage_ai/server/frontend_dist/_next/static/chunks/4267-cb102e060a43d9bd.js +1 -0
  50. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/4366-93e09e5a4a7e182c.js → frontend_dist/_next/static/chunks/4366-3e52497942acbafe.js} +1 -1
  51. mage_ai/server/frontend_dist/_next/static/chunks/{4783-1a21d9be47574bba.js → 4783-422429203610c318.js} +1 -1
  52. mage_ai/server/frontend_dist/_next/static/chunks/5810-e26a0768db1cfdba.js +1 -0
  53. mage_ai/server/frontend_dist/_next/static/chunks/{5896-14e5a23b1c6a0769.js → 5896-7b8e36634d7d94eb.js} +1 -1
  54. mage_ai/server/frontend_dist/_next/static/chunks/{6285-e9b45335bfb9ccaf.js → 6285-648f9a732e100b2f.js} +1 -1
  55. mage_ai/server/frontend_dist/_next/static/chunks/6798-b904395b0c18647b.js +1 -0
  56. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/7022-070ec0144a4d029c.js → frontend_dist/_next/static/chunks/7022-e76cae3ba5ee5312.js} +1 -1
  57. mage_ai/server/frontend_dist/_next/static/chunks/722-900f786d24f91b2e.js +1 -0
  58. mage_ai/server/frontend_dist/_next/static/chunks/{7361-694e1e4fb9c97d68.js → 7361-6c5c9063b9f91700.js} +1 -1
  59. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/8146-92e7ccfed169ee9c.js → frontend_dist/_next/static/chunks/8146-27f0e31f309897a5.js} +1 -1
  60. mage_ai/server/frontend_dist/_next/static/chunks/845-9a73c65fe3fdc328.js +1 -0
  61. mage_ai/server/frontend_dist/_next/static/chunks/8487-8e1c09546dff4dbf.js +1 -0
  62. mage_ai/server/frontend_dist/_next/static/chunks/9264-cc44b07f248707b0.js +1 -0
  63. mage_ai/server/frontend_dist/_next/static/chunks/9618-4eb49cdbd1ba11d7.js +1 -0
  64. mage_ai/server/frontend_dist/_next/static/chunks/{976-18c98af60b76f1a7.js → 976-0a8c2c4d7acd957b.js} +1 -1
  65. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-78c4a077a2f279c2.js +1 -0
  66. mage_ai/server/frontend_dist/_next/static/chunks/pages/files-b37d221eb5ddc248.js +1 -0
  67. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-7adc543fc490367a.js +1 -0
  68. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks-51d366993f6dd449.js +1 -0
  69. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{files-449a022f2f0f2d94.js → files-fe6e73463a20d67c.js} +1 -1
  70. mage_ai/server/frontend_dist/_next/static/chunks/pages/{manage-f83deb790548693b.js → manage-d8a38b5d1f50e798.js} +1 -1
  71. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-9adc2974aada27ba.js +1 -0
  72. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-51b1311dff2a974e.js +1 -0
  73. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-2333e524d34b474a.js +1 -0
  74. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e051057d9fe94f23.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-6d1afeb4a84f50f7.js} +1 -1
  75. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1ff9bb8e22ca1e75.js +1 -0
  76. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-11363aa58d51f4e1.js +1 -0
  77. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-779c3ef0676a12ac.js +1 -0
  78. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-bbea9a088657404a.js +1 -0
  79. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-3737f2b0afc2ede3.js +1 -0
  80. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-3c8f062913c66f3e.js +1 -0
  81. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-c1f4ed17d501ccca.js +1 -0
  82. mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-8bdd858240d5dbf6.js +1 -0
  83. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-dd4fb405695f74bf.js +1 -0
  84. mage_ai/server/frontend_dist/block-layout.html +2 -2
  85. mage_ai/server/frontend_dist/compute.html +5 -5
  86. mage_ai/server/frontend_dist/files.html +5 -5
  87. mage_ai/server/frontend_dist/global-data-products/[...slug].html +5 -5
  88. mage_ai/server/frontend_dist/global-data-products.html +5 -5
  89. mage_ai/server/frontend_dist/global-hooks/[...slug].html +5 -5
  90. mage_ai/server/frontend_dist/global-hooks.html +5 -5
  91. mage_ai/server/frontend_dist/index.html +2 -2
  92. mage_ai/server/frontend_dist/manage/files.html +5 -5
  93. mage_ai/server/frontend_dist/manage/settings.html +5 -5
  94. mage_ai/server/frontend_dist/manage/users/[user].html +5 -5
  95. mage_ai/server/frontend_dist/manage/users/new.html +5 -5
  96. mage_ai/server/frontend_dist/manage/users.html +5 -5
  97. mage_ai/server/frontend_dist/manage.html +5 -5
  98. mage_ai/server/frontend_dist/oauth.html +4 -4
  99. mage_ai/server/frontend_dist/overview.html +5 -5
  100. mage_ai/server/frontend_dist/pipeline-runs.html +5 -5
  101. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +5 -5
  102. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +5 -5
  103. mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +5 -5
  104. mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
  105. mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +5 -5
  106. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +5 -5
  107. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +5 -5
  108. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +5 -5
  109. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +5 -5
  110. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +5 -5
  111. mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +5 -5
  112. mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +5 -5
  113. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +5 -5
  114. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +5 -5
  115. mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
  116. mage_ai/server/frontend_dist/pipelines.html +5 -5
  117. mage_ai/server/frontend_dist/settings/account/profile.html +5 -5
  118. mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +5 -5
  119. mage_ai/server/frontend_dist/settings/workspace/permissions.html +5 -5
  120. mage_ai/server/frontend_dist/settings/workspace/preferences.html +5 -5
  121. mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +5 -5
  122. mage_ai/server/frontend_dist/settings/workspace/roles.html +5 -5
  123. mage_ai/server/frontend_dist/settings/workspace/sync-data.html +5 -5
  124. mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +5 -5
  125. mage_ai/server/frontend_dist/settings/workspace/users.html +5 -5
  126. mage_ai/server/frontend_dist/settings.html +2 -2
  127. mage_ai/server/frontend_dist/sign-in.html +20 -20
  128. mage_ai/server/frontend_dist/templates/[...slug].html +5 -5
  129. mage_ai/server/frontend_dist/templates.html +5 -5
  130. mage_ai/server/frontend_dist/terminal.html +5 -5
  131. mage_ai/server/frontend_dist/test.html +5 -5
  132. mage_ai/server/frontend_dist/triggers.html +5 -5
  133. mage_ai/server/frontend_dist/version-control.html +5 -5
  134. mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
  135. mage_ai/server/frontend_dist_base_path_template/_next/static/aoO6jYZLVlUGCCdY-wmy8/_buildManifest.js +1 -0
  136. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1749-9a6276b2918fdae1.js → 1749-bf512b4dabbab7fa.js} +1 -1
  137. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1952-ac7722e8b1ab88fe.js → 1952-57858e7445d24413.js} +1 -1
  138. mage_ai/server/{frontend_dist/_next/static/chunks/2714-1e79e9f2e998b544.js → frontend_dist_base_path_template/_next/static/chunks/2714-68fef54789d7eaeb.js} +1 -1
  139. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-92cdffd87b6f6e05.js +1 -0
  140. mage_ai/server/{frontend_dist/_next/static/chunks/3419-f8d518d024e7b5c8.js → frontend_dist_base_path_template/_next/static/chunks/3419-715ca383fa15a5ef.js} +1 -1
  141. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3437-b4d6a037cf5781f8.js +1 -0
  142. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3943-c9fb980f03df6450.js +1 -0
  143. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4267-cb102e060a43d9bd.js +1 -0
  144. mage_ai/server/{frontend_dist/_next/static/chunks/4366-93e09e5a4a7e182c.js → frontend_dist_base_path_template/_next/static/chunks/4366-3e52497942acbafe.js} +1 -1
  145. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{4783-1a21d9be47574bba.js → 4783-422429203610c318.js} +1 -1
  146. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5810-e26a0768db1cfdba.js +1 -0
  147. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{5896-14e5a23b1c6a0769.js → 5896-7b8e36634d7d94eb.js} +1 -1
  148. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{6285-e9b45335bfb9ccaf.js → 6285-648f9a732e100b2f.js} +1 -1
  149. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6798-b904395b0c18647b.js +1 -0
  150. mage_ai/server/{frontend_dist/_next/static/chunks/7022-070ec0144a4d029c.js → frontend_dist_base_path_template/_next/static/chunks/7022-e76cae3ba5ee5312.js} +1 -1
  151. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/722-900f786d24f91b2e.js +1 -0
  152. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{7361-694e1e4fb9c97d68.js → 7361-6c5c9063b9f91700.js} +1 -1
  153. mage_ai/server/{frontend_dist/_next/static/chunks/8146-92e7ccfed169ee9c.js → frontend_dist_base_path_template/_next/static/chunks/8146-27f0e31f309897a5.js} +1 -1
  154. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/845-9a73c65fe3fdc328.js +1 -0
  155. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8487-8e1c09546dff4dbf.js +1 -0
  156. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-cc44b07f248707b0.js +1 -0
  157. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9618-4eb49cdbd1ba11d7.js +1 -0
  158. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{976-18c98af60b76f1a7.js → 976-0a8c2c4d7acd957b.js} +1 -1
  159. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-78c4a077a2f279c2.js +1 -0
  160. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-b37d221eb5ddc248.js +1 -0
  161. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-7adc543fc490367a.js +1 -0
  162. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks-51d366993f6dd449.js +1 -0
  163. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{files-449a022f2f0f2d94.js → files-fe6e73463a20d67c.js} +1 -1
  164. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{manage-f83deb790548693b.js → manage-d8a38b5d1f50e798.js} +1 -1
  165. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-9adc2974aada27ba.js +1 -0
  166. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-51b1311dff2a974e.js +1 -0
  167. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-2333e524d34b474a.js +1 -0
  168. mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e051057d9fe94f23.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-6d1afeb4a84f50f7.js} +1 -1
  169. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1ff9bb8e22ca1e75.js +1 -0
  170. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-11363aa58d51f4e1.js +1 -0
  171. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-779c3ef0676a12ac.js +1 -0
  172. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-bbea9a088657404a.js +1 -0
  173. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-3737f2b0afc2ede3.js +1 -0
  174. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-3c8f062913c66f3e.js +1 -0
  175. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-c1f4ed17d501ccca.js +1 -0
  176. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-8bdd858240d5dbf6.js +1 -0
  177. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-dd4fb405695f74bf.js +1 -0
  178. mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
  179. mage_ai/server/frontend_dist_base_path_template/compute.html +5 -5
  180. mage_ai/server/frontend_dist_base_path_template/files.html +5 -5
  181. mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +5 -5
  182. mage_ai/server/frontend_dist_base_path_template/global-data-products.html +5 -5
  183. mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +5 -5
  184. mage_ai/server/frontend_dist_base_path_template/global-hooks.html +5 -5
  185. mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
  186. mage_ai/server/frontend_dist_base_path_template/manage/files.html +5 -5
  187. mage_ai/server/frontend_dist_base_path_template/manage/settings.html +5 -5
  188. mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +5 -5
  189. mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +5 -5
  190. mage_ai/server/frontend_dist_base_path_template/manage/users.html +5 -5
  191. mage_ai/server/frontend_dist_base_path_template/manage.html +5 -5
  192. mage_ai/server/frontend_dist_base_path_template/oauth.html +4 -4
  193. mage_ai/server/frontend_dist_base_path_template/overview.html +5 -5
  194. mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +5 -5
  195. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +5 -5
  196. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +5 -5
  197. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +5 -5
  198. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
  199. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +5 -5
  200. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +5 -5
  201. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +5 -5
  202. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +5 -5
  203. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +5 -5
  204. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +5 -5
  205. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +5 -5
  206. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +5 -5
  207. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +5 -5
  208. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +5 -5
  209. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
  210. mage_ai/server/frontend_dist_base_path_template/pipelines.html +5 -5
  211. mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +5 -5
  212. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +5 -5
  213. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +5 -5
  214. mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +5 -5
  215. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +5 -5
  216. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +5 -5
  217. mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +5 -5
  218. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +5 -5
  219. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +5 -5
  220. mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
  221. mage_ai/server/frontend_dist_base_path_template/sign-in.html +23 -23
  222. mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +5 -5
  223. mage_ai/server/frontend_dist_base_path_template/templates.html +5 -5
  224. mage_ai/server/frontend_dist_base_path_template/terminal.html +5 -5
  225. mage_ai/server/frontend_dist_base_path_template/test.html +5 -5
  226. mage_ai/server/frontend_dist_base_path_template/triggers.html +5 -5
  227. mage_ai/server/frontend_dist_base_path_template/version-control.html +5 -5
  228. mage_ai/server/server.py +9 -3
  229. mage_ai/services/k8s/job_manager.py +1 -0
  230. mage_ai/settings/repo.py +3 -0
  231. mage_ai/shared/files.py +47 -0
  232. mage_ai/shared/models.py +1 -0
  233. mage_ai/streaming/constants.py +1 -0
  234. mage_ai/streaming/sinks/postgres.py +2 -0
  235. mage_ai/streaming/sinks/rabbitmq.py +76 -0
  236. mage_ai/streaming/sinks/sink_factory.py +4 -0
  237. mage_ai/tests/api/operations/test_operations_with_hooks.py +136 -91
  238. mage_ai/tests/api/policies/test_oauth_policy.py +38 -0
  239. mage_ai/tests/data_preparation/models/global_hooks/test_global_hooks.py +33 -8
  240. mage_ai/tests/data_preparation/models/global_hooks/test_hook.py +82 -38
  241. mage_ai/tests/data_preparation/models/global_hooks/test_predicates.py +803 -0
  242. mage_ai/tests/data_preparation/models/global_hooks/test_utils.py +6 -1
  243. mage_ai/tests/data_preparation/models/test_block.py +26 -0
  244. mage_ai/tests/data_preparation/models/test_pipeline.py +10 -0
  245. mage_ai/tests/factory.py +40 -2
  246. mage_ai/tests/orchestration/test_pipeline_scheduler.py +82 -1
  247. mage_ai/tests/services/k8s/test_job_manager.py +16 -0
  248. mage_ai/tests/shared/mixins.py +60 -23
  249. mage_ai/tests/streaming/sinks/test_rabbitmq.py +36 -0
  250. {mage_ai-0.9.46.dist-info → mage_ai-0.9.47.dist-info}/METADATA +7 -4
  251. {mage_ai-0.9.46.dist-info → mage_ai-0.9.47.dist-info}/RECORD +257 -243
  252. {mage_ai-0.9.46.dist-info → mage_ai-0.9.47.dist-info}/WHEEL +1 -1
  253. mage_ai/server/frontend_dist/_next/static/9jB4XPuz6BzxBcG9VNao5/_buildManifest.js +0 -1
  254. mage_ai/server/frontend_dist/_next/static/chunks/3943-9e1105393a3be0de.js +0 -1
  255. mage_ai/server/frontend_dist/_next/static/chunks/4267-fd4d8049e83178de.js +0 -1
  256. mage_ai/server/frontend_dist/_next/static/chunks/5810-12eadc488265d55b.js +0 -1
  257. mage_ai/server/frontend_dist/_next/static/chunks/595-0d174b1f9fbfce4f.js +0 -1
  258. mage_ai/server/frontend_dist/_next/static/chunks/6333-bc1b433b428a9095.js +0 -1
  259. mage_ai/server/frontend_dist/_next/static/chunks/722-a1584445357a276c.js +0 -1
  260. mage_ai/server/frontend_dist/_next/static/chunks/8487-032ef9b17d20aad9.js +0 -1
  261. mage_ai/server/frontend_dist/_next/static/chunks/9264-1d4f0327d42fed91.js +0 -1
  262. mage_ai/server/frontend_dist/_next/static/chunks/9618-2c5045255ac5a6e7.js +0 -1
  263. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-ebef928183f9a3bb.js +0 -1
  264. mage_ai/server/frontend_dist/_next/static/chunks/pages/files-0f2d4be6fdca86ca.js +0 -1
  265. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-77edfa32d000e88b.js +0 -1
  266. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-hooks-e561ae38cf5592e8.js +0 -1
  267. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-10e9a2d19541caa2.js +0 -1
  268. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c8d3a5289ab93f88.js +0 -1
  269. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-ff7e9108502f5716.js +0 -1
  270. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-0691711636fa95c7.js +0 -1
  271. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-2914e326a5f1ffe0.js +0 -1
  272. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-3a7500e6e53084d3.js +0 -1
  273. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-c0e551d265a8d467.js +0 -1
  274. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-e47db5c3eaf683af.js +0 -1
  275. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/profile-55ac955dfa9a5a8d.js +0 -1
  276. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-29c92a9bc54ae5cd.js +0 -1
  277. mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-572d82d6eb7a5d43.js +0 -1
  278. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-2d26d80370a2e481.js +0 -1
  279. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3943-9e1105393a3be0de.js +0 -1
  280. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4267-fd4d8049e83178de.js +0 -1
  281. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5810-12eadc488265d55b.js +0 -1
  282. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/595-0d174b1f9fbfce4f.js +0 -1
  283. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6333-bc1b433b428a9095.js +0 -1
  284. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/722-a1584445357a276c.js +0 -1
  285. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8487-032ef9b17d20aad9.js +0 -1
  286. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9264-1d4f0327d42fed91.js +0 -1
  287. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9618-2c5045255ac5a6e7.js +0 -1
  288. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-ebef928183f9a3bb.js +0 -1
  289. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-0f2d4be6fdca86ca.js +0 -1
  290. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-77edfa32d000e88b.js +0 -1
  291. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks-e561ae38cf5592e8.js +0 -1
  292. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-10e9a2d19541caa2.js +0 -1
  293. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c8d3a5289ab93f88.js +0 -1
  294. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-ff7e9108502f5716.js +0 -1
  295. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-0691711636fa95c7.js +0 -1
  296. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-2914e326a5f1ffe0.js +0 -1
  297. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-3a7500e6e53084d3.js +0 -1
  298. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-c0e551d265a8d467.js +0 -1
  299. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-e47db5c3eaf683af.js +0 -1
  300. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-55ac955dfa9a5a8d.js +0 -1
  301. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-29c92a9bc54ae5cd.js +0 -1
  302. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-572d82d6eb7a5d43.js +0 -1
  303. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-2d26d80370a2e481.js +0 -1
  304. mage_ai/server/frontend_dist_base_path_template/_next/static/uPDjJYpJMst1q6psbRyte/_buildManifest.js +0 -1
  305. /mage_ai/server/frontend_dist/_next/static/{9jB4XPuz6BzxBcG9VNao5 → N3FS4bHv0jpYeeg672uYK}/_ssgManifest.js +0 -0
  306. /mage_ai/server/frontend_dist_base_path_template/_next/static/{uPDjJYpJMst1q6psbRyte → aoO6jYZLVlUGCCdY-wmy8}/_ssgManifest.js +0 -0
  307. {mage_ai-0.9.46.dist-info → mage_ai-0.9.47.dist-info}/LICENSE +0 -0
  308. {mage_ai-0.9.46.dist-info → mage_ai-0.9.47.dist-info}/entry_points.txt +0 -0
  309. {mage_ai-0.9.46.dist-info → mage_ai-0.9.47.dist-info}/top_level.txt +0 -0
@@ -28,6 +28,11 @@ class GlobalHookUtilsTest(AsyncDBTestCase):
28
28
  extracted_data = extract_valid_data(entity_name, data)
29
29
 
30
30
  if entity_name in types:
31
- self.assertEqual(extracted_data, dict(hook=data['hook']))
31
+ self.assertEqual(extracted_data, dict(
32
+ hook=data['hook'],
33
+ resource_id=data['resource_id'],
34
+ resource_parent_id=data['resource_parent_id'],
35
+ user=data['user'],
36
+ ))
32
37
  else:
33
38
  self.assertEqual(extracted_data, ignore_keys(data, ['mage']))
@@ -13,6 +13,7 @@ from mage_ai.data_preparation.models.pipeline import Pipeline
13
13
  from mage_ai.data_preparation.repo_manager import get_repo_config
14
14
  from mage_ai.data_preparation.variable_manager import VariableManager
15
15
  from mage_ai.tests.base_test import DBTestCase
16
+ from mage_ai.tests.factory import create_integration_pipeline_with_blocks
16
17
 
17
18
 
18
19
  class BlockTest(DBTestCase):
@@ -707,3 +708,28 @@ def test_output(output, *args) -> None:
707
708
  block3.upstream_block_uuids[1],
708
709
  'test_data_loader_1',
709
710
  )
711
+
712
+ def test_output_variables_for_integration_pipeline_blocks(self):
713
+ pipeline = create_integration_pipeline_with_blocks(
714
+ 'test integration pipeline',
715
+ repo_path=self.repo_path,
716
+ )
717
+ block = pipeline.get_block('test_integration_source')
718
+
719
+ df = pd.DataFrame(
720
+ [
721
+ [1, 'abc@xyz.com', '32132'],
722
+ [2, 'abc2@xyz.com', '12345'],
723
+ [3, 'test', '1234'],
724
+ [4, 'abc@test.net', 'abcde'],
725
+ [5, 'abc12345@', '54321'],
726
+ [6, 'abcdef@123.com', '56789'],
727
+ ],
728
+ columns=['id', 'email', 'zip_code'],
729
+ )
730
+
731
+ block.store_variables({
732
+ 'output_sample_data_stream1': df
733
+ })
734
+ output_variables = block.output_variables()
735
+ self.assertTrue('output_sample_data_stream1' in output_variables)
@@ -49,6 +49,8 @@ class PipelineTest(DBTestCase):
49
49
  run_pipeline_in_one_process=False,
50
50
  spark_config=dict(),
51
51
  type='python',
52
+ remote_variables_dir=None,
53
+ variables_dir=self.repo_path,
52
54
  blocks=[
53
55
  dict(
54
56
  language='python',
@@ -212,6 +214,8 @@ class PipelineTest(DBTestCase):
212
214
  run_pipeline_in_one_process=False,
213
215
  spark_config=dict(),
214
216
  type='python',
217
+ remote_variables_dir=None,
218
+ variables_dir=self.repo_path,
215
219
  blocks=[
216
220
  dict(
217
221
  language='python',
@@ -303,6 +307,8 @@ class PipelineTest(DBTestCase):
303
307
  run_pipeline_in_one_process=False,
304
308
  spark_config=dict(),
305
309
  type='python',
310
+ remote_variables_dir=None,
311
+ variables_dir=self.repo_path,
306
312
  blocks=[
307
313
  dict(
308
314
  language='python',
@@ -417,6 +423,8 @@ class PipelineTest(DBTestCase):
417
423
  run_pipeline_in_one_process=False,
418
424
  spark_config=dict(),
419
425
  type='python',
426
+ remote_variables_dir=None,
427
+ variables_dir=self.repo_path,
420
428
  blocks=[
421
429
  dict(
422
430
  language='python',
@@ -670,6 +678,8 @@ class PipelineTest(DBTestCase):
670
678
  type='integration',
671
679
  updated_at=None,
672
680
  uuid='test_pipeline_9',
681
+ remote_variables_dir=None,
682
+ variables_dir=self.repo_path,
673
683
  blocks=[
674
684
  dict(
675
685
  all_upstream_blocks_executed=True,
mage_ai/tests/factory.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import os
2
- from datetime import datetime
2
+ from datetime import datetime, timedelta
3
3
  from typing import Dict, Union
4
4
 
5
5
  from faker import Faker
@@ -10,7 +10,11 @@ from mage_ai.data_preparation.models.constants import BlockType, PipelineType
10
10
  from mage_ai.data_preparation.models.pipeline import Pipeline
11
11
  from mage_ai.data_preparation.models.triggers import ScheduleType
12
12
  from mage_ai.orchestration.db.models.oauth import User
13
- from mage_ai.orchestration.db.models.schedules import PipelineRun, PipelineSchedule
13
+ from mage_ai.orchestration.db.models.schedules import (
14
+ Backfill,
15
+ PipelineRun,
16
+ PipelineSchedule,
17
+ )
14
18
  from mage_ai.shared.hash import extract, ignore_keys, merge_dict
15
19
 
16
20
  faker = Faker()
@@ -159,6 +163,40 @@ def create_pipeline_run_with_schedule(
159
163
  return pipeline_run
160
164
 
161
165
 
166
+ def create_backfill(
167
+ pipeline_uuid: str,
168
+ end_datetime: datetime = None,
169
+ interval_type: Backfill.IntervalType = Backfill.IntervalType.DAY,
170
+ interval_units: int = 1,
171
+ pipeline_schedule_id: int = None,
172
+ start_datetime: datetime = None,
173
+ **kwargs,
174
+ ):
175
+ if start_datetime is None:
176
+ start_datetime = datetime.today() - timedelta(days=1)
177
+ if end_datetime is None:
178
+ end_datetime = datetime.today()
179
+ if pipeline_schedule_id is None:
180
+ pipeline_schedule = PipelineSchedule.create(
181
+ name=f'{pipeline_uuid}_trigger',
182
+ pipeline_uuid=pipeline_uuid,
183
+ schedule_type=ScheduleType.TIME,
184
+ )
185
+ pipeline_schedule_id = pipeline_schedule.id
186
+ backfill = Backfill.create(
187
+ end_datetime=end_datetime,
188
+ interval_type=interval_type,
189
+ interval_units=interval_units,
190
+ pipeline_uuid=pipeline_uuid,
191
+ pipeline_schedule_id=pipeline_schedule_id,
192
+ start_datetime=start_datetime,
193
+ status=Backfill.Status.INITIAL,
194
+ **kwargs,
195
+ )
196
+
197
+ return backfill
198
+
199
+
162
200
  def create_user(
163
201
  as_dict: bool = False,
164
202
  save: bool = True,
@@ -14,12 +14,14 @@ from mage_ai.data_preparation.models.triggers import (
14
14
  )
15
15
  from mage_ai.data_preparation.preferences import get_preferences
16
16
  from mage_ai.data_preparation.variable_manager import VariableManager
17
+ from mage_ai.orchestration.backfills.service import start_backfill
17
18
  from mage_ai.orchestration.db.models.schedules import (
19
+ Backfill,
18
20
  BlockRun,
19
21
  PipelineRun,
20
22
  PipelineSchedule,
21
23
  )
22
- from mage_ai.orchestration.job_manager import JobType
24
+ from mage_ai.orchestration.job_manager import JobManager, JobType
23
25
  from mage_ai.orchestration.notification.sender import NotificationSender
24
26
  from mage_ai.orchestration.pipeline_scheduler import (
25
27
  PipelineScheduler,
@@ -30,6 +32,7 @@ from mage_ai.shared.array import find
30
32
  from mage_ai.shared.hash import ignore_keys, merge_dict
31
33
  from mage_ai.tests.base_test import DBTestCase
32
34
  from mage_ai.tests.factory import (
35
+ create_backfill,
33
36
  create_integration_pipeline_with_blocks,
34
37
  create_pipeline_run_with_schedule,
35
38
  create_pipeline_with_blocks,
@@ -141,6 +144,84 @@ class PipelineSchedulerTests(DBTestCase):
141
144
  pipeline_run=pipeline_run,
142
145
  )
143
146
 
147
+ @freeze_time('2023-11-11 12:30:00')
148
+ def test_backfill_status_with_completed_pipeline_run(self):
149
+ pipeline_schedule = PipelineSchedule.create(
150
+ name='test_pipeline_trigger',
151
+ pipeline_uuid='test_pipeline',
152
+ )
153
+ backfill = create_backfill(
154
+ 'test_pipeline',
155
+ end_datetime=datetime.today(),
156
+ pipeline_schedule_id=pipeline_schedule.id,
157
+ start_datetime=datetime.today(),
158
+ )
159
+ pipeline_runs = start_backfill(backfill)
160
+ pipeline_run = pipeline_runs[0]
161
+ pipeline_run.update(status=PipelineRun.PipelineRunStatus.RUNNING)
162
+ scheduler = PipelineScheduler(pipeline_run=pipeline_run)
163
+ with patch.object(JobManager, 'add_job') as mock_add_br_job:
164
+ scheduler.schedule()
165
+ self.assertEqual(
166
+ backfill.status,
167
+ Backfill.Status.RUNNING,
168
+ )
169
+ mock_add_br_job.assert_called()
170
+
171
+ for b in pipeline_run.block_runs:
172
+ b.update(status=BlockRun.BlockRunStatus.COMPLETED)
173
+ scheduler.schedule()
174
+ self.assertEqual(
175
+ backfill.status,
176
+ Backfill.Status.COMPLETED,
177
+ )
178
+
179
+ @freeze_time('2023-11-11 12:30:00')
180
+ def test_backfill_status_with_failed_pipeline_run(self):
181
+ pipeline_schedule = PipelineSchedule.create(
182
+ name='test_pipeline_trigger',
183
+ pipeline_uuid='test_pipeline',
184
+ )
185
+ backfill = create_backfill(
186
+ 'test_pipeline',
187
+ end_datetime=datetime.today(),
188
+ pipeline_schedule_id=pipeline_schedule.id,
189
+ start_datetime=datetime.today(),
190
+ )
191
+ pipeline_runs = start_backfill(backfill)
192
+ pipeline_run = pipeline_runs[0]
193
+ scheduler = PipelineScheduler(pipeline_run=pipeline_run)
194
+
195
+ for b in pipeline_run.block_runs:
196
+ b.update(status=BlockRun.BlockRunStatus.FAILED)
197
+ scheduler.schedule()
198
+ # Backfill with 1 pipeline run that fails
199
+ self.assertEqual(
200
+ backfill.status,
201
+ Backfill.Status.FAILED,
202
+ )
203
+
204
+ # Retry failed pipeline run that was associated with the existing backfill
205
+ retried_pipeline_run = create_pipeline_run_with_schedule(
206
+ 'test_pipeline',
207
+ execution_date=pipeline_run.execution_date,
208
+ pipeline_schedule_id=pipeline_schedule.id,
209
+ )
210
+ scheduler2 = PipelineScheduler(pipeline_run=retried_pipeline_run)
211
+ backfill.update(status=Backfill.Status.INITIAL)
212
+ self.assertEqual(
213
+ backfill.status,
214
+ Backfill.Status.INITIAL,
215
+ )
216
+ # Retried pipeline run successfully completes, so backfill status updates to "completed"
217
+ for b in retried_pipeline_run.block_runs:
218
+ b.update(status=BlockRun.BlockRunStatus.COMPLETED)
219
+ scheduler2.schedule()
220
+ self.assertEqual(
221
+ backfill.status,
222
+ Backfill.Status.COMPLETED,
223
+ )
224
+
144
225
  @freeze_time('2023-10-11 12:13:14')
145
226
  def test_schedule_all_with_integration_pipeline(self):
146
227
  integration_pipeline_schedule = PipelineSchedule.create(
@@ -41,6 +41,14 @@ MOCK_POD_CONFIG = V1Pod(
41
41
  )],
42
42
  restart_policy='Never',
43
43
  service_account_name='old_service_account_name',
44
+ tolerations=[
45
+ {
46
+ 'effect': 'NoExecute',
47
+ 'key': 'node.kubernetes.io/not-ready',
48
+ 'operator': 'Exists',
49
+ 'toleration_seconds': 300,
50
+ },
51
+ ],
44
52
  volumes=[],
45
53
  )
46
54
  )
@@ -188,6 +196,14 @@ class JobManagerTests(TestCase):
188
196
  secret_ref=V1SecretEnvSource(name='mysecret', optional=None),
189
197
  ),
190
198
  ])
199
+ self.assertEqual(pod_config.tolerations, [
200
+ {
201
+ 'effect': 'NoExecute',
202
+ 'key': 'node.kubernetes.io/not-ready',
203
+ 'operator': 'Exists',
204
+ 'toleration_seconds': 300,
205
+ },
206
+ ])
191
207
 
192
208
  mock_client.V1ResourceRequirements.assert_called_once_with(
193
209
  limits=dict(
@@ -1,11 +1,15 @@
1
1
  import json
2
2
  import os
3
- import uuid
4
3
  from typing import Callable, Dict, List
5
4
 
6
5
  from mage_ai.authentication.permissions.constants import EntityName
7
6
  from mage_ai.data_preparation.models.constants import PipelineType
8
- from mage_ai.data_preparation.models.global_hooks.constants import HookOutputKey
7
+ from mage_ai.data_preparation.models.global_hooks.constants import (
8
+ HookOutputKey,
9
+ PredicateAndOrOperator,
10
+ PredicateOperator,
11
+ PredicateValueDataType,
12
+ )
9
13
  from mage_ai.data_preparation.models.global_hooks.models import (
10
14
  GlobalHooks,
11
15
  Hook,
@@ -13,10 +17,13 @@ from mage_ai.data_preparation.models.global_hooks.models import (
13
17
  HookOperation,
14
18
  HookOutputBlock,
15
19
  HookOutputSettings,
16
- HookPredicate,
17
20
  HookStage,
18
21
  HookStrategy,
19
22
  )
23
+ from mage_ai.data_preparation.models.global_hooks.predicates import (
24
+ HookPredicate,
25
+ PredicateValueType,
26
+ )
20
27
  from mage_ai.shared.hash import merge_dict
21
28
  from mage_ai.tests.api.operations.test_base import BaseApiTestCase
22
29
  from mage_ai.tests.factory import build_pipeline_with_blocks_and_content
@@ -62,8 +69,10 @@ def build_hooks(
62
69
  resource_type: EntityName = None,
63
70
  test_predicate_after: bool = False,
64
71
  test_predicate_before: bool = False,
65
- predicates_match: List[HookPredicate] = None,
66
- predicates_miss: List[HookPredicate] = None,
72
+ predicate_match: HookPredicate = None,
73
+ predicate_match_after: HookPredicate = None,
74
+ predicate_match_before: HookPredicate = None,
75
+ predicate_miss: HookPredicate = None,
67
76
  snapshot: bool = True,
68
77
  ) -> List[Hook]:
69
78
  if not global_hooks:
@@ -75,19 +84,37 @@ def build_hooks(
75
84
  type=pipeline.type,
76
85
  )
77
86
 
78
- if predicates_match is None:
79
- predicates_match = [[
80
- HookPredicate.load(resource=matching_predicate_resource),
81
- ]]
87
+ if predicate_match is None and predicate_match_after is None and predicate_match_before is None:
88
+ predicate_match = HookPredicate.load(
89
+ and_or_operator=PredicateAndOrOperator.AND,
90
+ predicates=[HookPredicate.load(
91
+ left_value=v,
92
+ left_value_type=PredicateValueType.load(
93
+ value_data_type=PredicateValueDataType.STRING,
94
+ ),
95
+ operator=PredicateOperator.EQUALS,
96
+ right_value=v,
97
+ right_value_type=PredicateValueType.load(
98
+ value_data_type=PredicateValueDataType.STRING,
99
+ ),
100
+ ) for v in matching_predicate_resource.values()],
101
+ )
82
102
 
83
- if predicates_miss is None:
84
- predicates_miss = [[
85
- HookPredicate.load(resource=dict(
86
- name=uuid.uuid4().hex,
87
- type=pipeline.type,
88
- )),
89
- predicates_match[0][0],
90
- ]]
103
+ if predicate_miss is None:
104
+ predicate_miss = HookPredicate.load(
105
+ and_or_operator=PredicateAndOrOperator.AND,
106
+ predicates=[HookPredicate.load(
107
+ left_value=v,
108
+ left_value_type=PredicateValueType.load(
109
+ value_data_type=PredicateValueDataType.STRING,
110
+ ),
111
+ operator=PredicateOperator.EQUALS,
112
+ right_value=None,
113
+ right_value_type=PredicateValueType.load(
114
+ value_data_type=PredicateValueDataType.STRING,
115
+ ),
116
+ ) for v in matching_predicate_resource.values()],
117
+ )
91
118
 
92
119
  if not operation_type:
93
120
  operation_type = HookOperation.DETAIL
@@ -120,9 +147,15 @@ def build_hooks(
120
147
  hook_setting = hook_settings[idx]
121
148
  hook_payload.update(hook_setting)
122
149
 
150
+ predicate_use = predicate_match
151
+ if predicate_match_after and HookStage.AFTER in hook_dict['stages']:
152
+ predicate_use = predicate_match_after
153
+ elif predicate_match_before and HookStage.BEFORE in hook_dict['stages']:
154
+ predicate_use = predicate_match_before
155
+
123
156
  hook = Hook.load(
124
157
  operation_type=operation_type,
125
- predicates=predicates_match + predicates_miss,
158
+ predicate=predicate_use,
126
159
  resource_type=resource_type,
127
160
  strategies=[HookStrategy.RAISE],
128
161
  uuid=f'hook{idx}_{test_case.faker.unique.name()}',
@@ -135,7 +168,7 @@ def build_hooks(
135
168
  **hook.to_dict(),
136
169
  )
137
170
  hook_miss.uuid = test_case.faker.unique.name()
138
- hook_miss.predicates = predicates_miss
171
+ hook_miss.predicate = predicate_miss
139
172
 
140
173
  if snapshot:
141
174
  hook.snapshot()
@@ -165,8 +198,10 @@ class GlobalHooksMixin(BaseApiTestCase):
165
198
  matching_predicate_resource: Dict = None,
166
199
  operation_type: HookOperation = None,
167
200
  pipeline_type: PipelineType = None,
168
- predicates_match: List[HookPredicate] = None,
169
- predicates_miss: List[HookPredicate] = None,
201
+ predicate_match: HookPredicate = None,
202
+ predicate_match_after: HookPredicate = None,
203
+ predicate_match_before: HookPredicate = None,
204
+ predicate_miss: HookPredicate = None,
170
205
  resource_type: EntityName = None,
171
206
  snapshot: bool = True,
172
207
  ):
@@ -259,8 +294,10 @@ class GlobalHooksMixin(BaseApiTestCase):
259
294
  matching_predicate_resource=matching_predicate_resource,
260
295
  operation_type=operation_type,
261
296
  pipeline=pipeline1,
262
- predicates_match=predicates_match,
263
- predicates_miss=predicates_miss,
297
+ predicate_match=predicate_match,
298
+ predicate_match_after=predicate_match_after,
299
+ predicate_match_before=predicate_match_before,
300
+ predicate_miss=predicate_miss,
264
301
  resource_type=resource_type,
265
302
  snapshot=snapshot,
266
303
  )
@@ -0,0 +1,36 @@
1
+ from unittest.mock import patch
2
+
3
+ from mage_ai.streaming.sinks.rabbitmq import RabbitMQSink
4
+ from mage_ai.tests.base_test import TestCase
5
+
6
+
7
+ class KinesisTests(TestCase):
8
+ def test_init(self):
9
+ with patch.object(RabbitMQSink, 'init_client') as mock_init_client:
10
+ RabbitMQSink(dict(
11
+ connector_type='rabbitmq',
12
+ connection_host='localhost',
13
+ connection_port='5672',
14
+ queue_name='queue_name',
15
+ username='guest',
16
+ password='guest',
17
+ amqp_url_virtual_host='%2f',
18
+ ))
19
+ mock_init_client.assert_called_once()
20
+
21
+ def test_init_invalid_config(self):
22
+ with patch.object(RabbitMQSink, 'init_client') as mock_init_client:
23
+ with self.assertRaises(Exception) as context:
24
+ RabbitMQSink(dict(
25
+ connector_type='rabbitmq',
26
+ connection_port='5672',
27
+ queue_name='queue_name',
28
+ username='guest',
29
+ password='guest',
30
+ amqp_url_virtual_host='%2f',
31
+ ))
32
+ self.assertTrue(
33
+ '__init__() missing 1 required positional argument: \'connection_host\''
34
+ in str(context.exception),
35
+ )
36
+ self.assertEqual(mock_init_client.call_count, 0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mage-ai
3
- Version: 0.9.46
3
+ Version: 0.9.47
4
4
  Summary: Mage is a tool for building and deploying data pipelines.
5
5
  Home-page: https://github.com/mage-ai/mage-ai
6
6
  Author: Mage
@@ -56,7 +56,7 @@ Requires-Dist: sqlalchemy <2.0.0,>=1.4.20
56
56
  Requires-Dist: terminado ==0.17.1
57
57
  Requires-Dist: thefuzz[speedup] ==0.19.0
58
58
  Requires-Dist: tornado ==6.1
59
- Requires-Dist: typer[all] ==0.7.0
59
+ Requires-Dist: typer[all] ==0.9.0
60
60
  Requires-Dist: typing-extensions ==4.5.0
61
61
  Provides-Extra: ai
62
62
  Requires-Dist: astor >=0.8.1 ; extra == 'ai'
@@ -74,6 +74,7 @@ Requires-Dist: azure-mgmt-containerinstance ==10.1.0 ; extra == 'all'
74
74
  Requires-Dist: azure-storage-blob ==12.14.1 ; extra == 'all'
75
75
  Requires-Dist: boto3 ==1.26.60 ; extra == 'all'
76
76
  Requires-Dist: botocore ==1.29.60 ; extra == 'all'
77
+ Requires-Dist: chroma >=0.4.17 ; extra == 'all'
77
78
  Requires-Dist: clickhouse-connect ==0.5.20 ; extra == 'all'
78
79
  Requires-Dist: confluent-avro ; extra == 'all'
79
80
  Requires-Dist: db-dtypes ==1.0.5 ; extra == 'all'
@@ -100,14 +101,14 @@ Requires-Dist: great-expectations ==0.15.50 ; extra == 'all'
100
101
  Requires-Dist: gspread ==5.7.2 ; extra == 'all'
101
102
  Requires-Dist: influxdb-client ==1.36.1 ; extra == 'all'
102
103
  Requires-Dist: kafka-python ==2.0.2 ; extra == 'all'
103
- Requires-Dist: kubernetes ==25.3.0 ; extra == 'all'
104
+ Requires-Dist: kubernetes >=28.1.0 ; extra == 'all'
104
105
  Requires-Dist: langchain >=0.0.222 ; extra == 'all'
105
106
  Requires-Dist: ldap3 ==2.9.1 ; extra == 'all'
106
107
  Requires-Dist: nats-py ==2.6.0 ; extra == 'all'
107
108
  Requires-Dist: nkeys ; extra == 'all'
108
109
  Requires-Dist: openai <1.0.0,>=0.27.8 ; extra == 'all'
109
110
  Requires-Dist: opensearch-py ==2.0.0 ; extra == 'all'
110
- Requires-Dist: opentelemetry-exporter-prometheus >=1.12.0rc1 ; extra == 'all'
111
+ Requires-Dist: opentelemetry-exporter-prometheus >=0.41b0 ; extra == 'all'
111
112
  Requires-Dist: opentelemetry-instrumentation-tornado >=0.41b0 ; extra == 'all'
112
113
  Requires-Dist: oracledb ==1.3.1 ; extra == 'all'
113
114
  Requires-Dist: pika ==1.3.1 ; extra == 'all'
@@ -134,6 +135,8 @@ Requires-Dist: azure-storage-blob ==12.14.1 ; extra == 'azure'
134
135
  Provides-Extra: bigquery
135
136
  Requires-Dist: google-cloud-bigquery ~=3.0 ; extra == 'bigquery'
136
137
  Requires-Dist: db-dtypes ==1.0.5 ; extra == 'bigquery'
138
+ Provides-Extra: chroma
139
+ Requires-Dist: chroma >=0.4.17 ; extra == 'chroma'
137
140
  Provides-Extra: clickhouse
138
141
  Requires-Dist: clickhouse-connect ==0.5.20 ; extra == 'clickhouse'
139
142
  Provides-Extra: dbt