mage-ai 0.9.70__py3-none-any.whl → 0.9.71__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 (568) hide show
  1. mage_ai/ai/utils/xgboost.py +222 -0
  2. mage_ai/api/errors.py +37 -25
  3. mage_ai/api/operations/base.py +13 -1
  4. mage_ai/api/parsers/PipelineScheduleParser.py +1 -1
  5. mage_ai/api/policies/BlockOutputPolicy.py +40 -17
  6. mage_ai/api/policies/GlobalDataProductPolicy.py +91 -41
  7. mage_ai/api/policies/KernelPolicy.py +55 -32
  8. mage_ai/api/policies/KernelProcessPolicy.py +56 -0
  9. mage_ai/api/policies/OutputPolicy.py +73 -41
  10. mage_ai/api/policies/PipelinePolicy.py +206 -138
  11. mage_ai/api/presenters/BlockLayoutItemPresenter.py +9 -7
  12. mage_ai/api/presenters/BlockPresenter.py +1 -1
  13. mage_ai/api/presenters/GlobalDataProductPresenter.py +6 -1
  14. mage_ai/api/presenters/KernelPresenter.py +5 -26
  15. mage_ai/api/presenters/KernelProcessPresenter.py +28 -0
  16. mage_ai/api/presenters/PipelinePresenter.py +18 -5
  17. mage_ai/api/presenters/StatusPresenter.py +2 -0
  18. mage_ai/api/presenters/SyncPresenter.py +25 -0
  19. mage_ai/api/resources/AutocompleteItemResource.py +1 -1
  20. mage_ai/api/resources/BlockLayoutItemResource.py +90 -44
  21. mage_ai/api/resources/BlockOutputResource.py +42 -9
  22. mage_ai/api/resources/BlockResource.py +4 -3
  23. mage_ai/api/resources/BlockRunResource.py +27 -22
  24. mage_ai/api/resources/ClusterResource.py +4 -1
  25. mage_ai/api/resources/CustomTemplateResource.py +34 -14
  26. mage_ai/api/resources/DataProviderResource.py +1 -1
  27. mage_ai/api/resources/ExecutionStateResource.py +3 -1
  28. mage_ai/api/resources/FileContentResource.py +8 -2
  29. mage_ai/api/resources/FileResource.py +10 -4
  30. mage_ai/api/resources/FileVersionResource.py +3 -1
  31. mage_ai/api/resources/GitBranchResource.py +46 -9
  32. mage_ai/api/resources/GlobalDataProductResource.py +44 -7
  33. mage_ai/api/resources/GlobalHookResource.py +4 -1
  34. mage_ai/api/resources/IntegrationDestinationResource.py +6 -2
  35. mage_ai/api/resources/IntegrationSourceResource.py +8 -4
  36. mage_ai/api/resources/IntegrationSourceStreamResource.py +6 -2
  37. mage_ai/api/resources/KernelProcessResource.py +44 -0
  38. mage_ai/api/resources/KernelResource.py +25 -3
  39. mage_ai/api/resources/OutputResource.py +33 -11
  40. mage_ai/api/resources/PageBlockLayoutResource.py +34 -23
  41. mage_ai/api/resources/PipelineInteractionResource.py +31 -15
  42. mage_ai/api/resources/PipelineResource.py +250 -123
  43. mage_ai/api/resources/PipelineRunResource.py +11 -3
  44. mage_ai/api/resources/PipelineScheduleResource.py +7 -2
  45. mage_ai/api/resources/PipelineTriggerResource.py +6 -1
  46. mage_ai/api/resources/ProjectResource.py +18 -7
  47. mage_ai/api/resources/SecretResource.py +1 -1
  48. mage_ai/api/resources/SeedResource.py +8 -1
  49. mage_ai/api/resources/StatusResource.py +21 -6
  50. mage_ai/api/resources/SyncResource.py +6 -8
  51. mage_ai/api/resources/VariableResource.py +46 -26
  52. mage_ai/api/resources/VersionControlProjectResource.py +9 -2
  53. mage_ai/api/resources/WidgetResource.py +1 -1
  54. mage_ai/api/resources/WorkspaceResource.py +1 -1
  55. mage_ai/api/views.py +47 -40
  56. mage_ai/authentication/permissions/seed.py +16 -2
  57. mage_ai/authentication/providers/oidc.py +21 -1
  58. mage_ai/autocomplete/utils.py +13 -9
  59. mage_ai/cache/base.py +1 -1
  60. mage_ai/cache/block.py +18 -12
  61. mage_ai/cache/block_action_object/__init__.py +32 -4
  62. mage_ai/cache/file.py +22 -19
  63. mage_ai/cache/pipeline.py +18 -12
  64. mage_ai/cli/main.py +1 -0
  65. mage_ai/cluster_manager/aws/emr_cluster_manager.py +9 -5
  66. mage_ai/cluster_manager/config.py +2 -2
  67. mage_ai/cluster_manager/manage.py +1 -1
  68. mage_ai/cluster_manager/workspace/base.py +1 -1
  69. mage_ai/command_center/applications/factory.py +10 -7
  70. mage_ai/command_center/files/factory.py +17 -15
  71. mage_ai/command_center/utils.py +25 -13
  72. mage_ai/data/__init__.py +0 -0
  73. mage_ai/data/constants.py +45 -0
  74. mage_ai/data/models/__init__.py +0 -0
  75. mage_ai/data/models/base.py +119 -0
  76. mage_ai/data/models/constants.py +1 -0
  77. mage_ai/data/models/generator.py +115 -0
  78. mage_ai/data/models/manager.py +168 -0
  79. mage_ai/data/models/pyarrow/__init__.py +0 -0
  80. mage_ai/data/models/pyarrow/record_batch.py +55 -0
  81. mage_ai/data/models/pyarrow/shared.py +21 -0
  82. mage_ai/data/models/pyarrow/table.py +8 -0
  83. mage_ai/data/models/reader.py +103 -0
  84. mage_ai/data/models/utils.py +59 -0
  85. mage_ai/data/models/writer.py +91 -0
  86. mage_ai/data/tabular/__init__.py +0 -0
  87. mage_ai/data/tabular/constants.py +23 -0
  88. mage_ai/data/tabular/mocks.py +19 -0
  89. mage_ai/data/tabular/models.py +126 -0
  90. mage_ai/data/tabular/reader.py +602 -0
  91. mage_ai/data/tabular/utils.py +102 -0
  92. mage_ai/data/tabular/writer.py +266 -0
  93. mage_ai/data/variables/__init__.py +0 -0
  94. mage_ai/data/variables/wrapper.py +54 -0
  95. mage_ai/data_cleaner/analysis/charts.py +61 -39
  96. mage_ai/data_cleaner/column_types/column_type_detector.py +53 -31
  97. mage_ai/data_cleaner/estimators/encoders.py +5 -2
  98. mage_ai/data_integrations/utils/scheduler.py +16 -11
  99. mage_ai/data_preparation/decorators.py +1 -0
  100. mage_ai/data_preparation/executors/block_executor.py +237 -155
  101. mage_ai/data_preparation/executors/streaming_pipeline_executor.py +1 -1
  102. mage_ai/data_preparation/git/__init__.py +27 -7
  103. mage_ai/data_preparation/git/api.py +7 -1
  104. mage_ai/data_preparation/git/utils.py +22 -16
  105. mage_ai/data_preparation/logging/logger_manager.py +4 -3
  106. mage_ai/data_preparation/models/block/__init__.py +1542 -878
  107. mage_ai/data_preparation/models/block/data_integration/mixins.py +4 -3
  108. mage_ai/data_preparation/models/block/dynamic/__init__.py +17 -6
  109. mage_ai/data_preparation/models/block/dynamic/child.py +41 -102
  110. mage_ai/data_preparation/models/block/dynamic/constants.py +1 -0
  111. mage_ai/data_preparation/models/block/dynamic/counter.py +296 -0
  112. mage_ai/data_preparation/models/block/dynamic/data.py +16 -0
  113. mage_ai/data_preparation/models/block/dynamic/factory.py +163 -0
  114. mage_ai/data_preparation/models/block/dynamic/models.py +19 -0
  115. mage_ai/data_preparation/models/block/dynamic/shared.py +92 -0
  116. mage_ai/data_preparation/models/block/dynamic/utils.py +291 -168
  117. mage_ai/data_preparation/models/block/dynamic/variables.py +384 -144
  118. mage_ai/data_preparation/models/block/dynamic/wrappers.py +77 -0
  119. mage_ai/data_preparation/models/block/extension/utils.py +10 -1
  120. mage_ai/data_preparation/models/block/global_data_product/__init__.py +10 -1
  121. mage_ai/data_preparation/models/block/integration/__init__.py +6 -2
  122. mage_ai/data_preparation/models/block/outputs.py +722 -0
  123. mage_ai/data_preparation/models/block/platform/mixins.py +7 -8
  124. mage_ai/data_preparation/models/block/r/__init__.py +56 -38
  125. mage_ai/data_preparation/models/block/settings/__init__.py +0 -0
  126. mage_ai/data_preparation/models/block/settings/dynamic/__init__.py +0 -0
  127. mage_ai/data_preparation/models/block/settings/dynamic/constants.py +7 -0
  128. mage_ai/data_preparation/models/block/settings/dynamic/mixins.py +118 -0
  129. mage_ai/data_preparation/models/block/settings/dynamic/models.py +31 -0
  130. mage_ai/data_preparation/models/block/settings/global_data_products/__init__.py +0 -0
  131. mage_ai/data_preparation/models/block/settings/global_data_products/mixins.py +20 -0
  132. mage_ai/data_preparation/models/block/settings/global_data_products/models.py +46 -0
  133. mage_ai/data_preparation/models/block/settings/variables/__init__.py +0 -0
  134. mage_ai/data_preparation/models/block/settings/variables/mixins.py +74 -0
  135. mage_ai/data_preparation/models/block/settings/variables/models.py +49 -0
  136. mage_ai/data_preparation/models/block/spark/mixins.py +2 -1
  137. mage_ai/data_preparation/models/block/sql/__init__.py +30 -5
  138. mage_ai/data_preparation/models/block/sql/utils/shared.py +21 -3
  139. mage_ai/data_preparation/models/block/utils.py +127 -70
  140. mage_ai/data_preparation/models/constants.py +19 -14
  141. mage_ai/data_preparation/models/custom_templates/custom_block_template.py +18 -13
  142. mage_ai/data_preparation/models/custom_templates/custom_pipeline_template.py +33 -16
  143. mage_ai/data_preparation/models/custom_templates/utils.py +1 -1
  144. mage_ai/data_preparation/models/file.py +41 -28
  145. mage_ai/data_preparation/models/global_data_product/__init__.py +88 -58
  146. mage_ai/data_preparation/models/global_hooks/models.py +1 -0
  147. mage_ai/data_preparation/models/interfaces.py +29 -0
  148. mage_ai/data_preparation/models/pipeline.py +365 -180
  149. mage_ai/data_preparation/models/pipelines/integration_pipeline.py +1 -2
  150. mage_ai/data_preparation/models/pipelines/seed.py +1 -1
  151. mage_ai/data_preparation/models/project/__init__.py +66 -18
  152. mage_ai/data_preparation/models/project/constants.py +2 -0
  153. mage_ai/data_preparation/models/triggers/__init__.py +120 -24
  154. mage_ai/data_preparation/models/utils.py +467 -17
  155. mage_ai/data_preparation/models/variable.py +1028 -137
  156. mage_ai/data_preparation/models/variables/__init__.py +0 -0
  157. mage_ai/data_preparation/models/variables/cache.py +149 -0
  158. mage_ai/data_preparation/models/variables/constants.py +72 -0
  159. mage_ai/data_preparation/models/variables/summarizer.py +336 -0
  160. mage_ai/data_preparation/models/variables/utils.py +77 -0
  161. mage_ai/data_preparation/models/widget/__init__.py +63 -41
  162. mage_ai/data_preparation/models/widget/charts.py +40 -27
  163. mage_ai/data_preparation/models/widget/constants.py +2 -0
  164. mage_ai/data_preparation/models/widget/utils.py +3 -3
  165. mage_ai/data_preparation/preferences.py +3 -3
  166. mage_ai/data_preparation/repo_manager.py +55 -21
  167. mage_ai/data_preparation/storage/base_storage.py +2 -2
  168. mage_ai/data_preparation/storage/gcs_storage.py +7 -4
  169. mage_ai/data_preparation/storage/local_storage.py +6 -3
  170. mage_ai/data_preparation/storage/s3_storage.py +5 -2
  171. mage_ai/data_preparation/templates/data_exporters/streaming/oracledb.yaml +8 -0
  172. mage_ai/data_preparation/variable_manager.py +281 -76
  173. mage_ai/io/base.py +3 -2
  174. mage_ai/io/bigquery.py +1 -0
  175. mage_ai/io/redshift.py +7 -5
  176. mage_ai/kernels/__init__.py +0 -0
  177. mage_ai/kernels/models.py +188 -0
  178. mage_ai/kernels/utils.py +169 -0
  179. mage_ai/orchestration/concurrency.py +6 -2
  180. mage_ai/orchestration/db/__init__.py +1 -0
  181. mage_ai/orchestration/db/migrations/versions/0227396a216c_add_userproject_table.py +38 -0
  182. mage_ai/orchestration/db/models/dynamic/__init__.py +0 -0
  183. mage_ai/orchestration/db/models/dynamic/controller.py +67 -0
  184. mage_ai/orchestration/db/models/oauth.py +2 -9
  185. mage_ai/orchestration/db/models/projects.py +10 -0
  186. mage_ai/orchestration/db/models/schedules.py +204 -187
  187. mage_ai/orchestration/db/models/schedules_project_platform.py +18 -12
  188. mage_ai/orchestration/db/models/utils.py +46 -5
  189. mage_ai/orchestration/metrics/pipeline_run.py +8 -9
  190. mage_ai/orchestration/notification/sender.py +1 -0
  191. mage_ai/orchestration/pipeline_scheduler_original.py +32 -8
  192. mage_ai/orchestration/pipeline_scheduler_project_platform.py +1 -1
  193. mage_ai/orchestration/run_status_checker.py +11 -4
  194. mage_ai/orchestration/triggers/api.py +12 -1
  195. mage_ai/presenters/charts/data_sources/base.py +4 -2
  196. mage_ai/presenters/charts/data_sources/block.py +15 -9
  197. mage_ai/presenters/charts/data_sources/chart_code.py +8 -5
  198. mage_ai/presenters/charts/data_sources/constants.py +1 -0
  199. mage_ai/presenters/charts/data_sources/system_metrics.py +22 -0
  200. mage_ai/presenters/interactions/models.py +11 -7
  201. mage_ai/presenters/pages/loaders/pipelines.py +5 -3
  202. mage_ai/presenters/pages/models/page_components/pipeline_schedules.py +3 -1
  203. mage_ai/presenters/utils.py +2 -0
  204. mage_ai/server/api/blocks.py +2 -1
  205. mage_ai/server/api/downloads.py +5 -1
  206. mage_ai/server/api/triggers.py +3 -1
  207. mage_ai/server/constants.py +1 -1
  208. mage_ai/server/frontend_dist/404.html +5 -5
  209. mage_ai/server/frontend_dist/_next/static/UZLabyPgcxtZvp0O0EUUS/_buildManifest.js +1 -0
  210. mage_ai/server/frontend_dist/_next/static/chunks/1376-22de38b4ad008d8a.js +1 -0
  211. mage_ai/server/frontend_dist/_next/static/chunks/{1557-b3502f3f1aa92ac7.js → 1557-25a7d985d5564fd3.js} +1 -1
  212. mage_ai/server/frontend_dist/_next/static/chunks/1668-30b4619b9534519b.js +1 -0
  213. mage_ai/server/frontend_dist/_next/static/chunks/1799-c42db95a015689ee.js +1 -0
  214. mage_ai/server/frontend_dist/_next/static/chunks/2996-2108b53b9d371d8d.js +1 -0
  215. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/3763-61b542dafdbf5754.js → frontend_dist/_next/static/chunks/3763-40780c6d1e4b261d.js} +1 -1
  216. mage_ai/server/frontend_dist/_next/static/chunks/3782-129dd2a2448a2e36.js +1 -0
  217. mage_ai/server/frontend_dist/_next/static/chunks/3958-bcdfa414ccfa1eb2.js +1 -0
  218. mage_ai/server/frontend_dist/_next/static/chunks/4168-97fd1578d1a38315.js +1 -0
  219. mage_ai/server/frontend_dist/_next/static/chunks/4982-fa5a238b139fbdd2.js +1 -0
  220. mage_ai/server/frontend_dist/_next/static/chunks/5699-176f445e1313f001.js +1 -0
  221. mage_ai/server/frontend_dist/_next/static/chunks/7162-7dd03f0f605de721.js +1 -0
  222. mage_ai/server/frontend_dist/_next/static/chunks/7779-68d2b72a90c5f925.js +1 -0
  223. mage_ai/server/frontend_dist/_next/static/chunks/7966-5446a8e43711e2f9.js +1 -0
  224. mage_ai/server/frontend_dist/_next/static/chunks/8023-6c2f172f48dcb99b.js +1 -0
  225. mage_ai/server/frontend_dist/_next/static/chunks/8095-c351b8a735d73e0c.js +1 -0
  226. mage_ai/server/frontend_dist/_next/static/chunks/{main-77fe248a6fbd12d8.js → main-b99d4e30a88d9dc7.js} +1 -1
  227. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-9fe2d9d07c94e968.js +1 -0
  228. mage_ai/server/frontend_dist/_next/static/chunks/pages/{block-layout-14f952f66964022f.js → block-layout-7f4b735c67115df5.js} +1 -1
  229. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-e7d48e6b0c3068ac.js +1 -0
  230. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-b943f31f050fc3a4.js +1 -0
  231. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/overview-597b74828bf105db.js → frontend_dist/_next/static/chunks/pages/overview-9f1ac4ec003884f3.js} +1 -1
  232. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-7181b086c93784d2.js → [...slug]-7e737f6fc7e83e9b.js} +1 -1
  233. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-d94488e3f2eeef36.js +1 -0
  234. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-cc641a7fa8473796.js +1 -0
  235. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-a5c0362763a21fa8.js → block-runs-284309877f3c5a5a.js} +1 -1
  236. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-26250e5335194ade.js +1 -0
  237. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-7acc7afc00df17c2.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-5f4c8128b2413fd8.js} +1 -1
  238. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-4ebfc8e400315dda.js +1 -0
  239. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-e5e0150a256aadb3.js +1 -0
  240. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/{profile-3f0df3decc856ee9.js → profile-3ae43c932537b254.js} +1 -1
  241. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-32985f3f7c7dd3ab.js → frontend_dist/_next/static/chunks/pages/settings/platform/preferences-b603d7fe4b175256.js} +1 -1
  242. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-c2e9ef989c8bfa73.js → frontend_dist/_next/static/chunks/pages/settings/platform/settings-319ddbabc239e91b.js} +1 -1
  243. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-47b64ced27c24985.js → [...slug]-5c360f72e4498855.js} +1 -1
  244. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{permissions-e5a4d3d815cec25d.js → permissions-fb29fa6c2bd90bb0.js} +1 -1
  245. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-3b76fa959ffa09d3.js +1 -0
  246. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-379e1ee292504842.js → [...slug]-3b787b42f1093b1f.js} +1 -1
  247. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles-0b83fbdd39e85f5b.js +1 -0
  248. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-a1e6950974d643a8.js +1 -0
  249. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/{[...slug]-2af9afbe727d88aa.js → [...slug]-0aa019d87db8b0b8.js} +1 -1
  250. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{users-a4db8710f703c729.js → users-88c694d19207f2ec.js} +1 -1
  251. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-31d0d50f7f30462b.js +1 -0
  252. mage_ai/server/frontend_dist/_next/static/chunks/{webpack-d079359c241db804.js → webpack-ac7fdc472bedf682.js} +1 -1
  253. mage_ai/server/frontend_dist/block-layout.html +3 -3
  254. mage_ai/server/frontend_dist/compute.html +6 -6
  255. mage_ai/server/frontend_dist/files.html +6 -6
  256. mage_ai/server/frontend_dist/global-data-products/[...slug].html +6 -6
  257. mage_ai/server/frontend_dist/global-data-products.html +6 -6
  258. mage_ai/server/frontend_dist/global-hooks/[...slug].html +6 -6
  259. mage_ai/server/frontend_dist/global-hooks.html +6 -6
  260. mage_ai/server/frontend_dist/index.html +3 -3
  261. mage_ai/server/frontend_dist/manage/files.html +6 -6
  262. mage_ai/server/frontend_dist/manage/settings.html +6 -6
  263. mage_ai/server/frontend_dist/manage/users/[user].html +6 -6
  264. mage_ai/server/frontend_dist/manage/users/new.html +6 -6
  265. mage_ai/server/frontend_dist/manage/users.html +6 -6
  266. mage_ai/server/frontend_dist/manage.html +6 -6
  267. mage_ai/server/frontend_dist/oauth.html +5 -5
  268. mage_ai/server/frontend_dist/overview.html +6 -6
  269. mage_ai/server/frontend_dist/pipeline-runs.html +6 -6
  270. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +6 -6
  271. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +6 -6
  272. mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +6 -6
  273. mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +3 -3
  274. mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +6 -6
  275. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +6 -6
  276. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +6 -6
  277. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +6 -6
  278. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +6 -6
  279. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +6 -6
  280. mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +6 -6
  281. mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +6 -6
  282. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +6 -6
  283. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +6 -6
  284. mage_ai/server/frontend_dist/pipelines/[pipeline].html +3 -3
  285. mage_ai/server/frontend_dist/pipelines.html +6 -6
  286. mage_ai/server/frontend_dist/platform/global-hooks/[...slug].html +6 -6
  287. mage_ai/server/frontend_dist/platform/global-hooks.html +6 -6
  288. mage_ai/server/frontend_dist/settings/account/profile.html +6 -6
  289. mage_ai/server/frontend_dist/settings/platform/preferences.html +6 -6
  290. mage_ai/server/frontend_dist/settings/platform/settings.html +6 -6
  291. mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +6 -6
  292. mage_ai/server/frontend_dist/settings/workspace/permissions.html +6 -6
  293. mage_ai/server/frontend_dist/settings/workspace/preferences.html +6 -6
  294. mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +6 -6
  295. mage_ai/server/frontend_dist/settings/workspace/roles.html +6 -6
  296. mage_ai/server/frontend_dist/settings/workspace/sync-data.html +6 -6
  297. mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +6 -6
  298. mage_ai/server/frontend_dist/settings/workspace/users.html +6 -6
  299. mage_ai/server/frontend_dist/settings.html +3 -3
  300. mage_ai/server/frontend_dist/sign-in.html +12 -12
  301. mage_ai/server/frontend_dist/templates/[...slug].html +6 -6
  302. mage_ai/server/frontend_dist/templates.html +6 -6
  303. mage_ai/server/frontend_dist/terminal.html +6 -6
  304. mage_ai/server/frontend_dist/test.html +3 -3
  305. mage_ai/server/frontend_dist/triggers.html +6 -6
  306. mage_ai/server/frontend_dist/version-control.html +6 -6
  307. mage_ai/server/frontend_dist_base_path_template/404.html +5 -5
  308. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1376-22de38b4ad008d8a.js +1 -0
  309. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1557-b3502f3f1aa92ac7.js → 1557-25a7d985d5564fd3.js} +1 -1
  310. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1668-30b4619b9534519b.js +1 -0
  311. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1799-c42db95a015689ee.js +1 -0
  312. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2996-2108b53b9d371d8d.js +1 -0
  313. mage_ai/server/{frontend_dist/_next/static/chunks/3763-61b542dafdbf5754.js → frontend_dist_base_path_template/_next/static/chunks/3763-40780c6d1e4b261d.js} +1 -1
  314. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-129dd2a2448a2e36.js +1 -0
  315. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3958-bcdfa414ccfa1eb2.js +1 -0
  316. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4168-97fd1578d1a38315.js +1 -0
  317. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4982-fa5a238b139fbdd2.js +1 -0
  318. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5699-176f445e1313f001.js +1 -0
  319. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7162-7dd03f0f605de721.js +1 -0
  320. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7779-68d2b72a90c5f925.js +1 -0
  321. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7966-5446a8e43711e2f9.js +1 -0
  322. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8023-6c2f172f48dcb99b.js +1 -0
  323. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8095-c351b8a735d73e0c.js +1 -0
  324. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{main-70b78159c2bb3fe1.js → main-384298e9133cec76.js} +1 -1
  325. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-13a578bce3b7f30c.js +1 -0
  326. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{block-layout-14f952f66964022f.js → block-layout-7f4b735c67115df5.js} +1 -1
  327. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-e7d48e6b0c3068ac.js +1 -0
  328. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-b943f31f050fc3a4.js +1 -0
  329. mage_ai/server/{frontend_dist/_next/static/chunks/pages/overview-597b74828bf105db.js → frontend_dist_base_path_template/_next/static/chunks/pages/overview-9f1ac4ec003884f3.js} +1 -1
  330. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-7181b086c93784d2.js → [...slug]-7e737f6fc7e83e9b.js} +1 -1
  331. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-d94488e3f2eeef36.js +1 -0
  332. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-cc641a7fa8473796.js +1 -0
  333. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-a5c0362763a21fa8.js → block-runs-284309877f3c5a5a.js} +1 -1
  334. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-26250e5335194ade.js +1 -0
  335. mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-7acc7afc00df17c2.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-5f4c8128b2413fd8.js} +1 -1
  336. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-4ebfc8e400315dda.js +1 -0
  337. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-e5e0150a256aadb3.js +1 -0
  338. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/{profile-3f0df3decc856ee9.js → profile-3ae43c932537b254.js} +1 -1
  339. mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/platform/preferences-32985f3f7c7dd3ab.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-b603d7fe4b175256.js} +1 -1
  340. mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/platform/settings-c2e9ef989c8bfa73.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-319ddbabc239e91b.js} +1 -1
  341. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-47b64ced27c24985.js → [...slug]-5c360f72e4498855.js} +1 -1
  342. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{permissions-e5a4d3d815cec25d.js → permissions-fb29fa6c2bd90bb0.js} +1 -1
  343. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-3b76fa959ffa09d3.js +1 -0
  344. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-379e1ee292504842.js → [...slug]-3b787b42f1093b1f.js} +1 -1
  345. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles-0b83fbdd39e85f5b.js +1 -0
  346. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-a1e6950974d643a8.js +1 -0
  347. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/{[...slug]-2af9afbe727d88aa.js → [...slug]-0aa019d87db8b0b8.js} +1 -1
  348. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{users-a4db8710f703c729.js → users-88c694d19207f2ec.js} +1 -1
  349. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-31d0d50f7f30462b.js +1 -0
  350. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-68c003fb6a175cd7.js → webpack-481689d9989710cd.js} +1 -1
  351. mage_ai/server/frontend_dist_base_path_template/_next/static/kcptwoOU-JJJg6Vwpkfmx/_buildManifest.js +1 -0
  352. mage_ai/server/frontend_dist_base_path_template/block-layout.html +3 -3
  353. mage_ai/server/frontend_dist_base_path_template/compute.html +6 -6
  354. mage_ai/server/frontend_dist_base_path_template/files.html +6 -6
  355. mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +6 -6
  356. mage_ai/server/frontend_dist_base_path_template/global-data-products.html +6 -6
  357. mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +6 -6
  358. mage_ai/server/frontend_dist_base_path_template/global-hooks.html +6 -6
  359. mage_ai/server/frontend_dist_base_path_template/index.html +3 -3
  360. mage_ai/server/frontend_dist_base_path_template/manage/files.html +6 -6
  361. mage_ai/server/frontend_dist_base_path_template/manage/settings.html +6 -6
  362. mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +6 -6
  363. mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +6 -6
  364. mage_ai/server/frontend_dist_base_path_template/manage/users.html +6 -6
  365. mage_ai/server/frontend_dist_base_path_template/manage.html +6 -6
  366. mage_ai/server/frontend_dist_base_path_template/oauth.html +5 -5
  367. mage_ai/server/frontend_dist_base_path_template/overview.html +6 -6
  368. mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +6 -6
  369. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +6 -6
  370. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +6 -6
  371. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +6 -6
  372. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +3 -3
  373. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +6 -6
  374. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +6 -6
  375. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +6 -6
  376. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +6 -6
  377. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +6 -6
  378. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +6 -6
  379. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +6 -6
  380. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +6 -6
  381. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +6 -6
  382. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +6 -6
  383. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +3 -3
  384. mage_ai/server/frontend_dist_base_path_template/pipelines.html +6 -6
  385. mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +6 -6
  386. mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +6 -6
  387. mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +6 -6
  388. mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +6 -6
  389. mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +6 -6
  390. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +6 -6
  391. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +6 -6
  392. mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +6 -6
  393. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +6 -6
  394. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +6 -6
  395. mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +6 -6
  396. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +6 -6
  397. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +6 -6
  398. mage_ai/server/frontend_dist_base_path_template/settings.html +3 -3
  399. mage_ai/server/frontend_dist_base_path_template/sign-in.html +12 -12
  400. mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +6 -6
  401. mage_ai/server/frontend_dist_base_path_template/templates.html +6 -6
  402. mage_ai/server/frontend_dist_base_path_template/terminal.html +6 -6
  403. mage_ai/server/frontend_dist_base_path_template/test.html +3 -3
  404. mage_ai/server/frontend_dist_base_path_template/triggers.html +6 -6
  405. mage_ai/server/frontend_dist_base_path_template/version-control.html +6 -6
  406. mage_ai/server/kernel_output_parser.py +4 -1
  407. mage_ai/server/scheduler_manager.py +9 -0
  408. mage_ai/server/server.py +35 -31
  409. mage_ai/server/utils/custom_output.py +284 -0
  410. mage_ai/server/utils/execute_custom_code.py +245 -0
  411. mage_ai/server/utils/output_display.py +123 -289
  412. mage_ai/server/websocket_server.py +116 -69
  413. mage_ai/services/k8s/config.py +23 -0
  414. mage_ai/services/k8s/job_manager.py +6 -1
  415. mage_ai/services/ssh/aws/emr/utils.py +8 -8
  416. mage_ai/settings/keys/auth.py +1 -0
  417. mage_ai/settings/platform/__init__.py +159 -38
  418. mage_ai/settings/platform/constants.py +5 -0
  419. mage_ai/settings/platform/utils.py +53 -10
  420. mage_ai/settings/repo.py +26 -12
  421. mage_ai/settings/server.py +128 -37
  422. mage_ai/shared/array.py +24 -1
  423. mage_ai/shared/complex.py +45 -0
  424. mage_ai/shared/config.py +2 -1
  425. mage_ai/shared/custom_logger.py +11 -0
  426. mage_ai/shared/dates.py +10 -6
  427. mage_ai/shared/files.py +63 -8
  428. mage_ai/shared/hash.py +33 -9
  429. mage_ai/shared/io.py +9 -5
  430. mage_ai/shared/models.py +82 -24
  431. mage_ai/shared/outputs.py +87 -0
  432. mage_ai/shared/parsers.py +141 -15
  433. mage_ai/shared/path_fixer.py +11 -7
  434. mage_ai/shared/singletons/__init__.py +0 -0
  435. mage_ai/shared/singletons/base.py +47 -0
  436. mage_ai/shared/singletons/memory.py +38 -0
  437. mage_ai/shared/strings.py +34 -1
  438. mage_ai/shared/yaml.py +24 -0
  439. mage_ai/streaming/sinks/oracledb.py +57 -0
  440. mage_ai/streaming/sinks/sink_factory.py +4 -0
  441. mage_ai/system/__init__.py +0 -0
  442. mage_ai/system/constants.py +14 -0
  443. mage_ai/system/memory/__init__.py +0 -0
  444. mage_ai/system/memory/constants.py +1 -0
  445. mage_ai/system/memory/manager.py +174 -0
  446. mage_ai/system/memory/presenters.py +158 -0
  447. mage_ai/system/memory/process.py +216 -0
  448. mage_ai/system/memory/samples.py +13 -0
  449. mage_ai/system/memory/utils.py +656 -0
  450. mage_ai/system/memory/wrappers.py +177 -0
  451. mage_ai/system/models.py +58 -0
  452. mage_ai/system/storage/__init__.py +0 -0
  453. mage_ai/system/storage/utils.py +29 -0
  454. mage_ai/tests/api/endpoints/mixins.py +2 -2
  455. mage_ai/tests/api/endpoints/test_blocks.py +2 -1
  456. mage_ai/tests/api/endpoints/test_custom_designs.py +4 -4
  457. mage_ai/tests/api/endpoints/test_pipeline_runs.py +2 -2
  458. mage_ai/tests/api/endpoints/test_projects.py +2 -1
  459. mage_ai/tests/api/operations/base/test_base.py +27 -27
  460. mage_ai/tests/api/operations/base/test_base_with_user_authentication.py +27 -27
  461. mage_ai/tests/api/operations/base/test_base_with_user_permissions.py +23 -23
  462. mage_ai/tests/api/operations/test_syncs.py +6 -4
  463. mage_ai/tests/api/resources/test_pipeline_resource.py +9 -2
  464. mage_ai/tests/authentication/providers/test_oidc.py +59 -0
  465. mage_ai/tests/base_test.py +2 -2
  466. mage_ai/tests/data/__init__.py +0 -0
  467. mage_ai/tests/data/models/__init__.py +0 -0
  468. mage_ai/tests/data_preparation/executors/test_block_executor.py +23 -16
  469. mage_ai/tests/data_preparation/git/test_git.py +4 -1
  470. mage_ai/tests/data_preparation/models/block/dynamic/test_combos.py +305 -0
  471. mage_ai/tests/data_preparation/models/block/dynamic/test_counter.py +212 -0
  472. mage_ai/tests/data_preparation/models/block/dynamic/test_factory.py +360 -0
  473. mage_ai/tests/data_preparation/models/block/dynamic/test_variables.py +332 -0
  474. mage_ai/tests/data_preparation/models/block/hook/test_hook_block.py +2 -2
  475. mage_ai/tests/data_preparation/models/block/platform/test_mixins.py +1 -1
  476. mage_ai/tests/data_preparation/models/block/sql/utils/test_shared.py +26 -1
  477. mage_ai/tests/data_preparation/models/block/test_global_data_product.py +3 -2
  478. mage_ai/tests/data_preparation/models/custom_templates/test_utils.py +5 -4
  479. mage_ai/tests/data_preparation/models/global_hooks/test_hook.py +3 -0
  480. mage_ai/tests/data_preparation/models/global_hooks/test_predicates.py +9 -3
  481. mage_ai/tests/data_preparation/models/test_block.py +115 -120
  482. mage_ai/tests/data_preparation/models/test_blocks_helper.py +114 -0
  483. mage_ai/tests/data_preparation/models/test_global_data_product.py +41 -24
  484. mage_ai/tests/data_preparation/models/test_pipeline.py +9 -6
  485. mage_ai/tests/data_preparation/models/test_project.py +4 -1
  486. mage_ai/tests/data_preparation/models/test_utils.py +80 -0
  487. mage_ai/tests/data_preparation/models/test_variable.py +242 -69
  488. mage_ai/tests/data_preparation/models/variables/__init__.py +0 -0
  489. mage_ai/tests/data_preparation/models/variables/test_summarizer.py +481 -0
  490. mage_ai/tests/data_preparation/storage/shared/__init__.py +0 -0
  491. mage_ai/tests/data_preparation/test_repo_manager.py +6 -7
  492. mage_ai/tests/data_preparation/test_variable_manager.py +57 -48
  493. mage_ai/tests/factory.py +64 -43
  494. mage_ai/tests/orchestration/db/models/test_schedules.py +3 -3
  495. mage_ai/tests/orchestration/db/models/test_schedules_dynamic_blocks.py +279 -0
  496. mage_ai/tests/orchestration/test_pipeline_scheduler.py +1 -0
  497. mage_ai/tests/orchestration/triggers/test_global_data_product.py +3 -2
  498. mage_ai/tests/orchestration/triggers/test_utils.py +3 -2
  499. mage_ai/tests/services/k8s/test_job_manager.py +18 -0
  500. mage_ai/tests/streaming/sinks/test_oracledb.py +38 -0
  501. mage_ai/tests/test_shared.py +61 -0
  502. mage_ai/usage_statistics/logger.py +7 -2
  503. mage_ai/utils/code.py +33 -19
  504. {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/METADATA +5 -2
  505. {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/RECORD +513 -417
  506. mage_ai/data_preparation/models/global_data_product/constants.py +0 -6
  507. mage_ai/server/frontend_dist/_next/static/RhDiJSkcjCsh4xxX4BFBk/_buildManifest.js +0 -1
  508. mage_ai/server/frontend_dist/_next/static/chunks/2631-b9f9bea3f1cf906d.js +0 -1
  509. mage_ai/server/frontend_dist/_next/static/chunks/3782-ef4cd4f0b52072d0.js +0 -1
  510. mage_ai/server/frontend_dist/_next/static/chunks/4783-422429203610c318.js +0 -1
  511. mage_ai/server/frontend_dist/_next/static/chunks/5699-6d708c6b2153ea08.js +0 -1
  512. mage_ai/server/frontend_dist/_next/static/chunks/635-0d6b7c8804bcd2dc.js +0 -1
  513. mage_ai/server/frontend_dist/_next/static/chunks/7022-0d52dd8868621fb0.js +0 -1
  514. mage_ai/server/frontend_dist/_next/static/chunks/7361-8a23dd8360593e7a.js +0 -1
  515. mage_ai/server/frontend_dist/_next/static/chunks/7966-b9b85ba10667e654.js +0 -1
  516. mage_ai/server/frontend_dist/_next/static/chunks/8095-bdce03896ef9639a.js +0 -1
  517. mage_ai/server/frontend_dist/_next/static/chunks/8146-6bed4e7401e067e6.js +0 -1
  518. mage_ai/server/frontend_dist/_next/static/chunks/9265-d2a1aaec75ec69b8.js +0 -1
  519. mage_ai/server/frontend_dist/_next/static/chunks/9440-4069842b90d4b801.js +0 -1
  520. mage_ai/server/frontend_dist/_next/static/chunks/9832-67896490f6e8a014.js +0 -1
  521. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-2a69553d8c6eeb53.js +0 -1
  522. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-591abd392dc50ed4.js +0 -1
  523. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-78e8e88f2a757a18.js +0 -1
  524. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-95ffcd3e2b27e567.js +0 -1
  525. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-b645a6d13ab9fe3a.js +0 -1
  526. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-1ed9045b2f1dfd65.js +0 -1
  527. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1417ad1c821d720a.js +0 -1
  528. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-59aca25a5b1d3998.js +0 -1
  529. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-349af617d05f001b.js +0 -1
  530. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles-36fa165a48af586b.js +0 -1
  531. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-60d01d3887e31136.js +0 -1
  532. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-3433c8b22e8342aa.js +0 -1
  533. mage_ai/server/frontend_dist_base_path_template/_next/static/TdpLLFome13qvM0gXvpHs/_buildManifest.js +0 -1
  534. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2631-b9f9bea3f1cf906d.js +0 -1
  535. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-ef4cd4f0b52072d0.js +0 -1
  536. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4783-422429203610c318.js +0 -1
  537. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5699-6d708c6b2153ea08.js +0 -1
  538. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/635-0d6b7c8804bcd2dc.js +0 -1
  539. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7022-0d52dd8868621fb0.js +0 -1
  540. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7361-8a23dd8360593e7a.js +0 -1
  541. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7966-b9b85ba10667e654.js +0 -1
  542. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8095-bdce03896ef9639a.js +0 -1
  543. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8146-6bed4e7401e067e6.js +0 -1
  544. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9265-d2a1aaec75ec69b8.js +0 -1
  545. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9440-4069842b90d4b801.js +0 -1
  546. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9832-67896490f6e8a014.js +0 -1
  547. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-2a69553d8c6eeb53.js +0 -1
  548. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-591abd392dc50ed4.js +0 -1
  549. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-78e8e88f2a757a18.js +0 -1
  550. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-95ffcd3e2b27e567.js +0 -1
  551. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-b645a6d13ab9fe3a.js +0 -1
  552. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-1ed9045b2f1dfd65.js +0 -1
  553. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1417ad1c821d720a.js +0 -1
  554. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-59aca25a5b1d3998.js +0 -1
  555. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-349af617d05f001b.js +0 -1
  556. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles-36fa165a48af586b.js +0 -1
  557. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-60d01d3887e31136.js +0 -1
  558. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-3433c8b22e8342aa.js +0 -1
  559. mage_ai/shared/memory.py +0 -90
  560. mage_ai/tests/data_preparation/models/block/dynamic/test_dynamic_helpers.py +0 -48
  561. /mage_ai/{tests/data_preparation/shared → ai/utils}/__init__.py +0 -0
  562. /mage_ai/server/frontend_dist/_next/static/{RhDiJSkcjCsh4xxX4BFBk → UZLabyPgcxtZvp0O0EUUS}/_ssgManifest.js +0 -0
  563. /mage_ai/server/frontend_dist_base_path_template/_next/static/{TdpLLFome13qvM0gXvpHs → kcptwoOU-JJJg6Vwpkfmx}/_ssgManifest.js +0 -0
  564. /mage_ai/tests/data_preparation/{shared → storage/shared}/test_secrets.py +0 -0
  565. {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/LICENSE +0 -0
  566. {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/WHEEL +0 -0
  567. {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/entry_points.txt +0 -0
  568. {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/top_level.txt +0 -0
@@ -61,6 +61,7 @@ from mage_ai.data_preparation.variable_manager import get_global_variables
61
61
  from mage_ai.orchestration.db import db_connection, safe_db_query
62
62
  from mage_ai.orchestration.db.errors import ValidationError
63
63
  from mage_ai.orchestration.db.models.base import Base, BaseModel, classproperty
64
+ from mage_ai.orchestration.db.models.dynamic.controller import is_ready_to_process_data
64
65
  from mage_ai.orchestration.db.models.schedules_project_platform import (
65
66
  BlockRunProjectPlatformMixin,
66
67
  PipelineRunProjectPlatformMixin,
@@ -105,7 +106,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
105
106
  event_matchers = relationship(
106
107
  'EventMatcher',
107
108
  secondary=pipeline_schedule_event_matcher_association_table,
108
- back_populates='pipeline_schedules'
109
+ back_populates='pipeline_schedules',
109
110
  )
110
111
 
111
112
  @classproperty
@@ -123,10 +124,13 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
123
124
  @validates('name')
124
125
  def validate_name(self, key, value):
125
126
  if not value or len(value) == 0:
126
- raise ValidationError(f'{key} cannot be empty.', metadata=dict(
127
- key=key,
128
- value=value,
129
- ))
127
+ raise ValidationError(
128
+ f'{key} cannot be empty.',
129
+ metadata=dict(
130
+ key=key,
131
+ value=value,
132
+ ),
133
+ )
130
134
 
131
135
  return value
132
136
 
@@ -140,33 +144,26 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
140
144
  @classmethod
141
145
  def fetch_latest_pipeline_runs_without_retries(self, ids: List[int]) -> List:
142
146
  sub_query = (
143
- PipelineRun.
144
- select(
147
+ PipelineRun.select(
145
148
  PipelineRun.id,
146
149
  PipelineRun.execution_date,
147
150
  PipelineRun.started_at,
148
151
  PipelineRun.status,
149
152
  (
150
- func.
151
- row_number().
152
- over(
153
+ func.row_number()
154
+ .over(
153
155
  partition_by=PipelineRun.execution_date,
154
- order_by=(PipelineRun.started_at.desc(), PipelineRun.id.desc())
155
- ).
156
- label('n_row_number')
157
- )
158
- ).
159
- filter(
156
+ order_by=(PipelineRun.started_at.desc(), PipelineRun.id.desc()),
157
+ )
158
+ .label('n_row_number')
159
+ ),
160
+ ).filter(
160
161
  PipelineRun.pipeline_schedule_id.in_(ids),
161
162
  )
162
163
  ).subquery()
163
164
 
164
- query = (
165
- PipelineRun.
166
- select(sub_query).
167
- where(
168
- text('n_row_number = 1'),
169
- )
165
+ query = PipelineRun.select(sub_query).where(
166
+ text('n_row_number = 1'),
170
167
  )
171
168
 
172
169
  query.cache = True
@@ -182,7 +179,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
182
179
  if project_platform_activated():
183
180
  return self.pipeline_project_platform
184
181
 
185
- return Pipeline.get(self.pipeline_uuid)
182
+ return Pipeline.get(self.pipeline_uuid, repo_path=get_repo_path())
186
183
 
187
184
  @property
188
185
  def pipeline_in_progress_runs_count(self) -> int:
@@ -193,12 +190,10 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
193
190
  PipelineRun.select(func.count(PipelineRun.id))
194
191
  .filter(
195
192
  PipelineRun.pipeline_schedule_id == self.id,
196
- PipelineRun.status.in_(
197
- [
198
- PipelineRun.PipelineRunStatus.INITIAL,
199
- PipelineRun.PipelineRunStatus.RUNNING,
200
- ]
201
- ),
193
+ PipelineRun.status.in_([
194
+ PipelineRun.PipelineRunStatus.INITIAL,
195
+ PipelineRun.PipelineRunStatus.RUNNING,
196
+ ]),
202
197
  (coalesce(PipelineRun.passed_sla, False).is_(False)),
203
198
  )
204
199
  .scalar()
@@ -227,8 +222,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
227
222
 
228
223
  @validates('schedule_interval')
229
224
  def validate_schedule_interval(self, key, schedule_interval):
230
- if schedule_interval and schedule_interval not in \
231
- [e.value for e in ScheduleInterval]:
225
+ if schedule_interval and schedule_interval not in [e.value for e in ScheduleInterval]:
232
226
  if not croniter.is_valid(schedule_interval):
233
227
  raise ValueError('Cron expression is invalid.')
234
228
 
@@ -258,23 +252,22 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
258
252
  @property
259
253
  def tag_associations(self):
260
254
  return (
261
- TagAssociation.
262
- select(
255
+ TagAssociation.select(
263
256
  TagAssociation.id,
264
257
  TagAssociation.tag_id,
265
258
  TagAssociation.taggable_id,
266
259
  TagAssociation.taggable_type,
267
260
  Tag.name,
268
- ).
269
- join(
261
+ )
262
+ .join(
270
263
  Tag,
271
264
  Tag.id == TagAssociation.tag_id,
272
- ).
273
- filter(
265
+ )
266
+ .filter(
274
267
  TagAssociation.taggable_id == self.id,
275
268
  TagAssociation.taggable_type == self.__class__.__name__,
276
- ).
277
- all()
269
+ )
270
+ .all()
278
271
  )
279
272
 
280
273
  @classmethod
@@ -325,8 +318,10 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
325
318
  continue
326
319
 
327
320
  last_enabled_at = trigger_config.last_enabled_at
328
- if trigger_config.status == ScheduleStatus.ACTIVE and \
329
- trigger_config.last_enabled_at is None:
321
+ if (
322
+ trigger_config.status == ScheduleStatus.ACTIVE
323
+ and trigger_config.last_enabled_at is None
324
+ ):
330
325
  last_enabled_at = datetime.now(tz=pytz.UTC)
331
326
  trigger_config.last_enabled_at = last_enabled_at
332
327
  add_or_update_trigger_for_pipeline_and_persist(
@@ -335,6 +330,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
335
330
  )
336
331
 
337
332
  kwargs = dict(
333
+ description=trigger_config.description,
338
334
  last_enabled_at=last_enabled_at,
339
335
  name=trigger_config.name,
340
336
  pipeline_uuid=trigger_config.pipeline_uuid,
@@ -345,12 +341,14 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
345
341
  sla=trigger_config.sla,
346
342
  start_time=trigger_config.start_time,
347
343
  status=trigger_config.status,
344
+ token=trigger_config.token,
348
345
  variables=trigger_config.variables,
349
346
  )
350
347
 
351
348
  if existing_trigger:
352
349
  if any([
353
350
  existing_trigger.last_enabled_at != kwargs.get('last_enabled_at'),
351
+ existing_trigger.description != kwargs.get('description'),
354
352
  existing_trigger.name != kwargs.get('name'),
355
353
  existing_trigger.pipeline_uuid != kwargs.get('pipeline_uuid'),
356
354
  existing_trigger.repo_path != kwargs.get('repo_path'),
@@ -360,13 +358,15 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
360
358
  existing_trigger.sla != kwargs.get('sla'),
361
359
  existing_trigger.start_time != kwargs.get('start_time'),
362
360
  existing_trigger.status != kwargs.get('status'),
361
+ existing_trigger.token != kwargs.get('token'),
363
362
  existing_trigger.variables != kwargs.get('variables'),
364
363
  ]):
365
- if existing_trigger.token is None:
364
+ if existing_trigger.token is None and kwargs.get('token') is None:
366
365
  kwargs['token'] = uuid.uuid4().hex
367
366
  existing_trigger.update(**kwargs)
368
367
  else:
369
- kwargs['token'] = uuid.uuid4().hex
368
+ if kwargs.get('token') is None:
369
+ kwargs['token'] = uuid.uuid4().hex
370
370
  triggers_to_create.append(kwargs)
371
371
 
372
372
  db_connection.session.bulk_save_objects(
@@ -424,16 +424,19 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
424
424
  if self.schedule_interval is None:
425
425
  return None
426
426
 
427
- if self.schedule_interval == ScheduleInterval.ONCE or \
428
- self.schedule_interval == ScheduleInterval.ALWAYS_ON:
427
+ if (
428
+ self.schedule_interval == ScheduleInterval.ONCE
429
+ or self.schedule_interval == ScheduleInterval.ALWAYS_ON
430
+ ):
429
431
  current_execution_date = now
430
432
  elif self.schedule_interval == ScheduleInterval.DAILY:
431
433
  current_execution_date = now.replace(second=0, microsecond=0, minute=0, hour=0)
432
434
  elif self.schedule_interval == ScheduleInterval.HOURLY:
433
435
  current_execution_date = now.replace(second=0, microsecond=0, minute=0)
434
436
  elif self.schedule_interval == ScheduleInterval.WEEKLY:
435
- current_execution_date = now.replace(second=0, microsecond=0, minute=0, hour=0) - \
436
- timedelta(days=now.weekday())
437
+ current_execution_date = now.replace(
438
+ second=0, microsecond=0, minute=0, hour=0
439
+ ) - timedelta(days=now.weekday())
437
440
  elif self.schedule_interval == ScheduleInterval.MONTHLY:
438
441
  current_execution_date = now.replace(second=0, microsecond=0, minute=0, hour=0, day=1)
439
442
  else:
@@ -480,8 +483,10 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
480
483
  if current_execution_date is None:
481
484
  return None
482
485
 
483
- if self.schedule_interval == ScheduleInterval.ONCE or \
484
- self.schedule_interval == ScheduleInterval.ALWAYS_ON:
486
+ if (
487
+ self.schedule_interval == ScheduleInterval.ONCE
488
+ or self.schedule_interval == ScheduleInterval.ALWAYS_ON
489
+ ):
485
490
  pass
486
491
  elif self.schedule_interval == ScheduleInterval.DAILY:
487
492
  next_execution_date = current_execution_date + timedelta(days=1)
@@ -502,6 +507,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
502
507
  self,
503
508
  previous_runtimes: List[int] = None,
504
509
  pipeline: Pipeline = None,
510
+ repo_config=None,
505
511
  ) -> bool:
506
512
  """
507
513
  Determine whether a pipeline schedule should be executed based on its configuration and
@@ -532,13 +538,20 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
532
538
  if self.status != ScheduleStatus.ACTIVE:
533
539
  return False
534
540
 
535
- if not self.landing_time_enabled() and \
536
- self.start_time is not None and \
537
- compare(now, self.start_time.replace(tzinfo=pytz.UTC)) == -1:
541
+ if (
542
+ not self.landing_time_enabled()
543
+ and self.start_time is not None
544
+ and compare(now, self.start_time.replace(tzinfo=pytz.UTC)) == -1
545
+ ):
538
546
  return False
539
547
 
540
548
  try:
541
- Pipeline.get(self.pipeline_uuid)
549
+ if pipeline is None:
550
+ pipeline = Pipeline.get(
551
+ self.pipeline_uuid,
552
+ repo_path=get_repo_path(),
553
+ repo_config=repo_config,
554
+ )
542
555
  except Exception:
543
556
  print(
544
557
  f'[WARNING] Pipeline {self.pipeline_uuid} cannot be found '
@@ -550,7 +563,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
550
563
  pipeline_run_count = self.pipeline_runs_count
551
564
  if pipeline_run_count == 0:
552
565
  return True
553
- executor_count = self.pipeline.executor_count
566
+ executor_count = pipeline.executor_count
554
567
  # Used by streaming pipeline to launch multiple executors
555
568
  if executor_count > 1 and pipeline_run_count < executor_count:
556
569
  return True
@@ -585,16 +598,21 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
585
598
  the initial pipeline run.
586
599
  """
587
600
  create_initial_pipeline_run = self.get_settings().create_initial_pipeline_run
588
- avoid_initial_pipeline_run = compare(
589
- current_execution_date,
590
- self.last_enabled_at,
591
- ) == -1 if not create_initial_pipeline_run else False
601
+ avoid_initial_pipeline_run = (
602
+ compare(
603
+ current_execution_date,
604
+ self.last_enabled_at,
605
+ )
606
+ == -1
607
+ if not create_initial_pipeline_run
608
+ else False
609
+ )
592
610
 
593
611
  # If the execution date is before start time or date pipeline schedule
594
612
  # was last enabled, don't schedule it.
595
613
  if (
596
- self.start_time is not None and
597
- compare(current_execution_date, self.start_time.replace(tzinfo=pytz.UTC)) == -1
614
+ self.start_time is not None
615
+ and compare(current_execution_date, self.start_time.replace(tzinfo=pytz.UTC)) == -1
598
616
  ) or avoid_initial_pipeline_run:
599
617
  return False
600
618
 
@@ -648,27 +666,17 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
648
666
  pipeline_run=None,
649
667
  sample_size: int = None,
650
668
  ):
651
- pipeline_runs = (
652
- PipelineRun.
653
- query.
654
- filter(
655
- PipelineRun.pipeline_schedule_id == self.id,
656
- PipelineRun.status == PipelineRun.PipelineRunStatus.COMPLETED,
657
- )
669
+ pipeline_runs = PipelineRun.query.filter(
670
+ PipelineRun.pipeline_schedule_id == self.id,
671
+ PipelineRun.status == PipelineRun.PipelineRunStatus.COMPLETED,
658
672
  )
659
673
 
660
674
  if pipeline_run:
661
- pipeline_runs = (
662
- pipeline_runs.
663
- filter(
664
- PipelineRun.id != pipeline_run.id,
665
- )
675
+ pipeline_runs = pipeline_runs.filter(
676
+ PipelineRun.id != pipeline_run.id,
666
677
  )
667
678
 
668
- pipeline_runs = (
669
- pipeline_runs.
670
- order_by(PipelineRun.execution_date.desc())
671
- )
679
+ pipeline_runs = pipeline_runs.order_by(PipelineRun.execution_date.desc())
672
680
 
673
681
  if sample_size:
674
682
  pipeline_runs = pipeline_runs.limit(sample_size)
@@ -701,15 +709,11 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
701
709
  )
702
710
 
703
711
  for pr in pipeline_runs:
704
- runtime = (
705
- pr.completed_at - pr.created_at
706
- ).total_seconds()
712
+ runtime = (pr.completed_at - pr.created_at).total_seconds()
707
713
  previous_runtimes.append(runtime)
708
714
 
709
715
  if pipeline_run:
710
- runtime = (
711
- pipeline_run.completed_at - pipeline_run.created_at
712
- ).total_seconds()
716
+ runtime = (pipeline_run.completed_at - pipeline_run.created_at).total_seconds()
713
717
  previous_runtimes = [runtime] + previous_runtimes
714
718
 
715
719
  return previous_runtimes[:sample_size_to_use]
@@ -761,8 +765,10 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
761
765
  super().__init__(**kwargs)
762
766
 
763
767
  def __repr__(self):
764
- return f'PipelineRun(id={self.id}, pipeline_uuid={self.pipeline_uuid},'\
765
- f' execution_date={self.execution_date})'
768
+ return (
769
+ f'PipelineRun(id={self.id}, pipeline_uuid={self.pipeline_uuid},'
770
+ f' execution_date={self.execution_date})'
771
+ )
766
772
 
767
773
  @property
768
774
  def block_runs_count(self) -> int:
@@ -774,36 +780,35 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
774
780
 
775
781
  @property
776
782
  def execution_partition(self) -> str:
777
- if self.variables and \
778
- isinstance(self.variables, dict) and \
779
- self.variables.get('execution_partition'):
780
-
783
+ if (
784
+ self.variables
785
+ and isinstance(self.variables, dict)
786
+ and self.variables.get('execution_partition')
787
+ ):
781
788
  return self.variables.get('execution_partition')
782
789
  if self.execution_date is None:
783
790
  return str(self.pipeline_schedule_id)
784
791
  else:
785
792
  return '/'.join([
786
- str(self.pipeline_schedule_id),
787
- self.execution_date.strftime(format='%Y%m%dT%H%M%S'),
788
- ])
793
+ str(self.pipeline_schedule_id),
794
+ self.execution_date.strftime(format='%Y%m%dT%H%M%S'),
795
+ ])
789
796
 
790
797
  @property
791
798
  def initial_block_runs(self) -> List['BlockRun']:
792
- return [b for b in self.block_runs
793
- if b.status == BlockRun.BlockRunStatus.INITIAL]
799
+ return [b for b in self.block_runs if b.status == BlockRun.BlockRunStatus.INITIAL]
794
800
 
795
801
  @property
796
802
  def running_block_runs(self) -> List['BlockRun']:
797
- return [
798
- b for b in self.block_runs
799
- if b.status == BlockRun.BlockRunStatus.RUNNING
800
- ]
803
+ return [b for b in self.block_runs if b.status == BlockRun.BlockRunStatus.RUNNING]
801
804
 
802
805
  @property
803
806
  def queued_or_running_block_runs(self) -> List['BlockRun']:
804
807
  return [
805
- b for b in self.block_runs
806
- if b.status in [
808
+ b
809
+ for b in self.block_runs
810
+ if b.status
811
+ in [
807
812
  BlockRun.BlockRunStatus.QUEUED,
808
813
  BlockRun.BlockRunStatus.RUNNING,
809
814
  ]
@@ -811,25 +816,22 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
811
816
 
812
817
  @property
813
818
  def completed_block_runs(self) -> List['BlockRun']:
814
- return [b for b in self.block_runs
815
- if b.status == BlockRun.BlockRunStatus.COMPLETED]
819
+ return [b for b in self.block_runs if b.status == BlockRun.BlockRunStatus.COMPLETED]
816
820
 
817
821
  @property
818
822
  def failed_block_runs(self) -> List['BlockRun']:
819
- return [b for b in self.block_runs
820
- if b.status == BlockRun.BlockRunStatus.FAILED]
823
+ return [b for b in self.block_runs if b.status == BlockRun.BlockRunStatus.FAILED]
821
824
 
822
825
  @property
823
826
  def pipeline(self) -> 'Pipeline':
824
827
  if project_platform_activated():
825
828
  return self.pipeline_project_platform
826
829
 
827
- return Pipeline.get(self.pipeline_uuid)
830
+ return Pipeline.get(self.pipeline_uuid, repo_path=get_repo_path())
828
831
 
829
832
  @property
830
833
  def pipeline_type(self) -> PipelineType:
831
- pipeline = Pipeline.get(self.pipeline_uuid, check_if_exists=True)
832
-
834
+ pipeline = self.pipeline
833
835
  return pipeline.type if pipeline is not None else None
834
836
 
835
837
  @property
@@ -862,13 +864,9 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
862
864
  pipeline_schedule_id: int = None,
863
865
  sample_size: int = None,
864
866
  ):
865
- pipeline_runs = (
866
- self.
867
- query.
868
- filter(
869
- self.pipeline_uuid == pipeline_uuid,
870
- self.status == self.PipelineRunStatus.COMPLETED,
871
- )
867
+ pipeline_runs = self.query.filter(
868
+ self.pipeline_uuid == pipeline_uuid,
869
+ self.status == self.PipelineRunStatus.COMPLETED,
872
870
  )
873
871
 
874
872
  if pipeline_run_id is not None:
@@ -985,7 +983,7 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
985
983
  if block and block.replicated_block:
986
984
  arr.add(block.uuid)
987
985
 
988
- return arr
986
+ return list(arr)
989
987
 
990
988
  completed_block_uuids = _build_block_uuids(self.completed_block_runs)
991
989
  finished_block_uuids = _build_block_uuids(self.block_runs)
@@ -1042,6 +1040,13 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1042
1040
 
1043
1041
  executable_block_runs = []
1044
1042
  for block_run in self.initial_block_runs:
1043
+ block = pipeline.get_block(block_run.block_uuid)
1044
+
1045
+ if block is not None and block.is_dynamic_streaming:
1046
+ if is_ready_to_process_data(pipeline, block_run, block_runs_all):
1047
+ executable_block_runs.append(block_run)
1048
+ continue
1049
+
1045
1050
  completed = False
1046
1051
  upstream_block_uuids_override = None
1047
1052
 
@@ -1065,13 +1070,9 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1065
1070
  elif metrics.get('upstream_blocks'):
1066
1071
  upstream_block_uuids_override = metrics.get('upstream_blocks') or None
1067
1072
 
1068
- block = pipeline.get_block(block_run.block_uuid)
1069
-
1070
1073
  if block and is_dynamic_block_child(block):
1071
1074
  if check_all_dynamic_upstreams_completed(
1072
- block,
1073
- block_runs_all,
1074
- execution_partition=self.execution_partition
1075
+ block, block_runs_all, execution_partition=self.execution_partition
1075
1076
  ):
1076
1077
  completed = True
1077
1078
  else:
@@ -1086,11 +1087,9 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1086
1087
  uuids_to_check.append(upstream_block_uuid)
1087
1088
 
1088
1089
  if allow_blocks_to_fail:
1089
- completed = all(uuid in finished_block_uuids
1090
- for uuid in uuids_to_check)
1090
+ completed = all(uuid in finished_block_uuids for uuid in uuids_to_check)
1091
1091
  else:
1092
- completed = all(uuid in completed_block_uuids
1093
- for uuid in uuids_to_check)
1092
+ completed = all(uuid in completed_block_uuids for uuid in uuids_to_check)
1094
1093
  else:
1095
1094
  metrics = block_run.metrics
1096
1095
 
@@ -1126,15 +1125,17 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1126
1125
  upstream_block_uuids_override = [
1127
1126
  controller_block_uuid,
1128
1127
  ]
1129
- elif metrics.get('controller') and \
1130
- metrics.get('child') and not \
1131
- metrics.get('run_in_parallel') and \
1132
- metrics.get('upstream_block_uuids'):
1133
-
1128
+ elif (
1129
+ metrics.get('controller')
1130
+ and metrics.get('child')
1131
+ and not metrics.get('run_in_parallel')
1132
+ and metrics.get('upstream_block_uuids')
1133
+ ):
1134
1134
  upstream_block_uuids_override = metrics.get('upstream_block_uuids')
1135
1135
  elif metrics and metrics.get('dynamic_upstream_block_uuids'):
1136
- upstream_block_uuids_override = \
1136
+ upstream_block_uuids_override = (
1137
1137
  metrics.get('dynamic_upstream_block_uuids') or []
1138
+ )
1138
1139
 
1139
1140
  incomplete = False
1140
1141
  if block:
@@ -1164,15 +1165,20 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1164
1165
  up_uuids.append(upstream_block.uuid)
1165
1166
 
1166
1167
  if len(up_uuids_dynamic_children) >= 1:
1167
- upstream_block_uuids_override = \
1168
- (upstream_block_uuids_override or []) + \
1169
- up_uuids + up_uuids_dynamic_children
1170
-
1171
- completed = not incomplete and block is not None and \
1172
- block.all_upstream_blocks_completed(
1168
+ upstream_block_uuids_override = (
1169
+ (upstream_block_uuids_override or [])
1170
+ + up_uuids
1171
+ + up_uuids_dynamic_children
1172
+ )
1173
+
1174
+ completed = (
1175
+ not incomplete
1176
+ and block is not None
1177
+ and block.all_upstream_blocks_completed(
1173
1178
  completed_block_uuids,
1174
1179
  upstream_block_uuids_override,
1175
1180
  )
1181
+ )
1176
1182
 
1177
1183
  if completed:
1178
1184
  executable_block_runs.append(block_run)
@@ -1203,15 +1209,19 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1203
1209
  pipeline = self.pipeline
1204
1210
 
1205
1211
  failed_block_uuids = set(
1206
- b.block_uuid for b in self.block_runs
1207
- if b.status in [
1212
+ b.block_uuid
1213
+ for b in self.block_runs
1214
+ if b.status
1215
+ in [
1208
1216
  BlockRun.BlockRunStatus.UPSTREAM_FAILED,
1209
1217
  BlockRun.BlockRunStatus.FAILED,
1210
1218
  ]
1211
1219
  )
1212
1220
  condition_failed_block_uuids = set(
1213
- b.block_uuid for b in self.block_runs
1214
- if b.status in [
1221
+ b.block_uuid
1222
+ for b in self.block_runs
1223
+ if b.status
1224
+ in [
1215
1225
  BlockRun.BlockRunStatus.CONDITION_FAILED,
1216
1226
  ]
1217
1227
  )
@@ -1237,13 +1247,13 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1237
1247
  upstream_block_uuids = block.upstream_block_uuids
1238
1248
  # If an upstream dynamic child fails, the block_run.block_uuid won’t match.
1239
1249
  if block_run.block_uuid == block.uuid:
1240
- block_uuids = list(block_uuids) + [pipeline.get_block(
1241
- block_inner,
1242
- ).uuid for block_inner in block_uuids]
1243
- if any(
1244
- b in block_uuids
1245
- for b in upstream_block_uuids
1246
- ):
1250
+ block_uuids = list(block_uuids) + [
1251
+ pipeline.get_block(
1252
+ block_inner,
1253
+ ).uuid
1254
+ for block_inner in block_uuids
1255
+ ]
1256
+ if any(b in block_uuids for b in upstream_block_uuids):
1247
1257
  block_run.update(status=status)
1248
1258
  updated_status = True
1249
1259
 
@@ -1299,9 +1309,9 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1299
1309
  @classmethod
1300
1310
  @safe_db_query
1301
1311
  def batch_update_status(self, pipeline_run_ids: List[int], status):
1302
- PipelineRun.query.filter(PipelineRun.id.in_(pipeline_run_ids)).update({
1303
- PipelineRun.status: status
1304
- }, synchronize_session=False)
1312
+ PipelineRun.query.filter(PipelineRun.id.in_(pipeline_run_ids)).update(
1313
+ {PipelineRun.status: status}, synchronize_session=False
1314
+ )
1305
1315
  db_connection.session.commit()
1306
1316
 
1307
1317
  @classmethod
@@ -1365,9 +1375,12 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1365
1375
  )
1366
1376
 
1367
1377
  from mage_ai.usage_statistics.logger import UsageStatisticLogger
1368
- asyncio.run(UsageStatisticLogger().pipeline_runs_impression(
1369
- lambda: self.query.filter(self.status == self.PipelineRunStatus.COMPLETED).count(),
1370
- ))
1378
+
1379
+ asyncio.run(
1380
+ UsageStatisticLogger().pipeline_runs_impression(
1381
+ lambda: self.query.filter(self.status == self.PipelineRunStatus.COMPLETED).count(),
1382
+ )
1383
+ )
1371
1384
 
1372
1385
  @safe_db_query
1373
1386
  def create_block_run(
@@ -1407,11 +1420,11 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1407
1420
  if block.replicated_block:
1408
1421
  replicated_block = pipeline.get_block(block.replicated_block)
1409
1422
  if replicated_block:
1410
- block_uuid = f'{block.uuid}:{replicated_block.uuid}'
1423
+ block_uuid = block.uuid_replicated
1411
1424
  else:
1412
1425
  raise Exception(
1413
- f'Replicated block {block.replicated_block} ' +
1414
- f'does not exist in pipeline {pipeline.uuid}.',
1426
+ f'Replicated block {block.replicated_block} '
1427
+ + f'does not exist in pipeline {pipeline.uuid}.',
1415
1428
  )
1416
1429
  elif block.is_data_integration():
1417
1430
  controller_uuid = block.controller_uuid
@@ -1422,10 +1435,12 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1422
1435
 
1423
1436
  block_arr.append((
1424
1437
  controller_uuid,
1425
- dict(metrics=dict(
1426
- controller=1,
1427
- original_block_uuid=block_uuid,
1428
- )),
1438
+ dict(
1439
+ metrics=dict(
1440
+ controller=1,
1441
+ original_block_uuid=block_uuid,
1442
+ )
1443
+ ),
1429
1444
  ))
1430
1445
 
1431
1446
  flags = []
@@ -1448,9 +1463,11 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1448
1463
  flags.append(DynamicBlockFlag.REDUCE_OUTPUT)
1449
1464
 
1450
1465
  if len(flags) >= 1:
1451
- create_options['metrics'] = dict(metadata=dict(
1452
- flags=flags,
1453
- ))
1466
+ create_options['metrics'] = dict(
1467
+ metadata=dict(
1468
+ flags=flags,
1469
+ )
1470
+ )
1454
1471
 
1455
1472
  block_arr.append((block_uuid, create_options))
1456
1473
 
@@ -1467,10 +1484,7 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1467
1484
  return [self.create_block_run(block_uuid, **options) for block_uuid, options in block_arr]
1468
1485
 
1469
1486
  def any_blocks_failed(self) -> bool:
1470
- return any(
1471
- b.status == BlockRun.BlockRunStatus.FAILED
1472
- for b in self.block_runs
1473
- )
1487
+ return any(b.status == BlockRun.BlockRunStatus.FAILED for b in self.block_runs)
1474
1488
 
1475
1489
  def all_blocks_completed(self, include_failed_blocks: bool = False) -> bool:
1476
1490
  statuses = [
@@ -1518,16 +1532,19 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1518
1532
  variables['event'] = merge_dict(variables.get('event', {}), event_variables)
1519
1533
  variables['execution_date'] = self.execution_date
1520
1534
  variables['execution_partition'] = self.execution_partition
1535
+ variables['pipeline_run_id'] = self.id
1521
1536
 
1522
1537
  interval_end_datetime = variables.get('interval_end_datetime')
1523
1538
  interval_seconds = variables.get('interval_seconds')
1524
1539
  interval_start_datetime = variables.get('interval_start_datetime')
1525
1540
  interval_start_datetime_previous = variables.get('interval_start_datetime_previous')
1526
1541
 
1527
- if interval_end_datetime or \
1528
- interval_seconds or \
1529
- interval_start_datetime or \
1530
- interval_start_datetime_previous:
1542
+ if (
1543
+ interval_end_datetime
1544
+ or interval_seconds
1545
+ or interval_start_datetime
1546
+ or interval_start_datetime_previous
1547
+ ):
1531
1548
  if interval_end_datetime:
1532
1549
  try:
1533
1550
  variables['interval_end_datetime'] = dateutil.parser.parse(
@@ -1585,9 +1602,7 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1585
1602
  # to call get_next again to go back to the original state
1586
1603
  cron_itr.get_next()
1587
1604
  interval_end_datetime = cron_itr.get_next(datetime)
1588
- interval_seconds = (
1589
- interval_end_datetime.timestamp() - current.timestamp()
1590
- )
1605
+ interval_seconds = interval_end_datetime.timestamp() - current.timestamp()
1591
1606
  except Exception:
1592
1607
  pass
1593
1608
 
@@ -1633,7 +1648,7 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
1633
1648
 
1634
1649
  @property
1635
1650
  def logs(self):
1636
- pipeline = Pipeline.get(self.pipeline_run.pipeline_uuid)
1651
+ pipeline = self.pipeline_run.pipeline_schedule.pipeline
1637
1652
  return LoggerManagerFactory.get_logger_manager(
1638
1653
  pipeline_uuid=pipeline.uuid,
1639
1654
  block_uuid=clean_name(self.block_uuid),
@@ -1645,7 +1660,7 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
1645
1660
  if project_platform_activated():
1646
1661
  return await self.logs_async_project_platform(repo_path=repo_path)
1647
1662
 
1648
- pipeline = await Pipeline.get_async(self.pipeline_run.pipeline_uuid)
1663
+ pipeline = await Pipeline.get_async(self.pipeline_run.pipeline_uuid, repo_path=repo_path)
1649
1664
  return await LoggerManagerFactory.get_logger_manager(
1650
1665
  pipeline_uuid=pipeline.uuid,
1651
1666
  block_uuid=clean_name(self.block_uuid),
@@ -1656,17 +1671,15 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
1656
1671
  @classmethod
1657
1672
  @safe_db_query
1658
1673
  def batch_update_status(self, block_run_ids: List[int], status):
1659
- BlockRun.query.filter(BlockRun.id.in_(block_run_ids)).update({
1660
- BlockRun.status: status
1661
- }, synchronize_session=False)
1674
+ BlockRun.query.filter(BlockRun.id.in_(block_run_ids)).update(
1675
+ {BlockRun.status: status}, synchronize_session=False
1676
+ )
1662
1677
  db_connection.session.commit()
1663
1678
 
1664
1679
  @classmethod
1665
1680
  @safe_db_query
1666
1681
  def batch_delete(self, block_run_ids: List[int]):
1667
- BlockRun.query.filter(BlockRun.id.in_(block_run_ids)).delete(
1668
- synchronize_session=False
1669
- )
1682
+ BlockRun.query.filter(BlockRun.id.in_(block_run_ids)).delete(synchronize_session=False)
1670
1683
  db_connection.session.commit()
1671
1684
 
1672
1685
  @classmethod
@@ -1680,8 +1693,13 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
1680
1693
  return block_runs[0]
1681
1694
  return None
1682
1695
 
1683
- def get_outputs(self, sample_count: int = None) -> List[Dict]:
1696
+ def get_outputs(
1697
+ self,
1698
+ exclude_blank_variable_uuids: bool = False,
1699
+ sample_count: int = None,
1700
+ ) -> List[Dict]:
1684
1701
  pipeline = Pipeline.get(self.pipeline_run.pipeline_uuid)
1702
+
1685
1703
  block = pipeline.get_block(self.block_uuid)
1686
1704
  block_uuid = self.block_uuid
1687
1705
 
@@ -1755,6 +1773,7 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
1755
1773
  ]
1756
1774
 
1757
1775
  return block.get_outputs(
1776
+ exclude_blank_variable_uuids=exclude_blank_variable_uuids,
1758
1777
  execution_partition=self.pipeline_run.execution_partition,
1759
1778
  sample_count=sample_count,
1760
1779
  block_uuid=block_uuid,
@@ -1783,9 +1802,7 @@ class EventMatcher(BaseModel):
1783
1802
  @classmethod
1784
1803
  def active_event_matchers(self) -> List['EventMatcher']:
1785
1804
  return self.query.filter(
1786
- EventMatcher.pipeline_schedules.any(
1787
- PipelineSchedule.status == ScheduleStatus.ACTIVE
1788
- )
1805
+ EventMatcher.pipeline_schedules.any(PipelineSchedule.status == ScheduleStatus.ACTIVE)
1789
1806
  ).all()
1790
1807
 
1791
1808
  @classmethod
@@ -1846,8 +1863,7 @@ class EventMatcher(BaseModel):
1846
1863
  return [t[0] for t in event_matchers_and_pipeline_schedule_ids]
1847
1864
 
1848
1865
  def active_pipeline_schedules(self) -> List[PipelineSchedule]:
1849
- return [p for p in self.pipeline_schedules
1850
- if p.status == ScheduleStatus.ACTIVE]
1866
+ return [p for p in self.pipeline_schedules if p.status == ScheduleStatus.ACTIVE]
1851
1867
 
1852
1868
  def match(self, config: Dict) -> bool:
1853
1869
  def __match_dict(sub_pattern, sub_config):
@@ -1863,6 +1879,7 @@ class EventMatcher(BaseModel):
1863
1879
  elif not __match_dict(v, sub_config[k]):
1864
1880
  return False
1865
1881
  return True
1882
+
1866
1883
  return __match_dict(self.pattern, config)
1867
1884
 
1868
1885