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
@@ -2,10 +2,27 @@ import json
2
2
  import os
3
3
  from dataclasses import dataclass, field
4
4
  from enum import Enum
5
- from typing import Any, Dict, List, Tuple, Union
5
+ from typing import Any, Dict, List, Optional, Tuple, Union
6
6
 
7
7
  import pandas as pd
8
+ import polars as pl
9
+ from scipy.sparse import csr_matrix
8
10
 
11
+ from mage_ai.data_preparation.models.block.dynamic.shared import (
12
+ has_dynamic_block_upstream_parent as has_dynamic_block_upstream_parent_v1,
13
+ )
14
+ from mage_ai.data_preparation.models.block.dynamic.shared import (
15
+ has_reduce_output_from_upstreams as has_reduce_output_from_upstreams_v1,
16
+ )
17
+ from mage_ai.data_preparation.models.block.dynamic.shared import (
18
+ is_dynamic_block as is_dynamic_block_v1,
19
+ )
20
+ from mage_ai.data_preparation.models.block.dynamic.shared import (
21
+ is_dynamic_block_child as is_dynamic_block_child_v1,
22
+ )
23
+ from mage_ai.data_preparation.models.block.dynamic.shared import (
24
+ should_reduce_output as should_reduce_output_v1,
25
+ )
9
26
  from mage_ai.data_preparation.models.block.dynamic.variables import (
10
27
  get_outputs_for_dynamic_block,
11
28
  )
@@ -13,6 +30,11 @@ from mage_ai.data_preparation.models.constants import (
13
30
  DATAFRAME_ANALYSIS_MAX_COLUMNS,
14
31
  DATAFRAME_SAMPLE_COUNT_PREVIEW,
15
32
  )
33
+ from mage_ai.data_preparation.models.utils import (
34
+ is_basic_iterable,
35
+ is_dataframe_or_series,
36
+ prepare_data_for_output,
37
+ )
16
38
  from mage_ai.server.kernel_output_parser import DataType
17
39
  from mage_ai.shared.array import find
18
40
  from mage_ai.shared.custom_logger import DX_PRINTER
@@ -76,66 +98,23 @@ def extract_dynamic_block_index(block_run_block_uuid: str) -> int:
76
98
 
77
99
 
78
100
  def is_dynamic_block(block) -> bool:
79
- """
80
- Checks if the given block is a dynamic block.
81
-
82
- Args:
83
- block: The block.
84
-
85
- Returns:
86
- bool: True if the block is a dynamic block, False otherwise.
87
- """
88
- return block and block.configuration and block.configuration.get('dynamic', False)
101
+ return is_dynamic_block_v1(block)
89
102
 
90
103
 
91
104
  def should_reduce_output(block) -> bool:
92
- """
93
- Checks if the given block should reduce its output.
94
-
95
- Args:
96
- block: The block.
97
-
98
- Returns:
99
- bool: True if the block should reduce its output, False otherwise.
100
- """
101
- if not block or not block.configuration or not block.configuration.get('reduce_output', False):
102
- return False
103
- return True
105
+ return should_reduce_output_v1(block)
104
106
 
105
107
 
106
108
  def has_reduce_output_from_upstreams(block) -> bool:
107
- return any([should_reduce_output(upstream_block) for upstream_block in block.upstream_blocks])
109
+ return has_reduce_output_from_upstreams_v1(block)
108
110
 
109
111
 
110
112
  def has_dynamic_block_upstream_parent(block) -> bool:
111
- return block.upstream_blocks and any([is_dynamic_block(b) for b in block.upstream_blocks])
112
-
113
-
114
- def is_dynamic_block_child(block) -> bool:
115
- """
116
- Checks if the given block is a dynamic block child.
117
-
118
- Args:
119
- block: The block.
120
-
121
- Returns:
122
- bool: True if the block is a dynamic block child, False otherwise.
123
- """
124
- if not block:
125
- return False
126
-
127
- dynamic_or_child = []
113
+ return has_dynamic_block_upstream_parent_v1(block)
128
114
 
129
- for upstream_block in block.upstream_blocks:
130
- if is_dynamic_block(upstream_block) or is_dynamic_block_child(upstream_block):
131
- dynamic_or_child.append(upstream_block)
132
-
133
- if len(dynamic_or_child) == 0:
134
- return False
135
115
 
136
- dynamic_or_child_with_reduce = list(filter(lambda x: should_reduce_output(x), dynamic_or_child))
137
-
138
- return len(dynamic_or_child) > len(dynamic_or_child_with_reduce)
116
+ def is_dynamic_block_child(block, include_reduce_output: Optional[bool] = None) -> bool:
117
+ return is_dynamic_block_child_v1(block, include_reduce_output=include_reduce_output)
139
118
 
140
119
 
141
120
  def is_replicated_block(block) -> bool:
@@ -152,6 +131,7 @@ def is_original_dynamic_child_block(
152
131
 
153
132
  def __get_block_run(block_run_id=block_run_id):
154
133
  from mage_ai.orchestration.db.models.schedules import BlockRun
134
+
155
135
  return BlockRun.query.get(block_run_id)
156
136
 
157
137
  if block:
@@ -179,10 +159,10 @@ def is_original_dynamic_child_block(
179
159
 
180
160
  def uuid_for_output_variables(
181
161
  block,
182
- block_uuid: str = None,
183
- dynamic_block_index: int = None,
184
- dynamic_block_uuid: str = None,
185
- join_character: str = None,
162
+ block_uuid: Optional[str] = None,
163
+ dynamic_block_index: Optional[int] = None,
164
+ dynamic_block_uuid: Optional[str] = None,
165
+ join_character: Optional[str] = None,
186
166
  **kwargs,
187
167
  ) -> Tuple[str, bool]:
188
168
  changed = False
@@ -199,9 +179,9 @@ def uuid_for_output_variables(
199
179
  return os.path.join(block.uuid, str(dynamic_block_index)), True
200
180
 
201
181
  is_dynamic = is_dynamic_block(block)
202
- if (not is_dynamic and (dynamic_block_index is None or is_dynamic_child)) or \
203
- (is_dynamic and is_dynamic_child):
204
-
182
+ if (not is_dynamic and (dynamic_block_index is None or is_dynamic_child)) or (
183
+ is_dynamic and is_dynamic_child
184
+ ):
205
185
  parts = block_uuid.split(':')
206
186
 
207
187
  if len(parts) >= 2:
@@ -239,28 +219,38 @@ def uuid_for_output_variables(
239
219
  return (block_uuid, changed)
240
220
 
241
221
 
242
- def transform_dataframe_for_display(dataframe: pd.DataFrame) -> Dict:
222
+ def transform_dataframe_for_display(
223
+ dataframe: pd.DataFrame,
224
+ is_dynamic: bool = False,
225
+ is_dynamic_child: bool = False,
226
+ sample_columns: int = DATAFRAME_ANALYSIS_MAX_COLUMNS,
227
+ sample_count: int = DATAFRAME_SAMPLE_COUNT_PREVIEW,
228
+ shape: Optional[Tuple[int, int]] = None,
229
+ ) -> Dict:
243
230
  data = None
231
+
232
+ column_name = '-'
233
+ if is_dynamic:
234
+ column_name = 'dynamic child blocks'
235
+ elif is_dynamic_child:
236
+ column_name = 'output'
237
+
244
238
  if isinstance(dataframe, pd.DataFrame):
245
- columns_to_display = dataframe.columns.tolist()[:DATAFRAME_ANALYSIS_MAX_COLUMNS]
246
- row_count, column_count = dataframe.shape
239
+ columns_to_display = dataframe.columns.tolist()[:sample_columns]
240
+ row_count, column_count = shape or dataframe.shape
241
+
242
+ df = dataframe.iloc[:sample_count][columns_to_display]
247
243
 
248
244
  data = dict(
249
245
  columns=columns_to_display,
250
- rows=json.loads(
251
- dataframe[columns_to_display][:DATAFRAME_SAMPLE_COUNT_PREVIEW].to_json(
252
- orient='split',
253
- )
254
- )['data'],
255
- index=list(dataframe.index),
246
+ rows=json.loads(df.to_json(orient='split'))['data'],
256
247
  shape=[row_count, column_count],
257
248
  )
258
249
  else:
259
250
  data = dict(
260
- columns=['col0'],
261
- rows=[[dataframe[:DATAFRAME_SAMPLE_COUNT_PREVIEW]]],
262
- index=[0],
263
- shape=[1, 1],
251
+ columns=[column_name],
252
+ rows=[[dataframe[:sample_count]]],
253
+ shape=list(shape) if shape else [1, 1],
264
254
  )
265
255
 
266
256
  return dict(
@@ -269,10 +259,26 @@ def transform_dataframe_for_display(dataframe: pd.DataFrame) -> Dict:
269
259
  )
270
260
 
271
261
 
272
- def coerce_into_dataframe(child_data: Union[
273
- List[Union[Dict, int, str, pd.DataFrame]],
274
- pd.DataFrame
275
- ]) -> Dict:
262
+ def coerce_into_dataframe(
263
+ child_data: Union[
264
+ List[Union[Dict, int, str, pd.DataFrame]],
265
+ Dict,
266
+ int,
267
+ str,
268
+ pd.DataFrame,
269
+ ],
270
+ is_dynamic: bool = False,
271
+ is_dynamic_child: bool = False,
272
+ single_item_only: bool = False,
273
+ ) -> pd.DataFrame:
274
+ child_data, _ = prepare_data_for_output(child_data, single_item_only=single_item_only)
275
+
276
+ column_name = '-'
277
+ if is_dynamic:
278
+ column_name = 'dynamic child blocks'
279
+ elif is_dynamic_child:
280
+ column_name = 'output'
281
+
276
282
  if isinstance(child_data, list) and len(child_data) >= 1:
277
283
  item = child_data[0]
278
284
  if isinstance(item, pd.DataFrame):
@@ -281,34 +287,51 @@ def coerce_into_dataframe(child_data: Union[
281
287
  child_data = pd.DataFrame(child_data)
282
288
  else:
283
289
  child_data = pd.DataFrame(
284
- [dict(col=value) for value in child_data],
290
+ [
291
+ {
292
+ column_name: value,
293
+ }
294
+ for value in child_data
295
+ ],
285
296
  )
286
- elif isinstance(child_data, pd.DataFrame):
297
+ elif isinstance(child_data, (pd.DataFrame, pl.DataFrame)):
287
298
  return child_data
288
299
  else:
289
- child_data = pd.DataFrame([dict(col=child_data)])
300
+ child_data = pd.DataFrame([
301
+ {
302
+ column_name: child_data,
303
+ }
304
+ ])
290
305
 
291
306
  return child_data
292
307
 
293
308
 
294
- def limit_output(output: Union[List, pd.DataFrame], sample_count: int) -> Union[List, pd.DataFrame]:
295
- if sample_count is not None:
296
- if output is not None:
297
- if isinstance(output, list):
298
- output = output[:sample_count]
299
- elif isinstance(output, pd.DataFrame):
309
+ def limit_output(
310
+ output: Union[List, pd.DataFrame, pd.Series, csr_matrix],
311
+ sample_count: int = DATAFRAME_SAMPLE_COUNT_PREVIEW,
312
+ sample_columns: Optional[int] = DATAFRAME_ANALYSIS_MAX_COLUMNS,
313
+ ) -> Union[List, pd.DataFrame, pd.Series, csr_matrix]:
314
+ if sample_count is not None and output is not None:
315
+ if isinstance(output, list):
316
+ output = output[:sample_count]
317
+ elif isinstance(output, pd.Series):
318
+ output = output.iloc[:sample_count]
319
+ elif isinstance(output, pd.DataFrame):
320
+ if sample_columns is not None:
321
+ output = output.iloc[:sample_count, :sample_columns]
322
+ else:
300
323
  output = output.iloc[:sample_count]
324
+ elif isinstance(output, csr_matrix):
325
+ output = output[:sample_count] # For csr_matrix, this slices rows
326
+ if sample_columns is not None:
327
+ output = output[:, :sample_columns]
301
328
  return output
302
329
 
303
330
 
304
331
  def transform_output(
305
- output: Tuple[
306
- Union[
307
- List[Union[Dict, int, str, pd.DataFrame]],
308
- pd.DataFrame
309
- ],
310
- List[Dict]
311
- ],
332
+ output: Tuple[Union[List[Union[Dict, int, str, pd.DataFrame]], pd.DataFrame], List[Dict]],
333
+ is_dynamic: bool = False,
334
+ is_dynamic_child: bool = False,
312
335
  ):
313
336
  child_data = None
314
337
  metadata = None
@@ -321,39 +344,66 @@ def transform_output(
321
344
  if child_data is None:
322
345
  return []
323
346
 
324
- child_data = coerce_into_dataframe(child_data)
347
+ child_data = coerce_into_dataframe(
348
+ child_data,
349
+ is_dynamic=is_dynamic,
350
+ is_dynamic_child=is_dynamic_child,
351
+ )
325
352
 
326
353
  if isinstance(child_data, tuple):
327
- return transform_output(child_data)
354
+ return transform_output(
355
+ child_data,
356
+ is_dynamic=is_dynamic,
357
+ is_dynamic_child=is_dynamic_child,
358
+ )
328
359
  elif isinstance(child_data, list):
329
- child_data = [transform_dataframe_for_display(data) for data in child_data]
360
+ child_data = [
361
+ transform_dataframe_for_display(
362
+ data,
363
+ is_dynamic=is_dynamic,
364
+ is_dynamic_child=is_dynamic_child,
365
+ )
366
+ for data in child_data
367
+ ]
330
368
  else:
331
- child_data = transform_dataframe_for_display(child_data)
369
+ child_data = transform_dataframe_for_display(
370
+ child_data,
371
+ is_dynamic=is_dynamic,
372
+ is_dynamic_child=is_dynamic_child,
373
+ )
332
374
 
333
375
  if metadata is not None:
334
- metadata = transform_dataframe_for_display(coerce_into_dataframe(metadata))
376
+ metadata = transform_dataframe_for_display(
377
+ coerce_into_dataframe(
378
+ metadata,
379
+ is_dynamic=is_dynamic,
380
+ is_dynamic_child=is_dynamic_child,
381
+ ),
382
+ is_dynamic=is_dynamic,
383
+ is_dynamic_child=is_dynamic_child,
384
+ )
335
385
 
336
386
  return child_data, metadata
337
387
 
338
388
 
339
389
  def transform_output_for_display(
340
- output: Tuple[
341
- Union[
342
- List[Union[Dict, int, str, pd.DataFrame]],
343
- pd.DataFrame
344
- ],
345
- List[Dict]
346
- ],
347
- sample_count: int = None,
390
+ output: Tuple[Union[List[Union[Dict, int, str, pd.DataFrame]], pd.DataFrame], List[Dict]],
391
+ is_dynamic: bool = False,
392
+ is_dynamic_child: bool = False,
393
+ sample_count: Optional[int] = None,
394
+ sample_columns: Optional[int] = None,
348
395
  ) -> List[Dict]:
349
- child_data, metadata = transform_output(output)
350
- child_data = limit_output(child_data, sample_count)
351
- metadata = limit_output(metadata, sample_count)
396
+ child_data, metadata = transform_output(
397
+ output,
398
+ is_dynamic=is_dynamic,
399
+ is_dynamic_child=is_dynamic_child,
400
+ )
401
+ child_data = limit_output(child_data, sample_count, sample_columns=sample_columns)
402
+ metadata = limit_output(metadata, sample_count, sample_columns=sample_columns)
352
403
 
353
404
  return dict(
354
405
  data=dict(
355
- columns=['child_data', 'metadata'],
356
- index=[0, 1],
406
+ columns=['dynamic children data', 'metadata'],
357
407
  rows=[child_data, metadata],
358
408
  shape=[2, 2],
359
409
  ),
@@ -364,34 +414,54 @@ def transform_output_for_display(
364
414
 
365
415
  def transform_output_for_display_reduce_output(
366
416
  output: List[Any],
367
- sample_count: int = None,
417
+ is_dynamic: bool = False,
418
+ is_dynamic_child: bool = False,
419
+ sample_count: Optional[int] = None,
420
+ sample_columns: Optional[int] = None,
368
421
  ) -> List[Dict]:
369
- output = limit_output(output, sample_count)
422
+ output = [
423
+ limit_output(
424
+ values,
425
+ sample_count=sample_count,
426
+ sample_columns=sample_columns,
427
+ )
428
+ for values in output
429
+ ]
370
430
 
371
- arr = [dict(
372
- text_data=data,
373
- type=DataType.TEXT,
374
- variable_uuid=f'output_{idx}',
375
- ) for idx, data in enumerate(output)]
431
+ output = limit_output(output, sample_count=sample_count, sample_columns=sample_columns)
432
+
433
+ arr = [
434
+ dict(
435
+ text_data=data,
436
+ type=DataType.TEXT,
437
+ variable_uuid=f'reduced output {idx}',
438
+ )
439
+ for idx, data in enumerate(output)
440
+ ]
376
441
 
377
442
  return arr
378
443
 
379
444
 
380
- def combine_transformed_output_for_multi_output(transform_outputs: List[Dict]):
381
- columns = []
382
- index = []
445
+ def combine_transformed_output_for_multi_output(
446
+ transform_outputs: List[Dict],
447
+ columns: Optional[List[str]] = None,
448
+ is_grouping: bool = False,
449
+ ) -> Dict[str, Union[DataType, Dict, bool, str]]:
450
+ columns_use = columns or []
383
451
  for i in range(len(transform_outputs)):
384
- columns.append(f'child_{i}')
385
- index.append(i)
452
+ if not columns:
453
+ columns_use.append(f'output {i}')
386
454
 
387
455
  return dict(
388
456
  data=dict(
389
- columns=columns,
390
- index=index,
457
+ columns=columns_use,
391
458
  rows=transform_outputs,
392
- shape=[len(transform_outputs), len(columns)],
459
+ shape=[
460
+ len(transform_outputs),
461
+ len(columns_use),
462
+ ],
393
463
  ),
394
- type=DataType.TABLE,
464
+ type=DataType.GROUP if is_grouping else DataType.TABLE,
395
465
  multi_output=True,
396
466
  )
397
467
 
@@ -403,25 +473,41 @@ def transform_output_for_display_dynamic_child(
403
473
  Dict,
404
474
  int,
405
475
  str,
406
- pd.DataFrame
407
- ]
476
+ pd.DataFrame,
477
+ ],
408
478
  ],
409
479
  is_dynamic: bool = False,
410
- sample_count: int = None,
480
+ is_dynamic_child: bool = False,
481
+ single_item_only: bool = False,
411
482
  ) -> List[Dict]:
412
483
  df = None
413
484
  for output_from_variable_object in output:
414
- df_inner = coerce_into_dataframe(output_from_variable_object)
485
+ df_inner = coerce_into_dataframe(
486
+ output_from_variable_object,
487
+ is_dynamic=is_dynamic,
488
+ is_dynamic_child=is_dynamic_child,
489
+ single_item_only=single_item_only,
490
+ )
415
491
  if df is None:
416
492
  df = df_inner
417
493
  else:
418
- df = pd.concat([df, df_inner], axis=1)
419
-
420
- df = limit_output(df, sample_count)
421
- if isinstance(df, pd.DataFrame) and 1 == len(set(df.columns)):
422
- df.columns = [f'{col}_{idx}' for idx, col in enumerate(df.columns)]
423
-
424
- return transform_dataframe_for_display(df)
494
+ df.reset_index(drop=True, inplace=True)
495
+ df_inner.reset_index(drop=True, inplace=True)
496
+ df = pd.concat([df, df_inner], axis=1, ignore_index=True)
497
+
498
+ shape = None
499
+ if hasattr(df, 'shape'):
500
+ shape = df.shape
501
+
502
+ if isinstance(df, pd.DataFrame) and len(set(df.columns)) == 1:
503
+ df.columns = [str(idx) for idx, col in enumerate(df.columns)]
504
+
505
+ return transform_dataframe_for_display(
506
+ df,
507
+ is_dynamic=is_dynamic,
508
+ is_dynamic_child=is_dynamic_child,
509
+ shape=shape,
510
+ )
425
511
 
426
512
 
427
513
  def create_combinations(combinations: List[Any]) -> List[Any]:
@@ -430,7 +516,7 @@ def create_combinations(combinations: List[Any]) -> List[Any]:
430
516
 
431
517
  for idx, arr in enumerate(combinations_inner):
432
518
  for value in arr:
433
- combinations_next = combinations_inner[(idx + 1):]
519
+ combinations_next = combinations_inner[(idx + 1) :]
434
520
  if len(combinations_next) >= 1:
435
521
  for combos_down in __create_combinations(combinations_next):
436
522
  combos.append([value] + combos_down)
@@ -447,6 +533,7 @@ def create_combinations(combinations: List[Any]) -> List[Any]:
447
533
  def build_combinations_for_dynamic_child(
448
534
  block,
449
535
  execution_partition: str = None,
536
+ origin_block: Optional[Any] = None,
450
537
  **kwargs,
451
538
  ):
452
539
  """
@@ -469,6 +556,9 @@ def build_combinations_for_dynamic_child(
469
556
  [0, 1],
470
557
  ]
471
558
  """
559
+ if origin_block is None:
560
+ origin_block = block
561
+
472
562
  dynamic_counts = []
473
563
 
474
564
  for upstream_block in block.upstream_blocks:
@@ -493,16 +583,22 @@ def build_combinations_for_dynamic_child(
493
583
  children_created = build_combinations_for_dynamic_child(
494
584
  upstream_block,
495
585
  execution_partition=execution_partition,
586
+ origin_block=origin_block,
496
587
  )
497
588
  if is_dynamic:
498
589
  for dynamic_block_index in range(len(children_created)):
499
590
  values, _metadata = get_outputs_for_dynamic_block(
500
591
  upstream_block,
501
592
  execution_partition=execution_partition,
502
- dynamic_block_index=dynamic_block_index
593
+ dynamic_block_index=dynamic_block_index,
594
+ origin_block=origin_block,
503
595
  )
504
596
  if values is not None:
505
- arr.extend([idx for idx in range(len(values))])
597
+ if is_basic_iterable(values) or is_dataframe_or_series(values):
598
+ count = len(values)
599
+ else:
600
+ count = 1
601
+ arr.extend([idx for idx in range(count)])
506
602
  else:
507
603
  arr.append(0)
508
604
  else:
@@ -511,8 +607,12 @@ def build_combinations_for_dynamic_child(
511
607
  arr, _metadata = get_outputs_for_dynamic_block(
512
608
  upstream_block,
513
609
  execution_partition=execution_partition,
610
+ origin_block=origin_block,
514
611
  )
515
- if arr is not None:
612
+ if arr is not None:
613
+ if not is_basic_iterable(arr) and not is_dataframe_or_series(arr):
614
+ arr = [0]
615
+ if arr is not None and hasattr(arr, '__len__') and len(arr) > 0:
516
616
  dynamic_counts.append([idx for idx in range(len(arr))])
517
617
  else:
518
618
  dynamic_counts.append([0])
@@ -542,10 +642,12 @@ def build_combinations_for_dynamic_child(
542
642
  if is_dynamic_child or is_dynamic:
543
643
  dynamic_block_indexes[upstream_block.uuid] = parent_index
544
644
 
545
- settings.append(dict(
546
- dynamic_block_index=dynamic_block_index,
547
- dynamic_block_indexes=dynamic_block_indexes,
548
- ))
645
+ settings.append(
646
+ dict(
647
+ dynamic_block_index=dynamic_block_index,
648
+ dynamic_block_indexes=dynamic_block_indexes,
649
+ )
650
+ )
549
651
 
550
652
  return settings
551
653
 
@@ -596,7 +698,9 @@ class DynamicBlockWrapper(BaseDataClass):
596
698
  # Upstream blocks that are dynamic blocks.
597
699
  upstream_dynamic_blocks: List[DynamicBlockWrapperBase] = field(default_factory=lambda: [])
598
700
  # Upstream blocks that are dynamic child blocks.
599
- upstream_dynamic_child_blocks: List[DynamicBlockWrapperBase] = field(default_factory=lambda: [])
701
+ upstream_dynamic_child_blocks: List[DynamicBlockWrapperBase] = field(
702
+ default_factory=lambda: []
703
+ )
600
704
  # Unique identifier used as a suffix in the block run.
601
705
  uuid: str = None
602
706
 
@@ -650,8 +754,9 @@ class DynamicBlockWrapper(BaseDataClass):
650
754
  if not self.block:
651
755
  return False
652
756
 
653
- return self.block.uuid == self.block_run_block_uuid or \
654
- (self.is_replicated() and self.block.uuid_replicated == self.block_run_block_uuid)
757
+ return self.block.uuid == self.block_run_block_uuid or (
758
+ self.is_replicated() and self.block.uuid_replicated == self.block_run_block_uuid
759
+ )
655
760
 
656
761
  def is_replicated(self) -> bool:
657
762
  return DynamicBlockFlag.REPLICATED in (self.flags or []) or is_replicated_block(self.block)
@@ -676,11 +781,15 @@ class DynamicBlockWrapper(BaseDataClass):
676
781
  if DynamicBlockFlag.SPAWN_OF_DYNAMIC_CHILD in (self.flags or []):
677
782
  return True
678
783
 
679
- return (self.block or self.block_uuid) and \
680
- self.block_run_block_uuid and \
681
- ((self.block and self.block.uuid != self.block_run_block_uuid) or
682
- (self.block_uuid and self.block_uuid != self.block_run_block_uuid)) and \
683
- not self.is_original(include_clone=True)
784
+ return (
785
+ (self.block or self.block_uuid)
786
+ and self.block_run_block_uuid
787
+ and (
788
+ (self.block and self.block.uuid != self.block_run_block_uuid)
789
+ or (self.block_uuid and self.block_uuid != self.block_run_block_uuid)
790
+ )
791
+ and not self.is_original(include_clone=True)
792
+ )
684
793
 
685
794
  def should_reduce_output(self) -> bool:
686
795
  if DynamicBlockFlag.REDUCE_OUTPUT in (self.flags or []):
@@ -769,11 +878,13 @@ class DynamicBlockWrapper(BaseDataClass):
769
878
  **kwargs,
770
879
  ) -> dict:
771
880
  if use_metadata_instructions:
772
- return ignore_keys_with_blank_values(dict(
773
- clone_original=self.metadata_instructions.clone_original,
774
- original=self.metadata_instructions.original.to_dict_base(),
775
- upstream=self.metadata_instructions.upstream.to_dict_base(),
776
- ))
881
+ return ignore_keys_with_blank_values(
882
+ dict(
883
+ clone_original=self.metadata_instructions.clone_original,
884
+ original=self.metadata_instructions.original.to_dict_base(),
885
+ upstream=self.metadata_instructions.upstream.to_dict_base(),
886
+ )
887
+ )
777
888
 
778
889
  data = self.to_dict_base(**kwargs)
779
890
  if include_all:
@@ -906,11 +1017,14 @@ def check_all_dynamic_upstreams_completed(
906
1017
 
907
1018
  from mage_ai.orchestration.db.models.schedules import BlockRun
908
1019
 
909
- upstreams_done = all([check_all_dynamic_upstreams_completed(
910
- b,
911
- block_runs=block_runs,
912
- execution_partition=execution_partition,
913
- ) for b in upstream_block.upstream_blocks])
1020
+ upstreams_done = all([
1021
+ check_all_dynamic_upstreams_completed(
1022
+ b,
1023
+ block_runs=block_runs,
1024
+ execution_partition=execution_partition,
1025
+ )
1026
+ for b in upstream_block.upstream_blocks
1027
+ ])
914
1028
 
915
1029
  if not upstreams_done:
916
1030
  return False
@@ -922,17 +1036,26 @@ def check_all_dynamic_upstreams_completed(
922
1036
  execution_partition=execution_partition,
923
1037
  )
924
1038
 
925
- selected = [br for br in block_runs if pipeline.get_block(
926
- br.block_uuid,
927
- ).uuid == upstream_block.uuid and br.status == BlockRun.BlockRunStatus.COMPLETED]
1039
+ selected = [
1040
+ br
1041
+ for br in block_runs
1042
+ if pipeline.get_block(
1043
+ br.block_uuid,
1044
+ ).uuid
1045
+ == upstream_block.uuid
1046
+ and br.status == BlockRun.BlockRunStatus.COMPLETED
1047
+ ]
928
1048
 
929
1049
  if len(list(selected)) < len(combos) + 1:
930
1050
  return False
931
1051
 
932
- return all([br.status == BlockRun.BlockRunStatus.COMPLETED for br in filter(
933
- lambda br: pipeline.get_block(br.block_uuid).uuid == upstream_block.uuid,
934
- block_runs,
935
- )])
1052
+ return all([
1053
+ br.status == BlockRun.BlockRunStatus.COMPLETED
1054
+ for br in filter(
1055
+ lambda br: pipeline.get_block(br.block_uuid).uuid == upstream_block.uuid,
1056
+ block_runs,
1057
+ )
1058
+ ])
936
1059
 
937
1060
  # 1. Are all the upstream blocks for my upstream blocks completed?
938
1061
  # 2. Then, are my immediate upstream blocks completed?