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
@@ -23,13 +23,13 @@ class FileFactory(BaseFactory):
23
23
  files = []
24
24
 
25
25
  async def build_and_score(line: str, files=files, factory=self):
26
- full_path, file_size, modified_timestamp = line.split(',')
26
+ full_path, file_size, modified_timestamp = line.split(",")
27
27
  filename = os.path.basename(full_path)
28
28
  modified_at = datetime.fromtimestamp(float(modified_timestamp)).isoformat()
29
29
 
30
30
  path_dict = shorten_directory(full_path)
31
- extension = path_dict.get('extension')
32
- directory = path_dict.get('directory')
31
+ extension = path_dict.get("extension")
32
+ directory = path_dict.get("directory")
33
33
 
34
34
  item_dict = dict(
35
35
  item_type=ItemType.DETAIL,
@@ -55,7 +55,6 @@ class FileFactory(BaseFactory):
55
55
  ),
56
56
  ),
57
57
  )
58
-
59
58
  scored = factory.filter_score(item_dict)
60
59
  if scored:
61
60
  files.append(scored)
@@ -64,23 +63,26 @@ class FileFactory(BaseFactory):
64
63
  now = datetime.utcnow().timestamp()
65
64
  cache = FileCache.initialize_cache_with_settings()
66
65
  lines = await cache.load() or []
67
- print(f'[FileFactory] Load files: {len(lines)} - {datetime.utcnow().timestamp() - now}')
66
+ print(
67
+ f"[FileFactory] Load files: {len(lines)} - {datetime.utcnow().timestamp() - now}"
68
+ )
68
69
 
69
70
  now = datetime.utcnow().timestamp()
70
- await asyncio.gather(
71
- *[build_and_score(item_dict) for item_dict in lines]
72
- )
71
+ await asyncio.gather(*[build_and_score(item_dict) for item_dict in lines])
73
72
  print(
74
- f'[FileFactory] Search {self.search}: '
75
- f'{len(files)} - {datetime.utcnow().timestamp() - now}',
73
+ f"[FileFactory] Search {self.search}: "
74
+ f"{len(files)} - {datetime.utcnow().timestamp() - now}",
76
75
  )
77
76
 
78
77
  now = datetime.utcnow().timestamp()
79
78
  files = await self.rank_items(files)
80
- files = [merge_dict(
81
- item_dict,
82
- add_application_actions(item_dict),
83
- ) for item_dict in files]
84
- print(f'[FileFactory] Rank items: {datetime.utcnow().timestamp() - now}')
79
+ files = [
80
+ merge_dict(
81
+ item_dict,
82
+ add_application_actions(item_dict),
83
+ )
84
+ for item_dict in files
85
+ ]
86
+ print(f"[FileFactory] Rank items: {datetime.utcnow().timestamp() - now}")
85
87
 
86
88
  return files[:10] + items
@@ -4,27 +4,39 @@ from typing import Dict
4
4
 
5
5
 
6
6
  def shorten_directory(full_path: str) -> Dict:
7
- parts = Path(os.path.dirname(full_path)).parts
7
+ # Use Path object for simplicity and cross-platform compatibility
8
+ path_obj = Path(full_path)
9
+ parts = path_obj.parts
8
10
  parts_count = len(parts)
9
- dir_name = ''
10
- if parts_count >= 1:
11
- os.path.join(*parts[max([0, parts_count - 3]):])
12
11
 
12
+ # Initialize dir_name as an empty string
13
+ dir_name = ""
14
+ # Handle directory part; ignore the filename in parts
15
+ if parts_count > 1:
16
+ # Join all parts except the last one (filename)
17
+ dir_name = os.path.join(*parts[: parts_count - 1])
18
+
19
+ # Simplifying the directory to show only relevant parts (3 levels up max)
13
20
  if parts_count >= 4:
14
- if parts_count >= 5:
15
- dir_name = os.path.join('.', dir_name)
21
+ if parts_count > 4:
22
+ # For deeply nested paths, show as relative path starting with ..
23
+ relevant_parts = parts[-3:]
24
+ dir_name = os.path.join("..", *relevant_parts)
16
25
  else:
17
- dir_name = os.path.join('..', dir_name)
26
+ # If exactly 4 levels deep, show entire path
27
+ dir_name = os.path.join(*parts[:-1])
18
28
 
19
- for _i in range(min(1, parts_count - 4)):
20
- dir_name = os.path.join('..', dir_name)
29
+ # Extracting extension (without the dot)
30
+ extension = (
31
+ path_obj.suffix[1:] if path_obj.suffix.startswith(".") else path_obj.suffix
32
+ )
21
33
 
22
- extension = Path(full_path or '').suffix
23
- if extension:
24
- extension = extension.replace('.', '')
34
+ # Include the filename in the output
35
+ filename = path_obj.name
25
36
 
26
37
  return dict(
27
38
  directory=dir_name,
28
39
  extension=extension,
29
- parts=parts,
40
+ parts=parts[:-1], # Exclude the filename from 'parts'
41
+ filename=filename,
30
42
  )
File without changes
@@ -0,0 +1,45 @@
1
+ from typing import AsyncGenerator, Generator, Iterable, List, Union
2
+
3
+ import polars as pl
4
+
5
+ from mage_ai.data.models.generator import DataGenerator
6
+ from mage_ai.data.models.pyarrow.record_batch import RecordBatch, TaggedRecordBatch
7
+ from mage_ai.data_preparation.models.variables.constants import VariableType
8
+ from mage_ai.shared.models import BaseEnum
9
+
10
+ SUPPORTED_VARIABLE_TYPES = [
11
+ VariableType.DATAFRAME,
12
+ VariableType.POLARS_DATAFRAME,
13
+ VariableType.SERIES_PANDAS,
14
+ VariableType.SERIES_POLARS,
15
+ ]
16
+
17
+ ScanBatchDatasetResult = Union[RecordBatch, TaggedRecordBatch, pl.DataFrame]
18
+ OutputData = Union[
19
+ DataGenerator,
20
+ List[pl.DataFrame],
21
+ Iterable[ScanBatchDatasetResult],
22
+ List[ScanBatchDatasetResult],
23
+ ]
24
+
25
+ RecordBatchGenerator = Union[Generator[ScanBatchDatasetResult, None, None], DataGenerator]
26
+
27
+ AsyncRecordBatchGenerator = AsyncGenerator[ScanBatchDatasetResult, None]
28
+
29
+
30
+ class InputDataType(BaseEnum):
31
+ # Batch settings will be used to fetch the data in batches,
32
+ # and execute the decorated function inside a yield loop.
33
+ BATCH = 'batch'
34
+ # @chunker, @chunking, @chunk
35
+ # CHUNKS = 'chunks' # This will be handled in the block code
36
+ # Original data will be passed as is.
37
+ DEFAULT = 'default'
38
+ # A generator to iterate over
39
+ GENERATOR = 'generator'
40
+ # Input variable will be a Callable function that loads the data; e.g. Variable object
41
+ READER = 'reader'
42
+
43
+
44
+ class ReadModeType(BaseEnum):
45
+ MEMORY = 'memory'
File without changes
@@ -0,0 +1,119 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import Any, List, Optional, Union
4
+
5
+ from mage_ai.data.constants import InputDataType
6
+ from mage_ai.data.models.constants import CHUNKS_DIRECTORY_NAME
7
+ from mage_ai.data.models.utils import variable_type_supported
8
+ from mage_ai.data.tabular.models import BatchSettings
9
+ from mage_ai.data_preparation.models.variables.constants import VariableType
10
+ from mage_ai.data_preparation.storage.base_storage import BaseStorage
11
+ from mage_ai.settings.repo import get_variables_dir
12
+ from mage_ai.system.models import ResourceUsage
13
+ from mage_ai.system.storage.utils import size_of_path
14
+
15
+
16
+ class BaseData:
17
+ def __init__(
18
+ self,
19
+ storage: BaseStorage,
20
+ variable_dir_path: str,
21
+ variable_path: str,
22
+ batch_settings: Optional[BatchSettings] = None,
23
+ chunks: Optional[List[Any]] = None,
24
+ input_data_types: Optional[List[InputDataType]] = None,
25
+ poll_interval: Optional[int] = None,
26
+ uuid: Optional[str] = None,
27
+ variable_type: Optional[VariableType] = None,
28
+ variable_types: Optional[List[VariableType]] = None,
29
+ variables_dir: Optional[str] = None,
30
+ ):
31
+ self.storage = storage
32
+ """
33
+ ~/.mage_data/[project_name]/pipelines/[pipeline_uuid]/.variables
34
+ /[pipeline_run.id]/[execution_partition]/[block.uuid]
35
+ ~/.mage_data/unit_3_observability/pipelines/sklearn_training/.variables
36
+ /9/20240518T144726_954384/load_models
37
+ """
38
+ self.variable_dir_path = variable_dir_path
39
+ """
40
+ ~/.mage_data/[project_name]/pipelines/[pipeline_uuid]/.variables
41
+ /[pipeline_run.id]/[execution_partition]/[block.uuid]
42
+ /[variable_name]
43
+
44
+ ~/.mage_data/unit_3_observability/pipelines/sklearn_training/.variables
45
+ /9/20240518T144726_954384/load_models
46
+ /output_0
47
+ """
48
+ self.batch_settings = batch_settings
49
+ self.chunks = chunks
50
+ self.poll_interval = poll_interval
51
+ self.variable_path = variable_path
52
+ self.variable_type = variable_type
53
+ self.variable_types = variable_types or []
54
+ self.variables_dir = variables_dir or get_variables_dir(root_project=False)
55
+ self.uuid = uuid or str(Path(self.variable_dir_path).relative_to(Path(self.variables_dir)))
56
+
57
+ @property
58
+ def data_source(self) -> Union[str, List[str]]:
59
+ if self.variable_types and len(self.variable_types) >= 1:
60
+ return self.__data_source_paths
61
+ return self.data_source_directory_path
62
+
63
+ @property
64
+ def number_of_outputs(self) -> int:
65
+ return (
66
+ len(self.variable_types)
67
+ if self.variable_types and len(self.variable_types) >= 1
68
+ else 1
69
+ )
70
+
71
+ @property
72
+ def data_source_directory_path(self) -> str:
73
+ return self.__build_data_source_path()
74
+
75
+ @property
76
+ def __data_source_paths(self) -> List[str]:
77
+ if self.variable_types:
78
+ return [
79
+ self.__build_data_source_path(str(idx)) for idx in range(len(self.variable_types))
80
+ ]
81
+ return [self.data_source_directory_path]
82
+
83
+ def __build_data_source_path(self, subdirectory: Optional[str] = None) -> str:
84
+ return os.path.join(self.variable_path, subdirectory or '', CHUNKS_DIRECTORY_NAME)
85
+
86
+ def is_dataframe(self) -> bool:
87
+ return all(
88
+ variable_type
89
+ in [
90
+ VariableType.DATAFRAME,
91
+ VariableType.POLARS_DATAFRAME,
92
+ VariableType.SERIES_PANDAS,
93
+ VariableType.SERIES_POLARS,
94
+ ]
95
+ for variable_type in (self.variable_types or [self.variable_type])
96
+ )
97
+
98
+ @property
99
+ def resource_usage(self) -> ResourceUsage:
100
+ return ResourceUsage.combine(self.resource_usages)
101
+
102
+ @property
103
+ def resource_usages(self) -> List[ResourceUsage]:
104
+ return [
105
+ ResourceUsage.load(
106
+ directory=path,
107
+ size=size_of_path(path, file_extension='parquet'),
108
+ )
109
+ for path in self.__data_source_paths
110
+ ]
111
+
112
+ def supported(self, data: Optional[Any] = None) -> bool:
113
+ if self.variable_types and len(self.variable_types) >= 1:
114
+ return all(
115
+ variable_type_supported(variable_type, data)
116
+ for variable_type in self.variable_types
117
+ )
118
+
119
+ return variable_type_supported(self.variable_type, data)
@@ -0,0 +1 @@
1
+ CHUNKS_DIRECTORY_NAME = 'chunks'
@@ -0,0 +1,115 @@
1
+ from collections.abc import Generator
2
+ from typing import Any, Callable, Dict, List, Optional
3
+
4
+
5
+ class DataGenerator:
6
+ def __init__(
7
+ self,
8
+ data: Optional[Any] = None,
9
+ load_data: Optional[Callable[[int], Any]] = None,
10
+ measure_data: Optional[Callable[[int], int]] = None,
11
+ ):
12
+ self.data = data
13
+ self.index = 0
14
+ self.load_data = load_data
15
+ self.measure_data = measure_data
16
+ self._length = None
17
+
18
+ def __len__(self):
19
+ # Check if the total length has been determined already
20
+ if self._length is None:
21
+ # Logic to determine the length from the datasource
22
+ # This could involve querying the database,
23
+ # reading file info, etc., without loading all data
24
+ self._length = self._data_length(self.index)
25
+ return self._length
26
+
27
+ def __iter__(self):
28
+ if self.data is not None and hasattr(self.data, '__iter__'):
29
+ for item in self.data:
30
+ yield item
31
+ elif self.data is not None and hasattr(self.data, '__getitem__'):
32
+ for item in self.__sequence_iterator():
33
+ yield item
34
+ else:
35
+ while self.index < self._data_length(self.index):
36
+ item = None
37
+ if self.load_data:
38
+ item = self.load_data(self.index)
39
+ elif self.data is not None:
40
+ item = self.data[self.index]
41
+ self.index += 1
42
+ yield item
43
+ self.data = None # Explicitly set data to None after iteration is finished
44
+
45
+ def __next__(self):
46
+ if self.index < self._data_length(self.index):
47
+ # Load the next item
48
+ item = None
49
+ if self.load_data:
50
+ item = self.load_data(self.index)
51
+ elif self.data is not None:
52
+ item = self.data[self.index]
53
+ self.index += 1
54
+ return item
55
+ else:
56
+ self.data = None # Set data to None when the generator is exhausted
57
+ # No more data, stop iteration
58
+ raise StopIteration
59
+
60
+ def iterable(self) -> bool:
61
+ return hasattr(self.data, '__iter__') or hasattr(self.data, '__getitem__')
62
+
63
+ def _data_length(self, index: Optional[int] = None) -> int:
64
+ if self.measure_data:
65
+ return self.measure_data(index or 0)
66
+ return len(self.data) if self.data is not None else 0
67
+
68
+ def __sequence_iterator(self) -> Any:
69
+ # Custom iterator for objects supporting the sequence protocol without __iter__
70
+ class SeqIterator:
71
+ def __init__(self, seq):
72
+ self.seq = seq
73
+ self.index = 0
74
+
75
+ def __next__(self):
76
+ try:
77
+ result = self.seq[self.index]
78
+ except IndexError:
79
+ raise StopIteration
80
+ self.index += 1
81
+ return result
82
+
83
+ return SeqIterator(self.data)
84
+
85
+
86
+ class GeneratorWithMetadata:
87
+ def __init__(self, generator: Generator, metadata: Optional[List[Dict[str, Any]]]):
88
+ """
89
+ Initializes the custom generator wrapper with a generator and associated metadata.
90
+
91
+ :param generator: The generator to wrap.
92
+ :param metadata: A dictionary containing metadata related to the generator.
93
+ """
94
+ self._generator = generator
95
+ self.metadata = metadata
96
+
97
+ def __iter__(self):
98
+ """
99
+ Returns the iterator object itself.
100
+ """
101
+ return self
102
+
103
+ def __next__(self):
104
+ """
105
+ Returns the next item from the generator.
106
+ """
107
+ return next(self._generator)
108
+
109
+ def get_metadata(self) -> Dict[str, Any]:
110
+ """
111
+ Returns the stored metadata.
112
+
113
+ :return: A dictionary containing metadata.
114
+ """
115
+ return self.metadata
@@ -0,0 +1,168 @@
1
+ from typing import Any, Dict, List, Optional, Union
2
+
3
+ import pandas as pd
4
+ import polars as pl
5
+
6
+ from mage_ai.data.constants import (
7
+ InputDataType,
8
+ OutputData,
9
+ RecordBatchGenerator,
10
+ ScanBatchDatasetResult,
11
+ )
12
+ from mage_ai.data.models.base import BaseData
13
+ from mage_ai.data.models.reader import Reader
14
+ from mage_ai.data.models.writer import Writer
15
+ from mage_ai.data.tabular.models import BatchSettings
16
+ from mage_ai.data_preparation.models.utils import infer_variable_type
17
+
18
+
19
+ class DataManager(BaseData):
20
+ def __init__(
21
+ self,
22
+ input_data_types: Optional[List[InputDataType]],
23
+ read_batch_settings: Optional[BatchSettings] = None,
24
+ read_chunks: Optional[List] = None,
25
+ write_batch_settings: Optional[BatchSettings] = None,
26
+ write_chunks: Optional[List] = None,
27
+ *args,
28
+ **kwargs,
29
+ ):
30
+ super().__init__(*args, **kwargs)
31
+ self.input_data_types = input_data_types or [InputDataType.DEFAULT]
32
+ self.read_batch_settings = read_batch_settings
33
+ self.read_chunks = read_chunks
34
+ self.write_batch_settings = write_batch_settings
35
+ self.write_chunks = write_chunks
36
+ self._reader = None
37
+ self._writer = None
38
+
39
+ @property
40
+ def batch_type(self) -> bool:
41
+ return InputDataType.BATCH in (self.input_data_types or [])
42
+
43
+ @property
44
+ def default_type(self) -> bool:
45
+ return not self.batch_type and not self.generator_type and not self.reader_type
46
+
47
+ @property
48
+ def generator_type(self) -> bool:
49
+ return InputDataType.GENERATOR in (self.input_data_types or [])
50
+
51
+ @property
52
+ def reader_type(self) -> bool:
53
+ return InputDataType.READER in (self.input_data_types or [])
54
+
55
+ @property
56
+ def reader(self) -> Reader:
57
+ if not self._reader:
58
+ self._reader = Reader(
59
+ batch_settings=self.read_batch_settings,
60
+ chunks=self.read_chunks,
61
+ storage=self.storage,
62
+ variable_dir_path=self.variable_dir_path,
63
+ variable_path=self.variable_path,
64
+ variable_type=self.variable_type,
65
+ variable_types=self.variable_types,
66
+ variables_dir=self.variables_dir,
67
+ )
68
+ return self._reader
69
+
70
+ @property
71
+ def writer(self) -> Writer:
72
+ if not self._writer:
73
+ self._writer = Writer(
74
+ batch_settings=self.write_batch_settings,
75
+ chunks=self.write_chunks,
76
+ storage=self.storage,
77
+ variable_dir_path=self.variable_dir_path,
78
+ variable_path=self.variable_path,
79
+ variable_type=self.variable_type,
80
+ variable_types=self.variable_types,
81
+ variables_dir=self.variables_dir,
82
+ )
83
+ return self._writer
84
+
85
+ def read_sync(
86
+ self,
87
+ limit_parts: Optional[int] = None,
88
+ part: Optional[int] = None,
89
+ sample: bool = False,
90
+ sample_count: Optional[int] = None,
91
+ ) -> Optional[Union[OutputData, ScanBatchDatasetResult, RecordBatchGenerator]]:
92
+ def __process_batch(batch: ScanBatchDatasetResult):
93
+ if batch is not None:
94
+ if isinstance(batch, (pd.DataFrame, pd.Series, pl.DataFrame, pl.Series)):
95
+ return batch
96
+ return batch.deserialize()
97
+
98
+ def __process_generator(generator_batch):
99
+ batches = [__process_batch(batch) for batch in generator_batch if batch is not None]
100
+
101
+ if self.batch_type:
102
+ return batches
103
+
104
+ if len(batches) >= 1:
105
+ item = batches[0]
106
+ if isinstance(item, pl.DataFrame):
107
+ return pl.concat(batches)
108
+ elif isinstance(item, pd.DataFrame):
109
+ return pd.concat(batches)
110
+
111
+ return batches
112
+
113
+ generator = self.reader.read_sync(
114
+ limit_parts=limit_parts,
115
+ part=part,
116
+ sample=sample,
117
+ sample_count=sample_count,
118
+ )
119
+
120
+ if sample:
121
+ if self.number_of_outputs == 1:
122
+ return __process_batch(generator)
123
+ return [__process_batch(batch) for batch in generator]
124
+ elif self.reader_type:
125
+ return self.reader
126
+ elif self.generator_type:
127
+ return generator
128
+
129
+ if self.number_of_outputs == 1:
130
+ return __process_generator(generator)
131
+
132
+ return [__process_generator(gen) for gen in generator]
133
+
134
+ async def read_async(
135
+ self,
136
+ limit_parts: Optional[int] = None,
137
+ sample: bool = False,
138
+ sample_count: Optional[int] = None,
139
+ ) -> Optional[Union[Any, str]]:
140
+ return self.read_sync(limit_parts=limit_parts, sample=sample, sample_count=sample_count)
141
+
142
+ async def write_async(
143
+ self,
144
+ data: Any,
145
+ chunk_size: Optional[int] = None,
146
+ ) -> Optional[Dict[str, int]]:
147
+ self.__prepare(data, self.writer)
148
+ return await self.writer.write_async(data)
149
+
150
+ def write_sync(
151
+ self,
152
+ data: Any,
153
+ chunk_size: Optional[int] = None,
154
+ ) -> Optional[Dict[str, int]]:
155
+ self.__prepare(data, self.writer)
156
+ return self.writer.write_sync(data)
157
+
158
+ def readable(self) -> bool:
159
+ return self.reader.supported()
160
+
161
+ def writeable(self, data: Optional[Any] = None) -> bool:
162
+ return self.writer.supported(data=data)
163
+
164
+ def __prepare(self, data: Any, base_data: BaseData) -> None:
165
+ if self.variable_type is None:
166
+ self.variable_type, _ = infer_variable_type(data)
167
+ if self.variable_type is not None:
168
+ base_data.variable_type = self.variable_type
File without changes
@@ -0,0 +1,55 @@
1
+ import math
2
+ from typing import Optional
3
+
4
+ import pyarrow as pa
5
+ import pyarrow.dataset as ds
6
+ from pandas.io.formats.style_render import Union
7
+
8
+ from mage_ai.data.models.generator import DataGenerator
9
+ from mage_ai.data.models.pyarrow.shared import Base
10
+ from mage_ai.data.models.pyarrow.table import Table
11
+ from mage_ai.data.tabular.constants import DEFAULT_BATCH_ITEMS_VALUE
12
+ from mage_ai.data.tabular.utils import DeserializedBatch
13
+
14
+
15
+ class Batch(Base):
16
+ def __init__(self, target: Union[pa.RecordBatch, ds.TaggedRecordBatch], **kwargs):
17
+ super().__init__(target, **kwargs)
18
+
19
+ def generator(
20
+ self, batch_size: Optional[int] = None, deserialize_on_consumption: Optional[bool] = False
21
+ ):
22
+ batch_size = batch_size or DEFAULT_BATCH_ITEMS_VALUE
23
+ table = pa.Table.from_batches([self.record_batch])
24
+ num_rows = table.num_rows
25
+
26
+ def __load(
27
+ index: int,
28
+ batch_size=batch_size,
29
+ deserialize_on_consumption=deserialize_on_consumption,
30
+ object_metadata=self.object_metadata,
31
+ table=table,
32
+ ) -> Union[DeserializedBatch, pa.Table]:
33
+ table_part = Table(
34
+ table.slice(offset=index * batch_size, length=batch_size),
35
+ )
36
+ return table_part.deserialize() if deserialize_on_consumption else table_part
37
+
38
+ def __measure(_index: int, batch_size=batch_size, num_rows=num_rows) -> int:
39
+ return math.ceil(num_rows / batch_size)
40
+
41
+ return DataGenerator(load_data=__load, measure_data=__measure)
42
+
43
+ @property
44
+ def record_batch(self) -> pa.RecordBatch:
45
+ return self.target
46
+
47
+
48
+ class RecordBatch(Batch):
49
+ pass
50
+
51
+
52
+ class TaggedRecordBatch(Batch):
53
+ @property
54
+ def record_batch(self) -> pa.RecordBatch:
55
+ return self.target.record_batch
@@ -0,0 +1,21 @@
1
+ from typing import Dict, Optional, Union
2
+
3
+ import pyarrow as pa
4
+ import pyarrow.dataset as ds
5
+
6
+ from mage_ai.data.tabular.utils import DeserializedBatch, deserialize_batch
7
+ from mage_ai.shared.models import Delegator
8
+
9
+
10
+ class Base(Delegator):
11
+ def __init__(
12
+ self,
13
+ target: Union[pa.RecordBatch, ds.TaggedRecordBatch, pa.Table],
14
+ object_metadata: Optional[Dict[str, str]] = None,
15
+ ):
16
+ self.target = target
17
+ self.delegate = Delegator(self.target)
18
+ self.object_metadata = object_metadata
19
+
20
+ def deserialize(self) -> DeserializedBatch:
21
+ return deserialize_batch(self.target, object_metadata=self.object_metadata)
@@ -0,0 +1,8 @@
1
+ import pyarrow as pa
2
+
3
+ from mage_ai.data.models.pyarrow.shared import Base
4
+
5
+
6
+ class Table(Base):
7
+ def __init__(self, target: pa.Table, **kwargs):
8
+ super().__init__(target, **kwargs)