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
@@ -1,15 +1,32 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import os
5
+ import re
3
6
  from collections.abc import Sequence
4
7
  from logging import Logger
5
- from typing import Any, Dict, List, Tuple, Union
8
+ from typing import Any, Dict, List, Optional, Tuple, Union
6
9
 
7
10
  import pandas as pd
8
-
11
+ import polars as pl
12
+
13
+ from mage_ai.data.constants import InputDataType
14
+ from mage_ai.data.tabular.models import BatchSettings
15
+ from mage_ai.data_preparation.models.block.dynamic.data import (
16
+ calculate_dynamic_index_data_index,
17
+ )
18
+ from mage_ai.data_preparation.models.block.settings.variables.models import (
19
+ ChunkKeyTypeUnion,
20
+ )
9
21
  from mage_ai.data_preparation.models.constants import BlockLanguage, BlockType
10
22
  from mage_ai.data_preparation.models.variable import Variable
11
- from mage_ai.shared.memory import get_memory_usage, get_memory_usage_async
23
+ from mage_ai.data_preparation.models.variables.utils import (
24
+ get_first_data_output_variable,
25
+ )
26
+ from mage_ai.io.base import ExportWritePolicy
27
+ from mage_ai.settings.server import DEBUG_MEMORY, MEMORY_MANAGER_V2
12
28
  from mage_ai.shared.strings import to_ordinal_integers
29
+ from mage_ai.system.memory.wrappers import execute_with_memory_tracking
13
30
 
14
31
 
15
32
  class LazyVariable:
@@ -17,8 +34,8 @@ class LazyVariable:
17
34
  self,
18
35
  block,
19
36
  variable: Variable,
20
- sample: int = None,
21
- sample_count: int = None,
37
+ sample: Optional[int] = None,
38
+ sample_count: Optional[int] = None,
22
39
  skip: bool = False,
23
40
  ):
24
41
  self.block = block
@@ -29,7 +46,10 @@ class LazyVariable:
29
46
  @property
30
47
  def is_dynamic(self):
31
48
  from mage_ai.data_preparation.models.block.dynamic.utils import is_dynamic_block
32
- return is_dynamic_block(self.block)
49
+
50
+ return (self.block.is_dynamic_v2 and self.block.is_dynamic_parent) or is_dynamic_block(
51
+ self.block
52
+ )
33
53
 
34
54
  def read_data(self):
35
55
  result = self.variable.read_data(
@@ -72,11 +92,14 @@ class LazyVariableSet(Sequence):
72
92
  **kwargs,
73
93
  ):
74
94
  self.block = block
75
- self.lazy_variables = [LazyVariable(
76
- block,
77
- variable_object,
78
- **kwargs,
79
- ) for variable_object in variable_objects]
95
+ self.lazy_variables = [
96
+ LazyVariable(
97
+ block,
98
+ variable_object,
99
+ **kwargs,
100
+ )
101
+ for variable_object in variable_objects
102
+ ]
80
103
  self.logger = logger
81
104
  self.logging_tags = logging_tags
82
105
 
@@ -95,42 +118,50 @@ class LazyVariableSet(Sequence):
95
118
  @property
96
119
  def is_dynamic(self):
97
120
  from mage_ai.data_preparation.models.block.dynamic.utils import is_dynamic_block
98
- return is_dynamic_block(self.block)
121
+
122
+ return (self.block.is_dynamic_v2 and self.block.is_dynamic_parent) or is_dynamic_block(
123
+ self.block
124
+ )
99
125
 
100
126
  @property
101
- def lazy_child_data(self) -> LazyVariable:
102
- return self[0]
127
+ def lazy_child_data(self) -> Union[List[LazyVariable], LazyVariable]:
128
+ if len(self) == 2:
129
+ return self[0]
130
+ return self.lazy_variables
103
131
 
104
132
  @property
105
- def lazy_metadata(self) -> LazyVariable:
106
- return self[1]
133
+ def lazy_metadata(self) -> Optional[LazyVariable]:
134
+ if len(self) == 2:
135
+ return self[1]
136
+ return None
107
137
 
108
138
  def read_child_data(self) -> Any:
109
139
  if not isinstance(self.lazy_child_data, pd.DataFrame) and not self.lazy_child_data:
110
140
  return None
111
141
 
112
- return self.read_lazy_variable(
113
- self.lazy_child_data,
114
- ) if self.lazy_child_data is not None else None
142
+ if isinstance(self.lazy_child_data, list):
143
+ return [self.read_lazy_variable(data) for data in self.lazy_child_data]
144
+
145
+ return (
146
+ self.read_lazy_variable(self.lazy_child_data)
147
+ if self.lazy_child_data is not None
148
+ else None
149
+ )
115
150
 
116
151
  def read_metadata(self) -> Any:
117
152
  return self.read_lazy_variable(self.lazy_metadata) if self.lazy_metadata else {}
118
153
 
119
154
  def read_lazy_variable(self, lazy_variable: LazyVariable) -> Any:
120
- return get_memory_usage(
121
- logger=self.logger,
122
- logging_tags=self.logging_tags,
123
- message_prefix=f'[Block {lazy_variable.block.uuid}.read_data',
124
- wrapped_function=lazy_variable.read_data,
125
- )
155
+ return lazy_variable.read_data()
126
156
 
127
- async def read_lazy_variable_async(self, lazy_variable: LazyVariable) -> Any:
128
- return await get_memory_usage_async(
129
- logger=self.logger,
130
- logging_tags=self.logging_tags,
131
- message_prefix=f'[Block {lazy_variable.block.uuid}.read_data',
132
- wrapped_function=lazy_variable.read_data_async,
133
- )
157
+ async def read_lazy_variable_async(
158
+ self,
159
+ lazy_variable: Union[List[LazyVariable], LazyVariable],
160
+ ) -> Any:
161
+ if isinstance(lazy_variable, list):
162
+ return await asyncio.gather(*[lv.read_data_async() for lv in lazy_variable])
163
+ elif lazy_variable:
164
+ return await lazy_variable.read_data_async()
134
165
 
135
166
  def read_data(self) -> Tuple[Any, Any]:
136
167
  metadata = self.read_metadata()
@@ -141,12 +172,13 @@ class LazyVariableSet(Sequence):
141
172
  metadata,
142
173
  )
143
174
 
144
- async def read_data_async(self) -> Tuple[Any, Any]:
175
+ async def read_data_async(self) -> Tuple[Optional[Any], Dict]:
145
176
  pair = tuple()
146
177
  if self.lazy_child_data:
147
178
  pair += (await self.read_lazy_variable_async(self.lazy_child_data),)
148
179
  else:
149
180
  pair += (None,)
181
+
150
182
  if self.lazy_metadata:
151
183
  pair += (await self.read_lazy_variable_async(self.lazy_metadata),)
152
184
  else:
@@ -156,7 +188,7 @@ class LazyVariableSet(Sequence):
156
188
 
157
189
 
158
190
  class LazyVariableController(Sequence):
159
- def __init__(self, block, lazy_variable_sets: List[List[LazyVariableSet]]):
191
+ def __init__(self, block, lazy_variable_sets: List[LazyVariableSet]):
160
192
  self.block = block
161
193
  self.lazy_variable_sets = lazy_variable_sets
162
194
 
@@ -173,13 +205,17 @@ class LazyVariableController(Sequence):
173
205
  @property
174
206
  def is_dynamic(self):
175
207
  from mage_ai.data_preparation.models.block.dynamic.utils import is_dynamic_block
176
- return is_dynamic_block(self.block)
208
+
209
+ return (self.block.is_dynamic_v2 and self.block.is_dynamic_parent) or is_dynamic_block(
210
+ self.block
211
+ )
177
212
 
178
213
  def render(
179
214
  self,
180
- child_dynamic_block_index: int = None,
181
- dynamic_block_index: int = None,
182
- ) -> Union[List[Tuple], Tuple]:
215
+ child_dynamic_block_index: Optional[int] = None,
216
+ dynamic_block_index: Optional[int] = None,
217
+ lazy_load: bool = False,
218
+ ) -> List[Union[Tuple[Optional[Any], Dict], List[LazyVariableSet]]]:
183
219
  arr = self.lazy_variable_sets
184
220
 
185
221
  if child_dynamic_block_index is not None:
@@ -188,24 +224,39 @@ class LazyVariableController(Sequence):
188
224
  child_data, metadata = lazy_variable_set.read_data()
189
225
 
190
226
  if self.is_dynamic:
191
- if isinstance(child_data, pd.DataFrame):
227
+ if child_data is None:
228
+ child_data = [None]
229
+ elif isinstance(child_data, pd.DataFrame):
192
230
  index = child_dynamic_block_index % len(child_data.index)
193
- child_data = child_data.iloc[index:index + 1]
231
+ child_data = child_data.iloc[index : index + 1]
194
232
  else:
195
233
  index = child_dynamic_block_index % len(child_data)
196
234
  child_data = child_data[index]
197
235
  metadata = metadata[index] if len(metadata) > index else {}
198
236
 
199
- return child_data, metadata
237
+ return [child_data, metadata]
200
238
 
201
239
  if dynamic_block_index is not None:
202
- arr = arr[dynamic_block_index:dynamic_block_index + 1]
240
+ arr = arr[dynamic_block_index : dynamic_block_index + 1]
241
+
242
+ if lazy_load:
243
+ return arr
244
+
203
245
  return [lazy_variable_set.read_data() for lazy_variable_set in arr]
204
246
 
205
- async def render_async(self, dynamic_block_index: int = None):
247
+ async def render_async(
248
+ self,
249
+ dynamic_block_index: Optional[int] = None,
250
+ lazy_load: bool = False,
251
+ ) -> List[Union[Tuple[Optional[Any], Dict], List[LazyVariableSet]]]:
206
252
  arr = self.lazy_variable_sets
253
+
207
254
  if dynamic_block_index is not None:
208
- arr = arr[dynamic_block_index:dynamic_block_index + 1]
255
+ arr = arr[dynamic_block_index : dynamic_block_index + 1]
256
+
257
+ if lazy_load:
258
+ return arr
259
+
209
260
  return await asyncio.gather(
210
261
  *[lazy_variable_set.read_data_async() for lazy_variable_set in arr],
211
262
  )
@@ -213,7 +264,7 @@ class LazyVariableController(Sequence):
213
264
 
214
265
  def get_dynamic_child_block_indexes(
215
266
  block,
216
- execution_partition: str = None,
267
+ execution_partition: Optional[str] = None,
217
268
  ) -> List[int]:
218
269
  from mage_ai.data_preparation.models.block.dynamic.utils import (
219
270
  build_combinations_for_dynamic_child,
@@ -225,18 +276,35 @@ def get_dynamic_child_block_indexes(
225
276
  1/
226
277
  2/
227
278
  """
228
- count = len(build_combinations_for_dynamic_child(
279
+ combos = build_combinations_for_dynamic_child(
229
280
  block,
230
281
  execution_partition=execution_partition,
231
- ))
282
+ )
283
+ count = len(combos)
232
284
 
233
285
  return [i for i in range(count)]
234
286
 
235
287
 
288
+ def sort_variables(variable_object):
289
+ # Using regular expressions to find all digits in the directory path
290
+ numbers = []
291
+ for text in [
292
+ str(variable_object.block_dir_name),
293
+ str(variable_object.uuid),
294
+ ]:
295
+ number = re.findall('\\d+', text)
296
+ if number:
297
+ numbers += number
298
+ else:
299
+ numbers.append(to_ordinal_integers(text)[0])
300
+ # Convert found strings to integers for correct numeric sort
301
+ return tuple(map(int, numbers))
302
+
303
+
236
304
  def get_variable_objects(
237
- block,
238
- execution_partition: str = None,
239
- dynamic_block_index: int = None,
305
+ block: Any,
306
+ execution_partition: Optional[str] = None,
307
+ dynamic_block_index: Optional[int] = None,
240
308
  ) -> List[Variable]:
241
309
  """
242
310
  If dynamic_block_index, get the folder names in the nested folder named after the
@@ -248,10 +316,15 @@ def get_variable_objects(
248
316
  Or else:
249
317
  output_0/
250
318
  output_1/
319
+
320
+ Or
321
+ output_0/
322
+ 0/
323
+ 1/
324
+ output_1/
325
+ 0/
326
+ 1/
251
327
  """
252
- pipeline = block.pipeline
253
- pipeline_uuid = pipeline.uuid
254
- variable_manager = pipeline.variable_manager
255
328
 
256
329
  """
257
330
  If block is a dynamic child block, get the variable objects specifically in the directory
@@ -263,34 +336,34 @@ def get_variable_objects(
263
336
  if dynamic_block_index is not None:
264
337
  block_uuid = os.path.join(block_uuid, str(dynamic_block_index))
265
338
 
266
- variable_uuids = variable_manager.get_variables_by_block(
267
- block.pipeline.uuid,
268
- block_uuid=block_uuid,
339
+ variable_uuids = block.get_variables_by_block(
340
+ block_uuid,
269
341
  clean_block_uuid=dynamic_block_index is None,
270
342
  partition=execution_partition,
271
343
  )
272
344
 
273
- def __sort(variable_object: str):
274
- if not variable_object:
275
- return -96, -96
276
- return to_ordinal_integers(variable_object.block_dir_name)[0], variable_object.uuid
277
-
278
345
  return sorted(
279
- [variable_manager.get_variable_object(
280
- block_uuid=block_uuid,
281
- clean_block_uuid=dynamic_block_index is None,
282
- partition=execution_partition,
283
- pipeline_uuid=pipeline_uuid,
284
- variable_uuid=variable_uuid,
285
- ) for variable_uuid in variable_uuids if variable_uuid != ''],
286
- key=__sort,
346
+ [
347
+ block.get_variable_object(
348
+ block_uuid,
349
+ variable_uuid,
350
+ clean_block_uuid=dynamic_block_index is None,
351
+ ordinal_position=int(dynamic_block_index)
352
+ if dynamic_block_index is not None
353
+ else None,
354
+ partition=execution_partition,
355
+ )
356
+ for variable_uuid in variable_uuids
357
+ if variable_uuid != ''
358
+ ],
359
+ key=sort_variables,
287
360
  )
288
361
 
289
362
 
290
363
  def delete_variable_objects_for_dynamic_child(
291
364
  block,
292
- dynamic_block_index: int = None,
293
- execution_partition: str = None,
365
+ dynamic_block_index: Optional[int] = None,
366
+ execution_partition: Optional[str] = None,
294
367
  ) -> None:
295
368
  variable_objects = get_variable_objects(
296
369
  block,
@@ -298,13 +371,23 @@ def delete_variable_objects_for_dynamic_child(
298
371
  execution_partition=execution_partition,
299
372
  )
300
373
  if variable_objects:
374
+ write_policy = (
375
+ block.write_settings.batch_settings.mode
376
+ if block.write_settings and block.write_settings.batch_settings
377
+ else None
378
+ )
301
379
  for variable_object in variable_objects:
302
- variable_object.delete()
380
+ if write_policy and variable_object.data_exists():
381
+ if ExportWritePolicy.FAIL == write_policy:
382
+ raise Exception(f'Write policy for block {block.uuid} is {write_policy}.')
383
+ elif ExportWritePolicy.APPEND != write_policy:
384
+ variable_object.delete()
303
385
 
304
386
 
305
387
  def __get_all_variable_objects_for_dynamic_child(
306
388
  block,
307
- execution_partition: str = None,
389
+ execution_partition: Optional[str] = None,
390
+ limit_parts: Optional[int] = None,
308
391
  ) -> List[List[Variable]]:
309
392
  """
310
393
  This method will get the nested outputs (output_0) in every numeric folder
@@ -313,6 +396,7 @@ def __get_all_variable_objects_for_dynamic_child(
313
396
  variable_objects_arr = []
314
397
 
315
398
  indexes = get_dynamic_child_block_indexes(block, execution_partition=execution_partition)
399
+
316
400
  for dynamic_block_index in indexes:
317
401
  # 0/output_0,
318
402
  # 0/output_1,
@@ -325,33 +409,36 @@ def __get_all_variable_objects_for_dynamic_child(
325
409
  dynamic_block_index=dynamic_block_index,
326
410
  )
327
411
 
328
- def __sort(variable_object: str):
329
- if not variable_object:
330
- return -96, -96
331
- return to_ordinal_integers(variable_object.block_dir_name)[0], variable_object.uuid
412
+ variable_objects_arr.append(sorted(arr, key=sort_variables))
332
413
 
333
- variable_objects_arr.append(sorted(arr, key=__sort))
414
+ if limit_parts is not None:
415
+ variable_objects_arr = variable_objects_arr[:limit_parts]
334
416
 
335
417
  return variable_objects_arr
336
418
 
337
419
 
338
420
  async def get_outputs_async(
339
421
  block,
340
- execution_partition: str = None,
341
- dynamic_block_index: int = None,
422
+ execution_partition: Optional[str] = None,
423
+ dynamic_block_index: Optional[int] = None,
424
+ limit_parts: Optional[int] = None,
342
425
  sample: bool = False,
343
- sample_count: int = None,
344
- ) -> Tuple[List[Union[Dict, int, str, pd.DataFrame]], List[Dict]]:
426
+ sample_count: Optional[int] = None,
427
+ ) -> List[Optional[Union[Dict, int, str, pd.DataFrame, Any]]]:
345
428
  variable_objects = get_variable_objects(
346
429
  block,
347
430
  execution_partition=execution_partition,
348
431
  dynamic_block_index=dynamic_block_index,
349
432
  )
350
433
 
351
- return await asyncio.gather(*[variable_object.read_data_async(
352
- sample=sample,
353
- sample_count=sample_count,
354
- ) for variable_object in variable_objects])
434
+ return await asyncio.gather(*[
435
+ variable_object.read_data_async(
436
+ limit_parts=limit_parts,
437
+ sample=sample,
438
+ sample_count=sample_count,
439
+ )
440
+ for variable_object in variable_objects
441
+ ])
355
442
 
356
443
 
357
444
  def get_outputs(
@@ -360,40 +447,106 @@ def get_outputs(
360
447
  dynamic_block_index: int = None,
361
448
  sample: bool = False,
362
449
  sample_count: int = None,
363
- ) -> Tuple[List[Union[Dict, int, str, pd.DataFrame]], List[Dict]]:
450
+ ) -> List[Optional[Union[Dict, int, str, pd.DataFrame, Any]]]:
451
+ variable_objects = get_variable_objects(
452
+ block,
453
+ execution_partition=execution_partition,
454
+ dynamic_block_index=dynamic_block_index,
455
+ )
456
+
457
+ return [
458
+ variable_object.read_data(
459
+ sample=sample,
460
+ sample_count=sample_count,
461
+ )
462
+ for variable_object in variable_objects
463
+ ]
464
+
465
+
466
+ def __get_first_data_output_variable(
467
+ block: Any,
468
+ execution_partition: Optional[str] = None,
469
+ dynamic_block_index: Optional[int] = None,
470
+ ):
364
471
  variable_objects = get_variable_objects(
365
472
  block,
366
473
  execution_partition=execution_partition,
367
474
  dynamic_block_index=dynamic_block_index,
368
475
  )
476
+ return get_first_data_output_variable(variable_objects)
477
+
478
+
479
+ def get_dynamic_children_count(
480
+ block: Any,
481
+ dynamic_block_index: Optional[int] = None,
482
+ execution_partition: Optional[str] = None,
483
+ variable_uuid: Optional[str] = None,
484
+ ) -> Tuple[Optional[int], bool]:
485
+ output_variable = __get_first_data_output_variable(
486
+ block, execution_partition=execution_partition, dynamic_block_index=dynamic_block_index
487
+ )
488
+ if output_variable:
489
+ return output_variable.items_count(), output_variable.is_partial_data_readable()
490
+
491
+ return None, False
492
+
493
+
494
+ def get_partial_dynamic_block_outputs(
495
+ block: Any,
496
+ index: int,
497
+ batch_settings: Optional[BatchSettings] = None,
498
+ chunks: Optional[List[ChunkKeyTypeUnion]] = None,
499
+ dynamic_block_index: Optional[int] = None,
500
+ execution_partition: Optional[str] = None,
501
+ input_data_types: Optional[List[InputDataType]] = None,
502
+ ) -> Tuple[Optional[Any], Optional[Dict[str, Any]]]:
503
+ output_variable = __get_first_data_output_variable(
504
+ block, execution_partition=execution_partition, dynamic_block_index=dynamic_block_index
505
+ )
506
+ result = None
507
+ if output_variable and output_variable.is_partial_data_readable():
508
+ result = block.read_partial_data(
509
+ output_variable.uuid,
510
+ batch_settings=batch_settings,
511
+ chunks=chunks,
512
+ partition=execution_partition,
513
+ input_data_types=input_data_types,
514
+ part_uuid=int(index),
515
+ )
369
516
 
370
- return [variable_object.read_data(
371
- sample=sample,
372
- sample_count=sample_count,
373
- ) for variable_object in variable_objects]
517
+ return result, None
374
518
 
375
519
 
376
520
  def get_outputs_for_dynamic_block(
377
- block,
378
- **kwargs
379
- ) -> Tuple[List[Union[Dict, int, str, pd.DataFrame]], List[Dict]]:
380
- values = get_outputs(block, **kwargs)
521
+ block, origin_block: Optional[Any] = None, **kwargs
522
+ ) -> List[Optional[Union[Dict, int, str, pd.DataFrame, Any]]]:
523
+ def func():
524
+ values = get_outputs(block, **kwargs)
381
525
 
382
- if BlockLanguage.SQL == block.language:
383
- return values[0] if len(values) == 1 else values, None
526
+ if BlockLanguage.SQL == block.language:
527
+ return [values[0] if len(values) == 1 else values, None]
384
528
 
385
- if len(values) >= 2:
386
- return values[0], values[1]
387
- elif len(values) >= 1:
388
- return values[0], None
529
+ if len(values) >= 2:
530
+ return values[0], values[1]
531
+ elif len(values) >= 1:
532
+ return [values[0], None]
389
533
 
390
- return None, None
534
+ return [None, None]
535
+
536
+ if DEBUG_MEMORY:
537
+ result, _ = execute_with_memory_tracking(
538
+ func,
539
+ log_message_prefix=f'[{(origin_block or block).uuid}:get_outputs_for_dynamic_block]',
540
+ )
541
+
542
+ return result
543
+
544
+ return func()
391
545
 
392
546
 
393
547
  async def get_outputs_for_dynamic_block_async(
394
- block,
395
- **kwargs
396
- ) -> Tuple[List[Union[Dict, int, str, pd.DataFrame]], List[Dict]]:
548
+ block, **kwargs
549
+ ) -> List[Optional[Union[Dict, int, str, pd.DataFrame, Any]]]:
397
550
  values = await get_outputs_async(block, **kwargs)
398
551
 
399
552
  if BlockLanguage.SQL == block.language:
@@ -409,29 +562,58 @@ async def get_outputs_for_dynamic_block_async(
409
562
 
410
563
  def get_outputs_for_dynamic_child(
411
564
  block,
412
- execution_partition: str = None,
413
- logger: Logger = None,
414
- logging_tags: Dict = None,
565
+ execution_partition: Optional[str] = None,
566
+ limit_parts: Optional[int] = None,
567
+ logger: Optional[Logger] = None,
568
+ logging_tags: Optional[Dict] = None,
415
569
  sample: bool = False,
416
- sample_count: int = None,
570
+ sample_count: Optional[int] = None,
417
571
  ) -> List[Tuple[List[Union[Dict, int, str, pd.DataFrame]], List[Dict]]]:
418
- # List[List[Variable]]
419
- list_of_lists_of_variables = __get_all_variable_objects_for_dynamic_child(
420
- block,
421
- execution_partition=execution_partition,
572
+ def func():
573
+ # List[List[Variable]]
574
+ list_of_lists_of_variables = __get_all_variable_objects_for_dynamic_child(
575
+ block,
576
+ execution_partition=execution_partition,
577
+ limit_parts=limit_parts,
578
+ )
579
+
580
+ # List[List[LazyVariableSet]]
581
+ lazy_variables_sets = [
582
+ LazyVariableSet(
583
+ block,
584
+ variable_objects,
585
+ logger=logger,
586
+ logging_tags=logging_tags,
587
+ sample=sample,
588
+ sample_count=sample_count,
589
+ )
590
+ for variable_objects in list_of_lists_of_variables
591
+ ]
592
+
593
+ return LazyVariableController(block, lazy_variables_sets)
594
+
595
+ result, _ = execute_with_memory_tracking(
596
+ func,
597
+ log_message_prefix=f'[{block.uuid}:get_outputs_for_dynamic_child]',
422
598
  )
599
+ return result
423
600
 
424
- # List[List[LazyVariableSet]]
425
- lazy_variables_sets = [LazyVariableSet(
426
- block,
427
- variable_objects,
428
- logger=logger,
429
- logging_tags=logging_tags,
430
- sample=sample,
431
- sample_count=sample_count,
432
- ) for variable_objects in list_of_lists_of_variables]
433
601
 
434
- return LazyVariableController(block, lazy_variables_sets)
602
+ def dynamic_upstream_block_item_counts(block, partition: Optional[str] = None) -> List[int]:
603
+ from mage_ai.data_preparation.models.block.dynamic.counter import DynamicItemCounter
604
+ from mage_ai.data_preparation.models.block.dynamic.utils import (
605
+ is_dynamic_block,
606
+ is_dynamic_block_child,
607
+ )
608
+
609
+ return [
610
+ DynamicItemCounter.build_counter(
611
+ b, downstream_block=block, partition=partition
612
+ ).item_count()
613
+ for b in block.upstream_blocks
614
+ if (b.is_dynamic_v2 and (b.should_dynamically_generate_block(block) or b.is_dynamic_child))
615
+ or (is_dynamic_block(b) or is_dynamic_block_child(b))
616
+ ]
435
617
 
436
618
 
437
619
  def fetch_input_variables_for_dynamic_upstream_blocks(
@@ -452,11 +634,21 @@ def fetch_input_variables_for_dynamic_upstream_blocks(
452
634
  input_vars = []
453
635
  kwargs_vars = []
454
636
  upstream_block_uuids = []
637
+ dynamic_upstream_item_counts = dynamic_upstream_block_item_counts(
638
+ block, partition=execution_partition
639
+ )
455
640
 
456
- for upstream_block in block.upstream_blocks:
457
- is_dynamic_child = is_dynamic_block_child(upstream_block)
458
- is_dynamic = is_dynamic_block(upstream_block)
459
- reduce_output = should_reduce_output(upstream_block)
641
+ for upstream_position_index, upstream_block in enumerate(block.upstream_blocks):
642
+ if block.is_dynamic_v2:
643
+ is_dynamic_child = upstream_block.is_dynamic_child
644
+ is_dynamic = upstream_block.should_dynamically_generate_block(block)
645
+ reduce_output = upstream_block.should_reduce_output_for_downstream_block(
646
+ block
647
+ ) or block.should_reduce_output_from_upstream_block(upstream_block)
648
+ else:
649
+ is_dynamic_child = is_dynamic_block_child(upstream_block)
650
+ is_dynamic = is_dynamic_block(upstream_block)
651
+ reduce_output = should_reduce_output(upstream_block)
460
652
 
461
653
  upstream_block_uuid = upstream_block.uuid
462
654
 
@@ -470,7 +662,7 @@ def fetch_input_variables_for_dynamic_upstream_blocks(
470
662
 
471
663
  # If dynamic child should reduce its output (which means it passes the entire
472
664
  # output to its downstream blocks):
473
- if should_reduce_output(upstream_block) and block.type != BlockType.EXTENSION:
665
+ if reduce_output and block.type != BlockType.EXTENSION:
474
666
  child_data = []
475
667
  metadata = {}
476
668
  for lazy_variable_set in lazy_variable_controller:
@@ -485,6 +677,12 @@ def fetch_input_variables_for_dynamic_upstream_blocks(
485
677
  # The first index is used to select which dynamic child to get data from
486
678
  # the 2nd index is used to determine which value from the dynamic list to
487
679
  # fetch as the input variable.
680
+ index = calculate_dynamic_index_data_index(
681
+ dynamic_block_index,
682
+ upstream_position_index,
683
+ len(lazy_variable_controller),
684
+ dynamic_upstream_item_counts,
685
+ )
488
686
  pair = lazy_variable_controller.render(
489
687
  child_dynamic_block_index=dynamic_block_index,
490
688
  )
@@ -492,22 +690,64 @@ def fetch_input_variables_for_dynamic_upstream_blocks(
492
690
  input_vars.append(child_data)
493
691
  kwargs_vars.append(metadata)
494
692
  elif is_dynamic:
495
- child_data, metadata = get_outputs_for_dynamic_block(
496
- upstream_block,
497
- execution_partition=execution_partition,
498
- )
499
- index = dynamic_block_index % len(child_data)
500
-
501
- if isinstance(child_data, list):
502
- input_vars.append(child_data[index])
503
- elif isinstance(child_data, pd.DataFrame):
504
- row = child_data.iloc[index]
505
- input_vars.append(row.to_dict() if row is not None else row)
506
- elif isinstance(child_data, dict):
507
- input_vars.append(child_data.get(index))
508
-
509
- if metadata and index < len(metadata):
510
- kwargs_vars.append(metadata[index])
693
+ child_data_count = None
694
+ is_partial_data_readable = False
695
+
696
+ if MEMORY_MANAGER_V2:
697
+ child_data_count, is_partial_data_readable = get_dynamic_children_count(
698
+ upstream_block,
699
+ execution_partition=execution_partition,
700
+ )
701
+
702
+ if child_data_count is not None and is_partial_data_readable:
703
+ index = calculate_dynamic_index_data_index(
704
+ dynamic_block_index,
705
+ upstream_position_index,
706
+ child_data_count,
707
+ dynamic_upstream_item_counts,
708
+ )
709
+ child_data, metadata = get_partial_dynamic_block_outputs(
710
+ upstream_block,
711
+ index,
712
+ batch_settings=block.upstream_batch_settings(upstream_block.uuid),
713
+ chunks=block.upstream_chunks(upstream_block.uuid),
714
+ execution_partition=execution_partition,
715
+ input_data_types=block.input_data_types(upstream_block.uuid),
716
+ )
717
+ input_vars.append(child_data)
718
+
719
+ if metadata is not None and isinstance(metadata, dict):
720
+ kwargs_vars.append(metadata)
721
+ else:
722
+ child_data, metadata = get_outputs_for_dynamic_block(
723
+ upstream_block,
724
+ execution_partition=execution_partition,
725
+ )
726
+ child_data_count = len(child_data) if hasattr(child_data, '__len__') else 0
727
+ if child_data_count >= 1:
728
+ index = calculate_dynamic_index_data_index(
729
+ dynamic_block_index,
730
+ upstream_position_index,
731
+ child_data_count,
732
+ dynamic_upstream_item_counts,
733
+ )
734
+
735
+ if isinstance(child_data, list):
736
+ input_vars.append(child_data[index])
737
+ elif isinstance(child_data, (pd.DataFrame,)):
738
+ row = child_data.iloc[index]
739
+ input_vars.append(row)
740
+ elif isinstance(child_data, (pl.DataFrame,)):
741
+ row = child_data[index]
742
+ input_vars.append(row)
743
+ elif isinstance(child_data, dict):
744
+ input_vars.append(child_data.get(index))
745
+
746
+ if metadata is not None:
747
+ if isinstance(metadata, list) and index < len(metadata):
748
+ kwargs_vars.append(metadata[index])
749
+ elif isinstance(metadata, dict):
750
+ kwargs_vars.append(metadata)
511
751
  else:
512
752
  from mage_ai.data_preparation.models.block.utils import (
513
753
  fetch_input_variables,