mage-ai 0.9.69__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.
- mage_ai/ai/utils/xgboost.py +222 -0
- mage_ai/api/errors.py +37 -25
- mage_ai/api/operations/base.py +13 -1
- mage_ai/api/parsers/PipelineScheduleParser.py +1 -1
- mage_ai/api/policies/BackfillPolicy.py +1 -0
- mage_ai/api/policies/BlockOutputPolicy.py +40 -17
- mage_ai/api/policies/GlobalDataProductPolicy.py +91 -41
- mage_ai/api/policies/KernelPolicy.py +55 -32
- mage_ai/api/policies/KernelProcessPolicy.py +56 -0
- mage_ai/api/policies/OutputPolicy.py +73 -41
- mage_ai/api/policies/PipelinePolicy.py +206 -137
- mage_ai/api/policies/WorkspacePolicy.py +1 -0
- mage_ai/api/presenters/BackfillPresenter.py +1 -0
- mage_ai/api/presenters/BlockLayoutItemPresenter.py +9 -7
- mage_ai/api/presenters/BlockPresenter.py +1 -1
- mage_ai/api/presenters/GlobalDataProductPresenter.py +6 -1
- mage_ai/api/presenters/KernelPresenter.py +5 -26
- mage_ai/api/presenters/KernelProcessPresenter.py +28 -0
- mage_ai/api/presenters/PipelinePresenter.py +18 -5
- mage_ai/api/presenters/StatusPresenter.py +2 -0
- mage_ai/api/presenters/SyncPresenter.py +25 -0
- mage_ai/api/resources/AutocompleteItemResource.py +1 -1
- mage_ai/api/resources/BlockLayoutItemResource.py +90 -44
- mage_ai/api/resources/BlockOutputResource.py +42 -9
- mage_ai/api/resources/BlockResource.py +4 -3
- mage_ai/api/resources/BlockRunResource.py +27 -22
- mage_ai/api/resources/ClusterResource.py +4 -1
- mage_ai/api/resources/CustomTemplateResource.py +34 -14
- mage_ai/api/resources/DataProviderResource.py +1 -1
- mage_ai/api/resources/ExecutionStateResource.py +3 -1
- mage_ai/api/resources/FileContentResource.py +8 -2
- mage_ai/api/resources/FileResource.py +10 -4
- mage_ai/api/resources/FileVersionResource.py +3 -1
- mage_ai/api/resources/GitBranchResource.py +101 -31
- mage_ai/api/resources/GitCustomBranchResource.py +29 -1
- mage_ai/api/resources/GlobalDataProductResource.py +44 -7
- mage_ai/api/resources/GlobalHookResource.py +4 -1
- mage_ai/api/resources/IntegrationDestinationResource.py +6 -2
- mage_ai/api/resources/IntegrationSourceResource.py +8 -4
- mage_ai/api/resources/IntegrationSourceStreamResource.py +6 -2
- mage_ai/api/resources/KernelProcessResource.py +44 -0
- mage_ai/api/resources/KernelResource.py +25 -3
- mage_ai/api/resources/OauthResource.py +1 -1
- mage_ai/api/resources/OutputResource.py +33 -11
- mage_ai/api/resources/PageBlockLayoutResource.py +34 -23
- mage_ai/api/resources/PipelineInteractionResource.py +31 -15
- mage_ai/api/resources/PipelineResource.py +258 -125
- mage_ai/api/resources/PipelineRunResource.py +52 -7
- mage_ai/api/resources/PipelineScheduleResource.py +11 -2
- mage_ai/api/resources/PipelineTriggerResource.py +6 -1
- mage_ai/api/resources/ProjectResource.py +18 -7
- mage_ai/api/resources/PullRequestResource.py +6 -4
- mage_ai/api/resources/SecretResource.py +1 -1
- mage_ai/api/resources/SeedResource.py +8 -1
- mage_ai/api/resources/StatusResource.py +21 -6
- mage_ai/api/resources/SyncResource.py +6 -8
- mage_ai/api/resources/VariableResource.py +46 -26
- mage_ai/api/resources/VersionControlProjectResource.py +9 -2
- mage_ai/api/resources/WidgetResource.py +1 -1
- mage_ai/api/resources/WorkspaceResource.py +6 -5
- mage_ai/api/views.py +47 -40
- mage_ai/authentication/permissions/seed.py +16 -2
- mage_ai/authentication/providers/oidc.py +21 -1
- mage_ai/autocomplete/utils.py +13 -9
- mage_ai/cache/base.py +1 -1
- mage_ai/cache/block.py +18 -12
- mage_ai/cache/block_action_object/__init__.py +33 -5
- mage_ai/cache/file.py +22 -19
- mage_ai/cache/pipeline.py +18 -12
- mage_ai/cli/main.py +1 -0
- mage_ai/cluster_manager/aws/emr_cluster_manager.py +9 -5
- mage_ai/cluster_manager/config.py +2 -2
- mage_ai/cluster_manager/kubernetes/workload_manager.py +52 -1
- mage_ai/cluster_manager/manage.py +1 -1
- mage_ai/cluster_manager/workspace/base.py +7 -1
- mage_ai/cluster_manager/workspace/kubernetes.py +22 -1
- mage_ai/command_center/applications/factory.py +10 -7
- mage_ai/command_center/applications/utils.py +2 -2
- mage_ai/command_center/files/factory.py +17 -15
- mage_ai/command_center/presenters/text.py +1 -1
- mage_ai/command_center/utils.py +25 -13
- mage_ai/data/__init__.py +0 -0
- mage_ai/data/constants.py +45 -0
- mage_ai/data/models/__init__.py +0 -0
- mage_ai/data/models/base.py +119 -0
- mage_ai/data/models/constants.py +1 -0
- mage_ai/data/models/generator.py +115 -0
- mage_ai/data/models/manager.py +168 -0
- mage_ai/data/models/pyarrow/__init__.py +0 -0
- mage_ai/data/models/pyarrow/record_batch.py +55 -0
- mage_ai/data/models/pyarrow/shared.py +21 -0
- mage_ai/data/models/pyarrow/table.py +8 -0
- mage_ai/data/models/reader.py +103 -0
- mage_ai/data/models/utils.py +59 -0
- mage_ai/data/models/writer.py +91 -0
- mage_ai/data/tabular/__init__.py +0 -0
- mage_ai/data/tabular/constants.py +23 -0
- mage_ai/data/tabular/mocks.py +19 -0
- mage_ai/data/tabular/models.py +126 -0
- mage_ai/data/tabular/reader.py +602 -0
- mage_ai/data/tabular/utils.py +102 -0
- mage_ai/data/tabular/writer.py +266 -0
- mage_ai/data/variables/__init__.py +0 -0
- mage_ai/data/variables/wrapper.py +54 -0
- mage_ai/data_cleaner/analysis/charts.py +61 -39
- mage_ai/data_cleaner/column_types/column_type_detector.py +53 -31
- mage_ai/data_cleaner/estimators/encoders.py +5 -2
- mage_ai/data_integrations/utils/scheduler.py +16 -11
- mage_ai/data_preparation/decorators.py +1 -0
- mage_ai/data_preparation/executors/block_executor.py +237 -155
- mage_ai/data_preparation/executors/k8s_block_executor.py +30 -7
- mage_ai/data_preparation/executors/k8s_pipeline_executor.py +30 -7
- mage_ai/data_preparation/executors/streaming_pipeline_executor.py +2 -2
- mage_ai/data_preparation/git/__init__.py +77 -29
- mage_ai/data_preparation/git/api.py +69 -8
- mage_ai/data_preparation/git/utils.py +64 -34
- mage_ai/data_preparation/logging/logger_manager.py +4 -3
- mage_ai/data_preparation/models/block/__init__.py +1562 -879
- mage_ai/data_preparation/models/block/data_integration/mixins.py +4 -3
- mage_ai/data_preparation/models/block/dynamic/__init__.py +17 -6
- mage_ai/data_preparation/models/block/dynamic/child.py +41 -102
- mage_ai/data_preparation/models/block/dynamic/constants.py +1 -0
- mage_ai/data_preparation/models/block/dynamic/counter.py +296 -0
- mage_ai/data_preparation/models/block/dynamic/data.py +16 -0
- mage_ai/data_preparation/models/block/dynamic/factory.py +163 -0
- mage_ai/data_preparation/models/block/dynamic/models.py +19 -0
- mage_ai/data_preparation/models/block/dynamic/shared.py +92 -0
- mage_ai/data_preparation/models/block/dynamic/utils.py +295 -167
- mage_ai/data_preparation/models/block/dynamic/variables.py +384 -144
- mage_ai/data_preparation/models/block/dynamic/wrappers.py +77 -0
- mage_ai/data_preparation/models/block/extension/utils.py +10 -1
- mage_ai/data_preparation/models/block/global_data_product/__init__.py +35 -3
- mage_ai/data_preparation/models/block/integration/__init__.py +6 -2
- mage_ai/data_preparation/models/block/outputs.py +722 -0
- mage_ai/data_preparation/models/block/platform/mixins.py +7 -8
- mage_ai/data_preparation/models/block/r/__init__.py +56 -38
- mage_ai/data_preparation/models/block/remote/__init__.py +0 -0
- mage_ai/data_preparation/models/block/remote/models.py +58 -0
- mage_ai/data_preparation/models/block/settings/__init__.py +0 -0
- mage_ai/data_preparation/models/block/settings/dynamic/__init__.py +0 -0
- mage_ai/data_preparation/models/block/settings/dynamic/constants.py +7 -0
- mage_ai/data_preparation/models/block/settings/dynamic/mixins.py +118 -0
- mage_ai/data_preparation/models/block/settings/dynamic/models.py +31 -0
- mage_ai/data_preparation/models/block/settings/global_data_products/__init__.py +0 -0
- mage_ai/data_preparation/models/block/settings/global_data_products/mixins.py +20 -0
- mage_ai/data_preparation/models/block/settings/global_data_products/models.py +46 -0
- mage_ai/data_preparation/models/block/settings/variables/__init__.py +0 -0
- mage_ai/data_preparation/models/block/settings/variables/mixins.py +74 -0
- mage_ai/data_preparation/models/block/settings/variables/models.py +49 -0
- mage_ai/data_preparation/models/block/spark/mixins.py +2 -1
- mage_ai/data_preparation/models/block/sql/__init__.py +30 -5
- mage_ai/data_preparation/models/block/sql/utils/shared.py +21 -3
- mage_ai/data_preparation/models/block/utils.py +164 -69
- mage_ai/data_preparation/models/constants.py +21 -14
- mage_ai/data_preparation/models/custom_templates/custom_block_template.py +18 -13
- mage_ai/data_preparation/models/custom_templates/custom_pipeline_template.py +33 -16
- mage_ai/data_preparation/models/custom_templates/utils.py +1 -1
- mage_ai/data_preparation/models/file.py +41 -28
- mage_ai/data_preparation/models/global_data_product/__init__.py +100 -58
- mage_ai/data_preparation/models/global_hooks/models.py +1 -0
- mage_ai/data_preparation/models/interfaces.py +29 -0
- mage_ai/data_preparation/models/pipeline.py +374 -185
- mage_ai/data_preparation/models/pipelines/integration_pipeline.py +1 -2
- mage_ai/data_preparation/models/pipelines/seed.py +1 -1
- mage_ai/data_preparation/models/project/__init__.py +66 -18
- mage_ai/data_preparation/models/project/constants.py +2 -0
- mage_ai/data_preparation/models/triggers/__init__.py +124 -26
- mage_ai/data_preparation/models/utils.py +467 -17
- mage_ai/data_preparation/models/variable.py +1028 -137
- mage_ai/data_preparation/models/variables/__init__.py +0 -0
- mage_ai/data_preparation/models/variables/cache.py +149 -0
- mage_ai/data_preparation/models/variables/constants.py +72 -0
- mage_ai/data_preparation/models/variables/summarizer.py +336 -0
- mage_ai/data_preparation/models/variables/utils.py +77 -0
- mage_ai/data_preparation/models/widget/__init__.py +63 -41
- mage_ai/data_preparation/models/widget/charts.py +40 -27
- mage_ai/data_preparation/models/widget/constants.py +2 -0
- mage_ai/data_preparation/models/widget/utils.py +3 -3
- mage_ai/data_preparation/preferences.py +3 -3
- mage_ai/data_preparation/repo_manager.py +55 -21
- mage_ai/data_preparation/storage/base_storage.py +2 -2
- mage_ai/data_preparation/storage/gcs_storage.py +7 -4
- mage_ai/data_preparation/storage/local_storage.py +18 -9
- mage_ai/data_preparation/storage/s3_storage.py +5 -2
- mage_ai/data_preparation/templates/data_exporters/streaming/oracledb.yaml +8 -0
- mage_ai/data_preparation/variable_manager.py +281 -76
- mage_ai/io/base.py +3 -2
- mage_ai/io/bigquery.py +1 -0
- mage_ai/io/redshift.py +7 -5
- mage_ai/kernels/__init__.py +0 -0
- mage_ai/kernels/models.py +188 -0
- mage_ai/kernels/utils.py +169 -0
- mage_ai/orchestration/concurrency.py +6 -2
- mage_ai/orchestration/db/__init__.py +1 -0
- mage_ai/orchestration/db/migrations/versions/0227396a216c_add_userproject_table.py +38 -0
- mage_ai/orchestration/db/migrations/versions/42a14d6143f1_update_token_column_type.py +54 -0
- mage_ai/orchestration/db/models/dynamic/__init__.py +0 -0
- mage_ai/orchestration/db/models/dynamic/controller.py +67 -0
- mage_ai/orchestration/db/models/oauth.py +12 -18
- mage_ai/orchestration/db/models/projects.py +10 -0
- mage_ai/orchestration/db/models/schedules.py +225 -187
- mage_ai/orchestration/db/models/schedules_project_platform.py +18 -12
- mage_ai/orchestration/db/models/utils.py +46 -5
- mage_ai/orchestration/metrics/pipeline_run.py +8 -9
- mage_ai/orchestration/notification/sender.py +38 -15
- mage_ai/orchestration/pipeline_scheduler_original.py +64 -33
- mage_ai/orchestration/pipeline_scheduler_project_platform.py +1 -1
- mage_ai/orchestration/run_status_checker.py +11 -4
- mage_ai/orchestration/triggers/api.py +41 -2
- mage_ai/orchestration/triggers/global_data_product.py +9 -4
- mage_ai/orchestration/triggers/utils.py +10 -1
- mage_ai/orchestration/utils/resources.py +3 -0
- mage_ai/presenters/charts/data_sources/base.py +4 -2
- mage_ai/presenters/charts/data_sources/block.py +15 -9
- mage_ai/presenters/charts/data_sources/chart_code.py +8 -5
- mage_ai/presenters/charts/data_sources/constants.py +1 -0
- mage_ai/presenters/charts/data_sources/system_metrics.py +22 -0
- mage_ai/presenters/interactions/models.py +11 -7
- mage_ai/presenters/pages/loaders/pipelines.py +5 -3
- mage_ai/presenters/pages/models/page_components/pipeline_schedules.py +3 -1
- mage_ai/presenters/utils.py +2 -0
- mage_ai/server/api/blocks.py +2 -1
- mage_ai/server/api/downloads.py +9 -2
- mage_ai/server/api/runs.py +151 -0
- mage_ai/server/api/triggers.py +3 -1
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +8 -8
- mage_ai/server/frontend_dist/_next/static/UZLabyPgcxtZvp0O0EUUS/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1376-22de38b4ad008d8a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1557-25a7d985d5564fd3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1668-30b4619b9534519b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1799-c42db95a015689ee.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/2996-2108b53b9d371d8d.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{3548-fa0792ddb88f4646.js → 3548-9d26185b3fb663b1.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{3763-61b542dafdbf5754.js → 3763-40780c6d1e4b261d.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3782-129dd2a2448a2e36.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3958-bcdfa414ccfa1eb2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/4168-97fd1578d1a38315.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/4982-fa5a238b139fbdd2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/5699-176f445e1313f001.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7162-7dd03f0f605de721.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7779-68d2b72a90c5f925.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7966-5446a8e43711e2f9.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/8023-6c2f172f48dcb99b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/8095-c351b8a735d73e0c.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9624-8b8e100079ab69e1.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{main-77fe248a6fbd12d8.js → main-b99d4e30a88d9dc7.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-9fe2d9d07c94e968.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{block-layout-14f952f66964022f.js → block-layout-7f4b735c67115df5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-e7d48e6b0c3068ac.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-b943f31f050fc3a4.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-4bfc84ff07d7656f.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{overview-597b74828bf105db.js → overview-9f1ac4ec003884f3.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-3edc6270c5b0e962.js → frontend_dist/_next/static/chunks/pages/pipeline-runs-6d183f91a2ff6668.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-7e737f6fc7e83e9b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-38e1fbcfbfc1014e.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-d94488e3f2eeef36.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-cc641a7fa8473796.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/{block-runs-a5c0362763a21fa8.js → block-runs-284309877f3c5a5a.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-26250e5335194ade.js +1 -0
- 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
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-4ebfc8e400315dda.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-e5e0150a256aadb3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-eb11c5390c982b49.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-1bdfda8edc9cf4a8.js → triggers-4612d15a65c35912.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/{profile-3f0df3decc856ee9.js → profile-3ae43c932537b254.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-b603d7fe4b175256.js +1 -0
- 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
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-47b64ced27c24985.js → [...slug]-5c360f72e4498855.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{permissions-e5a4d3d815cec25d.js → permissions-fb29fa6c2bd90bb0.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-3b76fa959ffa09d3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-379e1ee292504842.js → [...slug]-3b787b42f1093b1f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles-0b83fbdd39e85f5b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-a1e6950974d643a8.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/{[...slug]-2af9afbe727d88aa.js → [...slug]-0aa019d87db8b0b8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{users-a4db8710f703c729.js → users-88c694d19207f2ec.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{triggers-9cba3211434a8966.js → triggers-a599c6ac89be8c8d.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-31d0d50f7f30462b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{webpack-d079359c241db804.js → webpack-ac7fdc472bedf682.js} +1 -1
- mage_ai/server/frontend_dist/block-layout.html +3 -3
- mage_ai/server/frontend_dist/compute.html +6 -6
- mage_ai/server/frontend_dist/files.html +6 -6
- mage_ai/server/frontend_dist/global-data-products/[...slug].html +6 -6
- mage_ai/server/frontend_dist/global-data-products.html +6 -6
- mage_ai/server/frontend_dist/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist/global-hooks.html +6 -6
- mage_ai/server/frontend_dist/index.html +3 -3
- mage_ai/server/frontend_dist/manage/files.html +6 -6
- mage_ai/server/frontend_dist/manage/settings.html +6 -6
- mage_ai/server/frontend_dist/manage/users/[user].html +6 -6
- mage_ai/server/frontend_dist/manage/users/new.html +6 -6
- mage_ai/server/frontend_dist/manage/users.html +6 -6
- mage_ai/server/frontend_dist/manage.html +6 -6
- mage_ai/server/frontend_dist/oauth.html +5 -5
- mage_ai/server/frontend_dist/overview.html +6 -6
- mage_ai/server/frontend_dist/pipeline-runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +3 -3
- mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline].html +3 -3
- mage_ai/server/frontend_dist/pipelines.html +6 -6
- mage_ai/server/frontend_dist/platform/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist/platform/global-hooks.html +6 -6
- mage_ai/server/frontend_dist/settings/account/profile.html +6 -6
- mage_ai/server/frontend_dist/settings/platform/preferences.html +6 -6
- mage_ai/server/frontend_dist/settings/platform/settings.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/permissions.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/roles.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/users.html +6 -6
- mage_ai/server/frontend_dist/settings.html +3 -3
- mage_ai/server/frontend_dist/sign-in.html +15 -15
- mage_ai/server/frontend_dist/templates/[...slug].html +6 -6
- mage_ai/server/frontend_dist/templates.html +6 -6
- mage_ai/server/frontend_dist/terminal.html +6 -6
- mage_ai/server/frontend_dist/test.html +3 -3
- mage_ai/server/frontend_dist/triggers.html +6 -6
- mage_ai/server/frontend_dist/version-control.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/404.html +8 -8
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1376-22de38b4ad008d8a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1557-25a7d985d5564fd3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1668-30b4619b9534519b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1799-c42db95a015689ee.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2996-2108b53b9d371d8d.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{3548-fa0792ddb88f4646.js → 3548-9d26185b3fb663b1.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{3763-61b542dafdbf5754.js → 3763-40780c6d1e4b261d.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-129dd2a2448a2e36.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3958-bcdfa414ccfa1eb2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4168-97fd1578d1a38315.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4982-fa5a238b139fbdd2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5699-176f445e1313f001.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7162-7dd03f0f605de721.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7779-68d2b72a90c5f925.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7966-5446a8e43711e2f9.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8023-6c2f172f48dcb99b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8095-c351b8a735d73e0c.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-8b8e100079ab69e1.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{main-70b78159c2bb3fe1.js → main-384298e9133cec76.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-13a578bce3b7f30c.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{block-layout-14f952f66964022f.js → block-layout-7f4b735c67115df5.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-e7d48e6b0c3068ac.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-b943f31f050fc3a4.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-4bfc84ff07d7656f.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{overview-597b74828bf105db.js → overview-9f1ac4ec003884f3.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipeline-runs-3edc6270c5b0e962.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-6d183f91a2ff6668.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-7e737f6fc7e83e9b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-38e1fbcfbfc1014e.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-d94488e3f2eeef36.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-cc641a7fa8473796.js +1 -0
- 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
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-26250e5335194ade.js +1 -0
- 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
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-4ebfc8e400315dda.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-e5e0150a256aadb3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-eb11c5390c982b49.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-1bdfda8edc9cf4a8.js → triggers-4612d15a65c35912.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/{profile-3f0df3decc856ee9.js → profile-3ae43c932537b254.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-b603d7fe4b175256.js +1 -0
- 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
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-47b64ced27c24985.js → [...slug]-5c360f72e4498855.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{permissions-e5a4d3d815cec25d.js → permissions-fb29fa6c2bd90bb0.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-3b76fa959ffa09d3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-379e1ee292504842.js → [...slug]-3b787b42f1093b1f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles-0b83fbdd39e85f5b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-a1e6950974d643a8.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/{[...slug]-2af9afbe727d88aa.js → [...slug]-0aa019d87db8b0b8.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{users-a4db8710f703c729.js → users-88c694d19207f2ec.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{triggers-9cba3211434a8966.js → triggers-a599c6ac89be8c8d.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-31d0d50f7f30462b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-68c003fb6a175cd7.js → webpack-481689d9989710cd.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/kcptwoOU-JJJg6Vwpkfmx/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/block-layout.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/compute.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/files.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-data-products.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-hooks.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/index.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/manage/files.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/oauth.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/overview.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +3 -3
- mage_ai/server/frontend_dist_base_path_template/pipelines.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/sign-in.html +15 -15
- mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/templates.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/terminal.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/test.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/triggers.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/version-control.html +6 -6
- mage_ai/server/kernel_output_parser.py +4 -1
- mage_ai/server/scheduler_manager.py +12 -1
- mage_ai/server/server.py +69 -42
- mage_ai/server/utils/custom_output.py +284 -0
- mage_ai/server/utils/execute_custom_code.py +245 -0
- mage_ai/server/utils/output_display.py +123 -289
- mage_ai/server/websocket_server.py +116 -69
- mage_ai/services/aws/ecs/ecs.py +1 -0
- mage_ai/services/k8s/config.py +27 -4
- mage_ai/services/k8s/job_manager.py +6 -1
- mage_ai/services/k8s/utils.py +97 -0
- mage_ai/services/ssh/aws/emr/utils.py +8 -8
- mage_ai/settings/keys/auth.py +1 -0
- mage_ai/settings/platform/__init__.py +159 -38
- mage_ai/settings/platform/constants.py +5 -0
- mage_ai/settings/platform/utils.py +53 -10
- mage_ai/settings/repo.py +26 -12
- mage_ai/settings/server.py +128 -37
- mage_ai/shared/array.py +24 -1
- mage_ai/shared/complex.py +45 -0
- mage_ai/shared/config.py +2 -1
- mage_ai/shared/custom_logger.py +11 -0
- mage_ai/shared/dates.py +10 -6
- mage_ai/shared/files.py +63 -8
- mage_ai/shared/hash.py +33 -9
- mage_ai/shared/io.py +9 -5
- mage_ai/shared/models.py +82 -24
- mage_ai/shared/outputs.py +87 -0
- mage_ai/shared/parsers.py +144 -13
- mage_ai/shared/path_fixer.py +11 -7
- mage_ai/shared/singletons/__init__.py +0 -0
- mage_ai/shared/singletons/base.py +47 -0
- mage_ai/shared/singletons/memory.py +38 -0
- mage_ai/shared/strings.py +34 -1
- mage_ai/shared/yaml.py +24 -0
- mage_ai/streaming/sinks/oracledb.py +57 -0
- mage_ai/streaming/sinks/sink_factory.py +4 -0
- mage_ai/system/__init__.py +0 -0
- mage_ai/system/constants.py +14 -0
- mage_ai/system/memory/__init__.py +0 -0
- mage_ai/system/memory/constants.py +1 -0
- mage_ai/system/memory/manager.py +174 -0
- mage_ai/system/memory/presenters.py +158 -0
- mage_ai/system/memory/process.py +216 -0
- mage_ai/system/memory/samples.py +13 -0
- mage_ai/system/memory/utils.py +656 -0
- mage_ai/system/memory/wrappers.py +177 -0
- mage_ai/system/models.py +58 -0
- mage_ai/system/storage/__init__.py +0 -0
- mage_ai/system/storage/utils.py +29 -0
- mage_ai/tests/api/endpoints/mixins.py +2 -2
- mage_ai/tests/api/endpoints/test_blocks.py +2 -1
- mage_ai/tests/api/endpoints/test_custom_designs.py +4 -4
- mage_ai/tests/api/endpoints/test_pipeline_runs.py +2 -2
- mage_ai/tests/api/endpoints/test_projects.py +2 -1
- mage_ai/tests/api/operations/base/mixins.py +1 -1
- mage_ai/tests/api/operations/base/test_base.py +27 -27
- mage_ai/tests/api/operations/base/test_base_with_user_authentication.py +27 -27
- mage_ai/tests/api/operations/base/test_base_with_user_permissions.py +23 -23
- mage_ai/tests/api/operations/test_syncs.py +6 -4
- mage_ai/tests/api/resources/test_pipeline_resource.py +11 -4
- mage_ai/tests/authentication/oauth/test_utils.py +1 -1
- mage_ai/tests/authentication/providers/test_oidc.py +59 -0
- mage_ai/tests/base_test.py +2 -2
- mage_ai/tests/data/__init__.py +0 -0
- mage_ai/tests/data/models/__init__.py +0 -0
- mage_ai/tests/data_preparation/executors/test_block_executor.py +23 -16
- mage_ai/tests/data_preparation/git/test_git.py +4 -1
- mage_ai/tests/data_preparation/models/block/dynamic/test_combos.py +305 -0
- mage_ai/tests/data_preparation/models/block/dynamic/test_counter.py +212 -0
- mage_ai/tests/data_preparation/models/block/dynamic/test_factory.py +360 -0
- mage_ai/tests/data_preparation/models/block/dynamic/test_variables.py +332 -0
- mage_ai/tests/data_preparation/models/block/hook/test_hook_block.py +2 -2
- mage_ai/tests/data_preparation/models/block/platform/test_mixins.py +1 -1
- mage_ai/tests/data_preparation/models/block/sql/utils/test_shared.py +26 -1
- mage_ai/tests/data_preparation/models/block/test_global_data_product.py +5 -2
- mage_ai/tests/data_preparation/models/custom_templates/test_utils.py +5 -4
- mage_ai/tests/data_preparation/models/global_hooks/test_hook.py +3 -0
- mage_ai/tests/data_preparation/models/global_hooks/test_predicates.py +9 -3
- mage_ai/tests/data_preparation/models/test_block.py +115 -120
- mage_ai/tests/data_preparation/models/test_blocks_helper.py +114 -0
- mage_ai/tests/data_preparation/models/test_global_data_product.py +41 -24
- mage_ai/tests/data_preparation/models/test_pipeline.py +9 -6
- mage_ai/tests/data_preparation/models/test_project.py +4 -1
- mage_ai/tests/data_preparation/models/test_utils.py +80 -0
- mage_ai/tests/data_preparation/models/test_variable.py +242 -69
- mage_ai/tests/data_preparation/models/variables/__init__.py +0 -0
- mage_ai/tests/data_preparation/models/variables/test_summarizer.py +481 -0
- mage_ai/tests/data_preparation/storage/shared/__init__.py +0 -0
- mage_ai/tests/data_preparation/test_repo_manager.py +6 -7
- mage_ai/tests/data_preparation/test_variable_manager.py +57 -48
- mage_ai/tests/factory.py +64 -43
- mage_ai/tests/orchestration/db/models/test_schedules.py +3 -3
- mage_ai/tests/orchestration/db/models/test_schedules_dynamic_blocks.py +279 -0
- mage_ai/tests/orchestration/test_pipeline_scheduler.py +1 -0
- mage_ai/tests/orchestration/triggers/test_global_data_product.py +141 -138
- mage_ai/tests/orchestration/triggers/test_utils.py +3 -2
- mage_ai/tests/server/test_server.py +19 -0
- mage_ai/tests/services/k8s/test_job_manager.py +27 -6
- mage_ai/tests/streaming/sinks/test_oracledb.py +38 -0
- mage_ai/tests/test_shared.py +61 -0
- mage_ai/usage_statistics/logger.py +7 -2
- mage_ai/utils/code.py +33 -19
- mage_ai/version_control/branch/utils.py +2 -1
- mage_ai/version_control/models.py +3 -2
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/METADATA +6 -3
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/RECORD +555 -454
- mage_ai/data_preparation/models/global_data_product/constants.py +0 -6
- mage_ai/server/frontend_dist/_next/static/_krrrgup_C-dPOpX36S8I/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1557-df144fbd8b2208c3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2631-b9f9bea3f1cf906d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3782-ef4cd4f0b52072d0.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/4783-422429203610c318.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5699-6d708c6b2153ea08.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/635-0d6b7c8804bcd2dc.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7022-0d52dd8868621fb0.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7361-8a23dd8360593e7a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7966-f07b2913f7326b50.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8095-bdce03896ef9639a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8146-6bed4e7401e067e6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9265-d2a1aaec75ec69b8.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9440-4069842b90d4b801.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9624-59b2f803f9c88cd6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9832-67896490f6e8a014.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-d9c89527266296f7.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-591abd392dc50ed4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-78e8e88f2a757a18.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-852d403c7bda21b3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a8b61d8d239fd16f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-95ffcd3e2b27e567.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-e1dd1ed71d26c10d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-1ed9045b2f1dfd65.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1417ad1c821d720a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-59aca25a5b1d3998.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-f028ef3880ed856c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-503049734a8b082f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-5b26eeda8aed8a7b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles-36fa165a48af586b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-8b793b3b696a2cd3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/KLL5mirre9d7_ZeEpaw3s/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1557-df144fbd8b2208c3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2631-b9f9bea3f1cf906d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-ef4cd4f0b52072d0.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/4783-422429203610c318.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5699-6d708c6b2153ea08.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/635-0d6b7c8804bcd2dc.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7022-0d52dd8868621fb0.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7361-8a23dd8360593e7a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7966-f07b2913f7326b50.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8095-bdce03896ef9639a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8146-6bed4e7401e067e6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9265-d2a1aaec75ec69b8.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9440-4069842b90d4b801.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-59b2f803f9c88cd6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9832-67896490f6e8a014.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-d9c89527266296f7.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-591abd392dc50ed4.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-78e8e88f2a757a18.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-852d403c7bda21b3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a8b61d8d239fd16f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/dashboard-95ffcd3e2b27e567.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-e1dd1ed71d26c10d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-1ed9045b2f1dfd65.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1417ad1c821d720a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-59aca25a5b1d3998.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-f028ef3880ed856c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-503049734a8b082f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-5b26eeda8aed8a7b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles-36fa165a48af586b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-8b793b3b696a2cd3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +0 -1
- mage_ai/shared/memory.py +0 -90
- mage_ai/tests/data_preparation/models/block/dynamic/test_dynamic_helpers.py +0 -48
- /mage_ai/{tests/data_preparation/shared → ai/utils}/__init__.py +0 -0
- /mage_ai/server/frontend_dist/_next/static/{_krrrgup_C-dPOpX36S8I → UZLabyPgcxtZvp0O0EUUS}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{KLL5mirre9d7_ZeEpaw3s → kcptwoOU-JJJg6Vwpkfmx}/_ssgManifest.js +0 -0
- /mage_ai/tests/data_preparation/{shared → storage/shared}/test_secrets.py +0 -0
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/WHEEL +0 -0
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.69.dist-info → mage_ai-0.9.71.dist-info}/top_level.txt +0 -0
|
@@ -7,16 +7,17 @@ import tempfile
|
|
|
7
7
|
import zipfile
|
|
8
8
|
from datetime import datetime, timezone
|
|
9
9
|
from io import BytesIO
|
|
10
|
-
from typing import Any, Callable, Dict, List, Tuple, Union
|
|
10
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
11
11
|
|
|
12
12
|
import aiofiles
|
|
13
13
|
import pytz
|
|
14
|
-
import yaml
|
|
15
14
|
from jinja2 import Template
|
|
16
15
|
|
|
17
16
|
from mage_ai.authentication.permissions.constants import EntityName
|
|
18
17
|
from mage_ai.cache.block import BlockCache
|
|
19
18
|
from mage_ai.cache.pipeline import PipelineCache
|
|
19
|
+
from mage_ai.data.constants import InputDataType
|
|
20
|
+
from mage_ai.data.tabular.models import BatchSettings
|
|
20
21
|
from mage_ai.data_preparation.models.block import Block, run_blocks, run_blocks_sync
|
|
21
22
|
from mage_ai.data_preparation.models.block.block_factory import BlockFactory
|
|
22
23
|
from mage_ai.data_preparation.models.block.data_integration.utils import (
|
|
@@ -27,6 +28,10 @@ from mage_ai.data_preparation.models.block.dynamic.utils import (
|
|
|
27
28
|
is_dynamic_block_child,
|
|
28
29
|
)
|
|
29
30
|
from mage_ai.data_preparation.models.block.errors import HasDownstreamDependencies
|
|
31
|
+
from mage_ai.data_preparation.models.block.extension.utils import compare_extension
|
|
32
|
+
from mage_ai.data_preparation.models.block.settings.variables.models import (
|
|
33
|
+
ChunkKeyTypeUnion,
|
|
34
|
+
)
|
|
30
35
|
from mage_ai.data_preparation.models.constants import (
|
|
31
36
|
DATA_INTEGRATION_CATALOG_FILE,
|
|
32
37
|
PIPELINE_CONFIG_FILE,
|
|
@@ -47,7 +52,10 @@ from mage_ai.data_preparation.models.file import File
|
|
|
47
52
|
from mage_ai.data_preparation.models.pipelines.models import PipelineSettings
|
|
48
53
|
from mage_ai.data_preparation.models.project import Project
|
|
49
54
|
from mage_ai.data_preparation.models.project.constants import FeatureUUID
|
|
50
|
-
from mage_ai.data_preparation.models.utils import
|
|
55
|
+
from mage_ai.data_preparation.models.utils import (
|
|
56
|
+
is_yaml_serializable,
|
|
57
|
+
warn_for_repo_path,
|
|
58
|
+
)
|
|
51
59
|
from mage_ai.data_preparation.models.variable import Variable
|
|
52
60
|
from mage_ai.data_preparation.repo_manager import (
|
|
53
61
|
RepoConfig,
|
|
@@ -73,6 +81,7 @@ from mage_ai.shared.io import safe_write, safe_write_async
|
|
|
73
81
|
from mage_ai.shared.path_fixer import remove_base_repo_path
|
|
74
82
|
from mage_ai.shared.strings import format_enum
|
|
75
83
|
from mage_ai.shared.utils import clean_name
|
|
84
|
+
from mage_ai.shared.yaml import load_yaml, yaml
|
|
76
85
|
|
|
77
86
|
CYCLE_DETECTION_ERR_MESSAGE = 'A cycle was detected in this pipeline'
|
|
78
87
|
|
|
@@ -81,10 +90,11 @@ class Pipeline:
|
|
|
81
90
|
def __init__(
|
|
82
91
|
self,
|
|
83
92
|
uuid,
|
|
84
|
-
repo_path=None,
|
|
93
|
+
repo_path: str = None,
|
|
85
94
|
config=None,
|
|
86
95
|
repo_config=None,
|
|
87
96
|
catalog=None,
|
|
97
|
+
context_data: Dict = None,
|
|
88
98
|
use_repo_path: bool = False,
|
|
89
99
|
description: str = None,
|
|
90
100
|
tags: List[str] = None,
|
|
@@ -99,9 +109,18 @@ class Pipeline:
|
|
|
99
109
|
self.description = description
|
|
100
110
|
self.executor_config = dict()
|
|
101
111
|
self.executor_type = None
|
|
112
|
+
self._rendered_executor_type = None # Render template variables
|
|
102
113
|
self.extensions = {}
|
|
103
114
|
self.name = None
|
|
104
115
|
self.notification_config = dict()
|
|
116
|
+
|
|
117
|
+
# For multi project
|
|
118
|
+
warn_for_repo_path(repo_path)
|
|
119
|
+
self.context_data = context_data
|
|
120
|
+
if self.context_data is None:
|
|
121
|
+
self.context_data = dict()
|
|
122
|
+
self._project = None
|
|
123
|
+
|
|
105
124
|
self.repo_path = repo_path or get_repo_path()
|
|
106
125
|
self.retry_config = {}
|
|
107
126
|
self.run_pipeline_in_one_process = False
|
|
@@ -129,17 +148,28 @@ class Pipeline:
|
|
|
129
148
|
# Used for showing the operation history. For example: recently viewed pipelines.
|
|
130
149
|
self.history = []
|
|
131
150
|
|
|
151
|
+
# Path of the pipeline metadata.yaml file
|
|
152
|
+
self._config_path = None
|
|
132
153
|
if config is None:
|
|
133
154
|
self.load_config_from_yaml()
|
|
134
155
|
else:
|
|
135
156
|
self.load_config(config, catalog=catalog)
|
|
136
157
|
|
|
137
|
-
|
|
138
|
-
|
|
158
|
+
def build_config_path(
|
|
159
|
+
self,
|
|
160
|
+
uuid: str,
|
|
161
|
+
repo_path: str,
|
|
162
|
+
context_data: Dict = None,
|
|
163
|
+
use_repo_path: bool = False,
|
|
164
|
+
) -> str:
|
|
139
165
|
if project_platform_activated() and not use_repo_path:
|
|
140
166
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
141
167
|
|
|
142
|
-
config_path, _repo_path = get_pipeline_config_path(
|
|
168
|
+
config_path, _repo_path = get_pipeline_config_path(
|
|
169
|
+
uuid,
|
|
170
|
+
context_data=context_data,
|
|
171
|
+
repo_path=repo_path,
|
|
172
|
+
)
|
|
143
173
|
if config_path:
|
|
144
174
|
return config_path
|
|
145
175
|
|
|
@@ -152,14 +182,25 @@ class Pipeline:
|
|
|
152
182
|
|
|
153
183
|
@property
|
|
154
184
|
def config_path(self):
|
|
155
|
-
|
|
185
|
+
if not self._config_path:
|
|
186
|
+
self._config_path = self.build_config_path(
|
|
187
|
+
self.uuid,
|
|
188
|
+
self.repo_path,
|
|
189
|
+
context_data=self.context_data,
|
|
190
|
+
use_repo_path=self.use_repo_path,
|
|
191
|
+
)
|
|
192
|
+
return self._config_path
|
|
156
193
|
|
|
157
194
|
@property
|
|
158
195
|
def catalog_config_path(self):
|
|
159
196
|
if project_platform_activated() and not self.use_repo_path:
|
|
160
197
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
161
198
|
|
|
162
|
-
config_path, _repo_path = get_pipeline_config_path(
|
|
199
|
+
config_path, _repo_path = get_pipeline_config_path(
|
|
200
|
+
self.uuid,
|
|
201
|
+
context_data=self.context_data,
|
|
202
|
+
repo_path=self.repo_path,
|
|
203
|
+
)
|
|
163
204
|
if config_path:
|
|
164
205
|
return os.path.join(os.path.dirname(config_path), DATA_INTEGRATION_CATALOG_FILE)
|
|
165
206
|
|
|
@@ -197,6 +238,16 @@ class Pipeline:
|
|
|
197
238
|
self.uuid,
|
|
198
239
|
)
|
|
199
240
|
|
|
241
|
+
@property
|
|
242
|
+
def project(self):
|
|
243
|
+
if self._project is not None:
|
|
244
|
+
return self._project
|
|
245
|
+
|
|
246
|
+
from mage_ai.data_preparation.models.project import Project
|
|
247
|
+
|
|
248
|
+
self._project = Project(context_data=self.context_data, repo_config=self.repo_config)
|
|
249
|
+
return self._project
|
|
250
|
+
|
|
200
251
|
@property
|
|
201
252
|
def remote_variables_dir(self):
|
|
202
253
|
remote_variables_dir = self.repo_config.remote_variables_dir
|
|
@@ -215,18 +266,20 @@ class Pipeline:
|
|
|
215
266
|
|
|
216
267
|
@property
|
|
217
268
|
def all_block_configs(self) -> List[Dict]:
|
|
218
|
-
return
|
|
219
|
-
self.
|
|
220
|
-
self.
|
|
221
|
-
self.
|
|
269
|
+
return (
|
|
270
|
+
self.block_configs
|
|
271
|
+
+ self.conditional_configs
|
|
272
|
+
+ self.callback_configs
|
|
273
|
+
+ self.widget_configs
|
|
274
|
+
)
|
|
222
275
|
|
|
223
276
|
@classmethod
|
|
224
277
|
def create(
|
|
225
278
|
self,
|
|
226
279
|
name: str,
|
|
280
|
+
repo_path: str = None,
|
|
227
281
|
description: str = None,
|
|
228
282
|
pipeline_type: PipelineType = PipelineType.PYTHON,
|
|
229
|
-
repo_path: str = None,
|
|
230
283
|
tags: List[str] = None,
|
|
231
284
|
):
|
|
232
285
|
"""
|
|
@@ -234,6 +287,8 @@ class Pipeline:
|
|
|
234
287
|
2. Create a new yaml file to store pipeline config
|
|
235
288
|
3. Create other files: requirements.txt, __init__.py
|
|
236
289
|
"""
|
|
290
|
+
warn_for_repo_path(repo_path)
|
|
291
|
+
|
|
237
292
|
uuid = clean_name(name)
|
|
238
293
|
pipeline_path = os.path.join(repo_path, PIPELINES_FOLDER, uuid)
|
|
239
294
|
if os.path.exists(pipeline_path):
|
|
@@ -242,14 +297,17 @@ class Pipeline:
|
|
|
242
297
|
copy_template_directory('pipeline', pipeline_path)
|
|
243
298
|
# Update metadata.yaml with pipeline config
|
|
244
299
|
with open(os.path.join(pipeline_path, PIPELINE_CONFIG_FILE), 'w') as fp:
|
|
245
|
-
yaml.dump(
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
300
|
+
yaml.dump(
|
|
301
|
+
dict(
|
|
302
|
+
created_at=str(datetime.now(tz=pytz.UTC)),
|
|
303
|
+
description=description,
|
|
304
|
+
name=name,
|
|
305
|
+
tags=tags or [],
|
|
306
|
+
uuid=uuid,
|
|
307
|
+
type=format_enum(pipeline_type or PipelineType.PYTHON),
|
|
308
|
+
),
|
|
309
|
+
fp,
|
|
310
|
+
)
|
|
253
311
|
|
|
254
312
|
pipeline = Pipeline(
|
|
255
313
|
uuid,
|
|
@@ -268,10 +326,13 @@ class Pipeline:
|
|
|
268
326
|
zip_size = sum(e.file_size for e in zipf.infolist()) # calc zip size in bytes
|
|
269
327
|
if zip_size / 1000 > PIPELINE_MAX_FILE_SIZE: # prevention against zip-bombs
|
|
270
328
|
raise PipelineZipTooLargeError(
|
|
271
|
-
f'Pipeline zip exceeds size limit {PIPELINE_MAX_FILE_SIZE/1000}Kb'
|
|
329
|
+
f'Pipeline zip exceeds size limit {PIPELINE_MAX_FILE_SIZE / 1000}Kb'
|
|
330
|
+
)
|
|
272
331
|
|
|
273
332
|
# Ignore `__MACOSX` for zips created on macOS systems
|
|
274
|
-
zip_contents = [
|
|
333
|
+
zip_contents = [
|
|
334
|
+
path for path in zipf.namelist() if not path.startswith('__MACOSX')
|
|
335
|
+
]
|
|
275
336
|
# Verify if zip contents are part of a root folder
|
|
276
337
|
prefix = os.path.commonpath(zip_contents)
|
|
277
338
|
|
|
@@ -301,7 +362,9 @@ class Pipeline:
|
|
|
301
362
|
raise FileWriteError(f'Failed to write pipeline file to {destination}.')
|
|
302
363
|
|
|
303
364
|
# return the pipeline configuration file
|
|
304
|
-
config_destination_path = pipeline_files[0][
|
|
365
|
+
config_destination_path = pipeline_files[0][
|
|
366
|
+
1
|
|
367
|
+
] # First item is the pipeline config path
|
|
305
368
|
ret_file = File.from_path(config_destination_path)
|
|
306
369
|
ret_file.filename = new_pipeline_uuid
|
|
307
370
|
|
|
@@ -331,8 +394,10 @@ class Pipeline:
|
|
|
331
394
|
repo_path=source_pipeline.repo_path,
|
|
332
395
|
)
|
|
333
396
|
|
|
334
|
-
if
|
|
335
|
-
|
|
397
|
+
if (
|
|
398
|
+
source_pipeline.type == PipelineType.INTEGRATION
|
|
399
|
+
and source_pipeline.data_integration is not None
|
|
400
|
+
):
|
|
336
401
|
with open(duplicate_pipeline.catalog_config_path, 'w') as fp:
|
|
337
402
|
json.dump(source_pipeline.data_integration, fp)
|
|
338
403
|
|
|
@@ -357,7 +422,7 @@ class Pipeline:
|
|
|
357
422
|
|
|
358
423
|
block_cache = await BlockCache.initialize_cache()
|
|
359
424
|
for block in blocks:
|
|
360
|
-
block_cache.add_pipeline(block, duplicate_pipeline)
|
|
425
|
+
block_cache.add_pipeline(block, duplicate_pipeline, duplicate_pipeline.repo_path)
|
|
361
426
|
|
|
362
427
|
return cls.get(
|
|
363
428
|
duplicate_pipeline_uuid,
|
|
@@ -376,30 +441,46 @@ class Pipeline:
|
|
|
376
441
|
|
|
377
442
|
@classmethod
|
|
378
443
|
def get(
|
|
379
|
-
|
|
444
|
+
cls,
|
|
380
445
|
uuid,
|
|
381
446
|
repo_path: str = None,
|
|
447
|
+
repo_config=None,
|
|
382
448
|
check_if_exists: bool = False,
|
|
383
449
|
all_projects: bool = False,
|
|
450
|
+
context_data: Dict = None,
|
|
384
451
|
use_repo_path: bool = False,
|
|
385
452
|
):
|
|
386
|
-
|
|
387
|
-
IntegrationPipeline,
|
|
388
|
-
)
|
|
453
|
+
warn_for_repo_path(repo_path)
|
|
389
454
|
|
|
390
|
-
config_path, repo_path =
|
|
455
|
+
config_path, repo_path = cls._get_config_path(
|
|
391
456
|
uuid,
|
|
392
457
|
repo_path=repo_path,
|
|
393
458
|
all_projects=all_projects,
|
|
459
|
+
context_data=context_data,
|
|
394
460
|
use_repo_path=use_repo_path,
|
|
395
461
|
)
|
|
396
462
|
|
|
397
|
-
if check_if_exists and not os.path.exists(config_path):
|
|
463
|
+
if check_if_exists and (not config_path or not os.path.exists(config_path)):
|
|
398
464
|
return None
|
|
399
465
|
|
|
400
|
-
pipeline =
|
|
466
|
+
pipeline = cls(
|
|
467
|
+
uuid,
|
|
468
|
+
repo_path=repo_path,
|
|
469
|
+
repo_config=repo_config,
|
|
470
|
+
context_data=context_data,
|
|
471
|
+
use_repo_path=use_repo_path,
|
|
472
|
+
)
|
|
401
473
|
if PipelineType.INTEGRATION == pipeline.type:
|
|
402
|
-
|
|
474
|
+
from mage_ai.data_preparation.models.pipelines.integration_pipeline import (
|
|
475
|
+
IntegrationPipeline,
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
pipeline = IntegrationPipeline(
|
|
479
|
+
uuid,
|
|
480
|
+
repo_path=repo_path,
|
|
481
|
+
repo_config=repo_config,
|
|
482
|
+
context_data=context_data,
|
|
483
|
+
)
|
|
403
484
|
|
|
404
485
|
return pipeline
|
|
405
486
|
|
|
@@ -424,7 +505,7 @@ class Pipeline:
|
|
|
424
505
|
return None
|
|
425
506
|
|
|
426
507
|
with open(metadata_path) as fp:
|
|
427
|
-
config =
|
|
508
|
+
config = load_yaml(fp) or {}
|
|
428
509
|
return config
|
|
429
510
|
|
|
430
511
|
@classmethod
|
|
@@ -433,12 +514,17 @@ class Pipeline:
|
|
|
433
514
|
uuid,
|
|
434
515
|
repo_path: str = None,
|
|
435
516
|
all_projects: bool = False,
|
|
517
|
+
context_data: Dict = None,
|
|
436
518
|
use_repo_path: bool = False,
|
|
437
519
|
) -> Tuple[str, str]:
|
|
438
520
|
if all_projects and not use_repo_path and project_platform_activated():
|
|
439
521
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
440
522
|
|
|
441
|
-
config_path, repo_path = get_pipeline_config_path(
|
|
523
|
+
config_path, repo_path = get_pipeline_config_path(
|
|
524
|
+
uuid,
|
|
525
|
+
context_data=context_data,
|
|
526
|
+
repo_path=repo_path,
|
|
527
|
+
)
|
|
442
528
|
else:
|
|
443
529
|
repo_path = repo_path or get_repo_path()
|
|
444
530
|
config_path = os.path.join(
|
|
@@ -478,7 +564,7 @@ class Pipeline:
|
|
|
478
564
|
|
|
479
565
|
config = None
|
|
480
566
|
async with aiofiles.open(config_path, mode='r') as f:
|
|
481
|
-
config =
|
|
567
|
+
config = load_yaml(await f.read()) or {}
|
|
482
568
|
except Exception as e:
|
|
483
569
|
if raise_exception:
|
|
484
570
|
raise e
|
|
@@ -495,16 +581,19 @@ class Pipeline:
|
|
|
495
581
|
uuid,
|
|
496
582
|
repo_path: str = None,
|
|
497
583
|
all_projects: bool = False,
|
|
584
|
+
context_data: Dict = None,
|
|
498
585
|
use_repo_path: bool = False,
|
|
499
586
|
):
|
|
500
|
-
|
|
501
|
-
IntegrationPipeline,
|
|
502
|
-
)
|
|
587
|
+
warn_for_repo_path(repo_path)
|
|
503
588
|
|
|
504
589
|
if all_projects and not use_repo_path and project_platform_activated():
|
|
505
590
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
506
591
|
|
|
507
|
-
config_path, repo_path = get_pipeline_config_path(
|
|
592
|
+
config_path, repo_path = get_pipeline_config_path(
|
|
593
|
+
uuid,
|
|
594
|
+
context_data=context_data,
|
|
595
|
+
repo_path=repo_path,
|
|
596
|
+
)
|
|
508
597
|
else:
|
|
509
598
|
repo_path = repo_path or get_repo_path()
|
|
510
599
|
config_path = os.path.join(
|
|
@@ -514,12 +603,16 @@ class Pipeline:
|
|
|
514
603
|
PIPELINE_CONFIG_FILE,
|
|
515
604
|
)
|
|
516
605
|
|
|
517
|
-
if not os.path.exists(config_path):
|
|
606
|
+
if not config_path or not os.path.exists(config_path):
|
|
518
607
|
raise Exception(f'Pipeline {uuid} does not exist.')
|
|
519
608
|
async with aiofiles.open(config_path, mode='r', encoding='utf-8') as f:
|
|
520
|
-
config =
|
|
609
|
+
config = load_yaml(await f.read()) or {}
|
|
521
610
|
|
|
522
611
|
if PipelineType.INTEGRATION == config.get('type'):
|
|
612
|
+
from mage_ai.data_preparation.models.pipelines.integration_pipeline import (
|
|
613
|
+
IntegrationPipeline,
|
|
614
|
+
)
|
|
615
|
+
|
|
523
616
|
catalog = None
|
|
524
617
|
catalog_config_path = os.path.join(
|
|
525
618
|
repo_path,
|
|
@@ -553,9 +646,15 @@ class Pipeline:
|
|
|
553
646
|
**kwargs,
|
|
554
647
|
) -> Union[List[str], List[Tuple[str, str]]]:
|
|
555
648
|
if project_platform_activated():
|
|
556
|
-
repo_paths = [
|
|
557
|
-
|
|
558
|
-
|
|
649
|
+
repo_paths = [
|
|
650
|
+
d.get(
|
|
651
|
+
'full_path',
|
|
652
|
+
)
|
|
653
|
+
for d in build_repo_path_for_all_projects(
|
|
654
|
+
context_data=kwargs.get('context_data'),
|
|
655
|
+
mage_projects_only=True
|
|
656
|
+
).values()
|
|
657
|
+
]
|
|
559
658
|
|
|
560
659
|
return Pipeline.get_all_pipelines(
|
|
561
660
|
*args,
|
|
@@ -571,6 +670,7 @@ class Pipeline:
|
|
|
571
670
|
repo_paths: List[str] = None,
|
|
572
671
|
disable_pipelines_folder_creation: bool = False,
|
|
573
672
|
include_repo_path: bool = False,
|
|
673
|
+
**kwargs,
|
|
574
674
|
) -> Union[List[str], List[Tuple[str, str]]]:
|
|
575
675
|
arr = []
|
|
576
676
|
|
|
@@ -580,7 +680,7 @@ class Pipeline:
|
|
|
580
680
|
if repo_paths:
|
|
581
681
|
paths.extend(repo_paths)
|
|
582
682
|
|
|
583
|
-
for path in paths:
|
|
683
|
+
for path in set(paths):
|
|
584
684
|
pipelines_folder = os.path.join(path, PIPELINES_FOLDER)
|
|
585
685
|
pipelines_folder_exists = os.path.exists(pipelines_folder)
|
|
586
686
|
if not pipelines_folder_exists and not disable_pipelines_folder_creation:
|
|
@@ -598,7 +698,10 @@ class Pipeline:
|
|
|
598
698
|
return arr
|
|
599
699
|
|
|
600
700
|
@classmethod
|
|
601
|
-
def get_pipelines_by_block(
|
|
701
|
+
def get_pipelines_by_block(
|
|
702
|
+
self, block, repo_path: str = None, widget=False
|
|
703
|
+
) -> List['Pipeline']:
|
|
704
|
+
warn_for_repo_path(repo_path)
|
|
602
705
|
repo_path = repo_path or get_repo_path()
|
|
603
706
|
pipelines_folder = os.path.join(repo_path, PIPELINES_FOLDER)
|
|
604
707
|
pipelines = []
|
|
@@ -689,6 +792,7 @@ class Pipeline:
|
|
|
689
792
|
from mage_ai.data_preparation.executors.streaming_pipeline_executor import (
|
|
690
793
|
StreamingPipelineExecutor,
|
|
691
794
|
)
|
|
795
|
+
|
|
692
796
|
StreamingPipelineExecutor(self).execute(
|
|
693
797
|
build_block_output_stdout=build_block_output_stdout,
|
|
694
798
|
global_vars=global_vars,
|
|
@@ -720,7 +824,7 @@ class Pipeline:
|
|
|
720
824
|
if not os.path.exists(self.config_path):
|
|
721
825
|
raise Exception(f'Pipeline {self.uuid} does not exist in repo_path {self.repo_path}.')
|
|
722
826
|
with open(self.config_path, encoding='utf-8') as fp:
|
|
723
|
-
config =
|
|
827
|
+
config = load_yaml(fp) or {}
|
|
724
828
|
return config
|
|
725
829
|
|
|
726
830
|
def get_catalog_from_json(self):
|
|
@@ -789,7 +893,9 @@ class Pipeline:
|
|
|
789
893
|
|
|
790
894
|
language = c.get('language')
|
|
791
895
|
|
|
792
|
-
return BlockFactory.block_class_from_type(
|
|
896
|
+
return BlockFactory.block_class_from_type(
|
|
897
|
+
block_type, language=language, pipeline=self
|
|
898
|
+
)(
|
|
793
899
|
c.get('name'),
|
|
794
900
|
c.get('uuid'),
|
|
795
901
|
block_type,
|
|
@@ -838,17 +944,28 @@ class Pipeline:
|
|
|
838
944
|
|
|
839
945
|
for extension_uuid, extension_config in config.get('extensions', {}).items():
|
|
840
946
|
extension_configs = extension_config.get('blocks') or []
|
|
841
|
-
extension_blocks = [
|
|
842
|
-
|
|
843
|
-
|
|
947
|
+
extension_blocks = [
|
|
948
|
+
build_shared_args_kwargs(
|
|
949
|
+
merge_dict(
|
|
950
|
+
c,
|
|
951
|
+
dict(
|
|
952
|
+
extension_uuid=extension_uuid,
|
|
953
|
+
),
|
|
954
|
+
)
|
|
955
|
+
)
|
|
956
|
+
for c in extension_configs
|
|
957
|
+
]
|
|
844
958
|
|
|
845
|
-
self.extensions[extension_uuid] = merge_dict(
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
959
|
+
self.extensions[extension_uuid] = merge_dict(
|
|
960
|
+
extension_config,
|
|
961
|
+
dict(
|
|
962
|
+
blocks_by_uuid=self.__initialize_blocks_by_uuid(
|
|
963
|
+
extension_configs,
|
|
964
|
+
extension_blocks,
|
|
965
|
+
all_blocks,
|
|
966
|
+
),
|
|
850
967
|
),
|
|
851
|
-
)
|
|
968
|
+
)
|
|
852
969
|
|
|
853
970
|
blocks_with_callbacks = {}
|
|
854
971
|
for callback_block in self.callbacks_by_uuid.values():
|
|
@@ -882,11 +999,13 @@ class Pipeline:
|
|
|
882
999
|
for b in configs:
|
|
883
1000
|
block = blocks_by_uuid[b['uuid']]
|
|
884
1001
|
block.downstream_blocks = [
|
|
885
|
-
all_blocks_by_uuid[uuid]
|
|
1002
|
+
all_blocks_by_uuid[uuid]
|
|
1003
|
+
for uuid in b.get('downstream_blocks', [])
|
|
886
1004
|
if uuid in all_blocks_by_uuid
|
|
887
1005
|
]
|
|
888
1006
|
block.upstream_blocks = [
|
|
889
|
-
all_blocks_by_uuid[uuid]
|
|
1007
|
+
all_blocks_by_uuid[uuid]
|
|
1008
|
+
for uuid in b.get('upstream_blocks', [])
|
|
890
1009
|
if uuid in all_blocks_by_uuid
|
|
891
1010
|
]
|
|
892
1011
|
|
|
@@ -940,7 +1059,9 @@ class Pipeline:
|
|
|
940
1059
|
|
|
941
1060
|
blocks_data = [b.to_dict(**shared_kwargs) for b in self.blocks_by_uuid.values()]
|
|
942
1061
|
callbacks_data = [b.to_dict(**shared_kwargs) for b in self.callbacks_by_uuid.values()]
|
|
943
|
-
conditionals_data = [
|
|
1062
|
+
conditionals_data = [
|
|
1063
|
+
b.to_dict(**shared_kwargs) for b in self.conditionals_by_uuid.values()
|
|
1064
|
+
]
|
|
944
1065
|
widgets_data = [b.to_dict(**shared_kwargs) for b in self.widgets_by_uuid.values()]
|
|
945
1066
|
|
|
946
1067
|
data = dict(
|
|
@@ -961,13 +1082,17 @@ class Pipeline:
|
|
|
961
1082
|
include_outputs=include_outputs,
|
|
962
1083
|
include_outputs_spark=include_outputs_spark,
|
|
963
1084
|
sample_count=sample_count,
|
|
964
|
-
|
|
1085
|
+
)
|
|
1086
|
+
for b in extension['blocks_by_uuid'].values()
|
|
965
1087
|
]
|
|
966
1088
|
extensions_data[extension_uuid] = merge_dict(
|
|
967
|
-
ignore_keys(
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1089
|
+
ignore_keys(
|
|
1090
|
+
extension,
|
|
1091
|
+
[
|
|
1092
|
+
'blocks',
|
|
1093
|
+
'blocks_by_uuid',
|
|
1094
|
+
],
|
|
1095
|
+
),
|
|
971
1096
|
dict(
|
|
972
1097
|
blocks=blocks,
|
|
973
1098
|
),
|
|
@@ -991,7 +1116,10 @@ class Pipeline:
|
|
|
991
1116
|
include_extensions: bool = False,
|
|
992
1117
|
include_outputs: bool = False,
|
|
993
1118
|
include_outputs_spark: bool = False,
|
|
994
|
-
sample_count: int = None,
|
|
1119
|
+
sample_count: Optional[int] = None,
|
|
1120
|
+
disable_block_output_previews: bool = False,
|
|
1121
|
+
exclude_blank_variable_uuids: bool = False,
|
|
1122
|
+
max_results: Optional[int] = None,
|
|
995
1123
|
):
|
|
996
1124
|
shared_kwargs = dict(
|
|
997
1125
|
check_if_file_exists=True,
|
|
@@ -1005,26 +1133,36 @@ class Pipeline:
|
|
|
1005
1133
|
)
|
|
1006
1134
|
if include_block_pipelines:
|
|
1007
1135
|
shared_kwargs['block_cache'] = BlockCache()
|
|
1008
|
-
blocks_data = await asyncio.gather(
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1136
|
+
blocks_data = await asyncio.gather(*[
|
|
1137
|
+
b.to_dict_async(
|
|
1138
|
+
**merge_dict(
|
|
1139
|
+
shared_kwargs,
|
|
1140
|
+
dict(
|
|
1141
|
+
include_block_catalog=include_block_catalog,
|
|
1142
|
+
include_block_pipelines=include_block_pipelines,
|
|
1143
|
+
include_outputs_spark=include_outputs_spark,
|
|
1144
|
+
disable_output_preview=disable_block_output_previews,
|
|
1145
|
+
exclude_blank_variable_uuids=exclude_blank_variable_uuids,
|
|
1146
|
+
max_results=max_results,
|
|
1147
|
+
),
|
|
1148
|
+
)
|
|
1149
|
+
)
|
|
1150
|
+
for b in self.blocks_by_uuid.values()
|
|
1151
|
+
])
|
|
1152
|
+
callbacks_data = await asyncio.gather(*[
|
|
1153
|
+
b.to_dict_async(**shared_kwargs) for b in self.callbacks_by_uuid.values()
|
|
1154
|
+
])
|
|
1155
|
+
conditionals_data = await asyncio.gather(*[
|
|
1156
|
+
b.to_dict_async(**shared_kwargs) for b in self.conditionals_by_uuid.values()
|
|
1157
|
+
])
|
|
1158
|
+
widgets_data = await asyncio.gather(*[
|
|
1159
|
+
b.to_dict_async(
|
|
1023
1160
|
include_content=include_content,
|
|
1024
1161
|
include_outputs=include_outputs,
|
|
1025
1162
|
sample_count=sample_count,
|
|
1026
|
-
|
|
1027
|
-
|
|
1163
|
+
)
|
|
1164
|
+
for b in self.widgets_by_uuid.values()
|
|
1165
|
+
])
|
|
1028
1166
|
data = dict(
|
|
1029
1167
|
blocks=blocks_data,
|
|
1030
1168
|
callbacks=callbacks_data,
|
|
@@ -1037,18 +1175,22 @@ class Pipeline:
|
|
|
1037
1175
|
for extension_uuid, extension in self.extensions.items():
|
|
1038
1176
|
blocks = []
|
|
1039
1177
|
if 'blocks_by_uuid' in extension:
|
|
1040
|
-
blocks = await asyncio.gather(
|
|
1041
|
-
|
|
1178
|
+
blocks = await asyncio.gather(*[
|
|
1179
|
+
b.to_dict_async(
|
|
1042
1180
|
include_content=include_content,
|
|
1043
1181
|
include_outputs=include_outputs,
|
|
1044
1182
|
sample_count=sample_count,
|
|
1045
|
-
|
|
1046
|
-
|
|
1183
|
+
)
|
|
1184
|
+
for b in extension['blocks_by_uuid'].values()
|
|
1185
|
+
])
|
|
1047
1186
|
extensions_data[extension_uuid] = merge_dict(
|
|
1048
|
-
ignore_keys(
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1187
|
+
ignore_keys(
|
|
1188
|
+
extension,
|
|
1189
|
+
[
|
|
1190
|
+
'blocks',
|
|
1191
|
+
'blocks_by_uuid',
|
|
1192
|
+
],
|
|
1193
|
+
),
|
|
1052
1194
|
dict(
|
|
1053
1195
|
blocks=blocks,
|
|
1054
1196
|
),
|
|
@@ -1086,6 +1228,8 @@ class Pipeline:
|
|
|
1086
1228
|
self.uuid = new_uuid
|
|
1087
1229
|
new_pipeline_path = self.dir_path
|
|
1088
1230
|
os.rename(old_pipeline_path, new_pipeline_path)
|
|
1231
|
+
# Force updating the config path
|
|
1232
|
+
self._config_path = None
|
|
1089
1233
|
await self.save_async()
|
|
1090
1234
|
transfer_related_models_for_pipeline(old_uuid, new_uuid)
|
|
1091
1235
|
|
|
@@ -1099,7 +1243,7 @@ class Pipeline:
|
|
|
1099
1243
|
should_update_tag_cache = True
|
|
1100
1244
|
|
|
1101
1245
|
cache = PipelineCache()
|
|
1102
|
-
cache.move_model(dict(uuid=new_uuid), dict(uuid=old_uuid))
|
|
1246
|
+
cache.move_model(dict(uuid=new_uuid), dict(uuid=old_uuid), repo_path=self.repo_path)
|
|
1103
1247
|
|
|
1104
1248
|
should_save = False
|
|
1105
1249
|
|
|
@@ -1107,11 +1251,12 @@ class Pipeline:
|
|
|
1107
1251
|
for extension_uuid, extension in data['extensions'].items():
|
|
1108
1252
|
if extension_uuid not in self.extensions:
|
|
1109
1253
|
self.extensions[extension_uuid] = {}
|
|
1110
|
-
self.extensions[extension_uuid]
|
|
1111
|
-
self.extensions[extension_uuid]
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1254
|
+
if compare_extension(extension, self.extensions[extension_uuid]):
|
|
1255
|
+
self.extensions[extension_uuid] = merge_dict(
|
|
1256
|
+
self.extensions[extension_uuid],
|
|
1257
|
+
extension,
|
|
1258
|
+
)
|
|
1259
|
+
should_save = True
|
|
1115
1260
|
|
|
1116
1261
|
if 'tags' in data:
|
|
1117
1262
|
new_tags = data.get('tags', [])
|
|
@@ -1137,16 +1282,17 @@ class Pipeline:
|
|
|
1137
1282
|
|
|
1138
1283
|
for key in [
|
|
1139
1284
|
'cache_block_output_in_memory',
|
|
1285
|
+
'concurrency_config',
|
|
1140
1286
|
'data_integration',
|
|
1141
1287
|
'executor_type',
|
|
1142
1288
|
'retry_config',
|
|
1143
1289
|
'run_pipeline_in_one_process',
|
|
1144
1290
|
]:
|
|
1145
|
-
if key in data:
|
|
1291
|
+
if key in data and data.get(key) != getattr(self, key):
|
|
1146
1292
|
setattr(self, key, data.get(key))
|
|
1147
1293
|
should_save = True
|
|
1148
1294
|
|
|
1149
|
-
if 'settings' in data:
|
|
1295
|
+
if 'settings' in data and data.get('settings') != self.settings.to_dict():
|
|
1150
1296
|
self.settings = PipelineSettings.load(**(data.get('settings') or {}))
|
|
1151
1297
|
should_save = True
|
|
1152
1298
|
|
|
@@ -1224,7 +1370,7 @@ class Pipeline:
|
|
|
1224
1370
|
)
|
|
1225
1371
|
|
|
1226
1372
|
if hooks:
|
|
1227
|
-
for hook in
|
|
1373
|
+
for hook in hooks or []:
|
|
1228
1374
|
output = hook.output
|
|
1229
1375
|
if not output:
|
|
1230
1376
|
continue
|
|
@@ -1242,25 +1388,31 @@ class Pipeline:
|
|
|
1242
1388
|
old_block_content = await block.content_async()
|
|
1243
1389
|
if block_data['content'] != old_block_content:
|
|
1244
1390
|
if cache_block_action_object is None:
|
|
1245
|
-
cache_block_action_object =
|
|
1391
|
+
cache_block_action_object = (
|
|
1246
1392
|
await BlockActionObjectCache.initialize_cache()
|
|
1393
|
+
)
|
|
1247
1394
|
|
|
1248
1395
|
await block.update_content_async(block_data['content'], widget=widget)
|
|
1249
1396
|
|
|
1250
1397
|
cache_block_action_object.update_block(block)
|
|
1251
1398
|
|
|
1252
|
-
if 'callback_content' in block_data
|
|
1253
|
-
and block.callback_block:
|
|
1399
|
+
if 'callback_content' in block_data and block.callback_block:
|
|
1254
1400
|
await block.callback_block.update_content_async(
|
|
1255
1401
|
block_data['callback_content'],
|
|
1256
1402
|
widget=widget,
|
|
1257
1403
|
)
|
|
1258
|
-
if
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1404
|
+
if (
|
|
1405
|
+
'outputs' in block_data
|
|
1406
|
+
and not widget
|
|
1407
|
+
and not is_dynamic_block(block)
|
|
1408
|
+
and not is_dynamic_block_child(block)
|
|
1409
|
+
):
|
|
1410
|
+
if BlockType.SCRATCHPAD == block.type:
|
|
1411
|
+
block.delete_variables()
|
|
1412
|
+
await block.save_outputs_async(
|
|
1413
|
+
block_data['outputs'],
|
|
1414
|
+
override=True,
|
|
1415
|
+
)
|
|
1264
1416
|
|
|
1265
1417
|
name = block_data.get('name')
|
|
1266
1418
|
|
|
@@ -1272,7 +1424,7 @@ class Pipeline:
|
|
|
1272
1424
|
block.update(extract(block_data, ['color']))
|
|
1273
1425
|
|
|
1274
1426
|
configuration = block_data.get('configuration')
|
|
1275
|
-
if configuration:
|
|
1427
|
+
if configuration and configuration != block.configuration:
|
|
1276
1428
|
block.configuration = configuration
|
|
1277
1429
|
should_save_async = should_save_async or True
|
|
1278
1430
|
|
|
@@ -1282,42 +1434,50 @@ class Pipeline:
|
|
|
1282
1434
|
if name and name != block.name:
|
|
1283
1435
|
keys_to_update.append('name')
|
|
1284
1436
|
|
|
1285
|
-
|
|
1437
|
+
upstream_blocks = block_data.get('upstream_blocks') or []
|
|
1438
|
+
if upstream_blocks != block.upstream_block_uuids:
|
|
1286
1439
|
keys_to_update.append('upstream_blocks')
|
|
1287
1440
|
block_data['upstream_blocks'] = [
|
|
1288
|
-
block_uuid_mapping.get(b, b)
|
|
1289
|
-
for b in block_data['upstream_blocks']
|
|
1441
|
+
block_uuid_mapping.get(b, b) for b in block_data['upstream_blocks']
|
|
1290
1442
|
]
|
|
1291
|
-
|
|
1292
1443
|
if len(keys_to_update) >= 1:
|
|
1293
1444
|
block.update(extract(block_data, keys_to_update))
|
|
1445
|
+
should_save_async = should_save_async or True
|
|
1294
1446
|
|
|
1295
|
-
should_save_async = should_save_async or True
|
|
1296
1447
|
elif name and name != block.name:
|
|
1297
1448
|
from mage_ai.cache.block_action_object import (
|
|
1298
1449
|
BlockActionObjectCache,
|
|
1299
1450
|
)
|
|
1300
1451
|
|
|
1301
1452
|
if cache_block_action_object is None:
|
|
1302
|
-
cache_block_action_object =
|
|
1453
|
+
cache_block_action_object = (
|
|
1303
1454
|
await BlockActionObjectCache.initialize_cache()
|
|
1455
|
+
)
|
|
1304
1456
|
cache_block_action_object.update_block(block, remove=True)
|
|
1305
1457
|
|
|
1458
|
+
new_block_uuid = clean_name(name)
|
|
1459
|
+
(
|
|
1460
|
+
old_file_path,
|
|
1461
|
+
old_file_path_relative,
|
|
1462
|
+
) = block.build_file_path_directory()
|
|
1463
|
+
(
|
|
1464
|
+
new_file_path,
|
|
1465
|
+
new_file_path_relative,
|
|
1466
|
+
) = block.build_file_path_directory(
|
|
1467
|
+
block_uuid=new_block_uuid,
|
|
1468
|
+
)
|
|
1469
|
+
|
|
1306
1470
|
block_update_payload = extract(block_data, ['name'])
|
|
1307
|
-
configuration = copy.deepcopy(block_data).get('configuration', {})
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
block_update_payload['configuration'] = configuration
|
|
1471
|
+
configuration = copy.deepcopy(block_data).get('configuration', {}) or {}
|
|
1472
|
+
configuration['file_path'] = new_file_path_relative
|
|
1473
|
+
|
|
1474
|
+
if not configuration.get('file_source'):
|
|
1475
|
+
configuration['file_source'] = {}
|
|
1476
|
+
configuration['file_source']['path'] = new_file_path_relative
|
|
1477
|
+
block_update_payload['configuration'] = configuration
|
|
1478
|
+
|
|
1316
1479
|
blocks_to_remove_from_cache.append(block.to_dict())
|
|
1317
|
-
block.update(
|
|
1318
|
-
block_update_payload,
|
|
1319
|
-
detach=block_data.get('detach', False)
|
|
1320
|
-
)
|
|
1480
|
+
block.update(block_update_payload, detach=block_data.get('detach', False))
|
|
1321
1481
|
|
|
1322
1482
|
block_uuids_to_add_to_cache.append(block.uuid)
|
|
1323
1483
|
cache_block_action_object.update_block(block)
|
|
@@ -1335,9 +1495,9 @@ class Pipeline:
|
|
|
1335
1495
|
# we need to update mage_sources.yml
|
|
1336
1496
|
if any(
|
|
1337
1497
|
(
|
|
1338
|
-
BlockType.DBT != block.type
|
|
1339
|
-
block.language in [BlockLanguage.SQL, BlockLanguage.PYTHON, BlockLanguage.R]
|
|
1340
|
-
any(
|
|
1498
|
+
BlockType.DBT != block.type
|
|
1499
|
+
and block.language in [BlockLanguage.SQL, BlockLanguage.PYTHON, BlockLanguage.R]
|
|
1500
|
+
and any(
|
|
1341
1501
|
BlockType.DBT == downstream_block.type
|
|
1342
1502
|
for downstream_block in block.downstream_blocks
|
|
1343
1503
|
)
|
|
@@ -1370,7 +1530,7 @@ class Pipeline:
|
|
|
1370
1530
|
old_uuid,
|
|
1371
1531
|
self.repo_path,
|
|
1372
1532
|
)
|
|
1373
|
-
cache.update_pipeline(block.to_dict(), self)
|
|
1533
|
+
cache.update_pipeline(block.to_dict(), self, self.repo_path)
|
|
1374
1534
|
|
|
1375
1535
|
if should_update_tag_cache:
|
|
1376
1536
|
from mage_ai.cache.tag import TagCache
|
|
@@ -1452,8 +1612,7 @@ class Pipeline:
|
|
|
1452
1612
|
|
|
1453
1613
|
files_to_be_written = []
|
|
1454
1614
|
with open(config_zip_path, 'r') as pipeline_config:
|
|
1455
|
-
|
|
1456
|
-
config = yaml.safe_load(pipeline_config)
|
|
1615
|
+
config = load_yaml(pipeline_config)
|
|
1457
1616
|
|
|
1458
1617
|
# check if pipeline exists with same uuid and generate new one if necessary
|
|
1459
1618
|
if not overwrite:
|
|
@@ -1563,8 +1722,10 @@ class Pipeline:
|
|
|
1563
1722
|
|
|
1564
1723
|
if block_uuid in self.blocks_by_uuid:
|
|
1565
1724
|
block = self.blocks_by_uuid[block_uuid]
|
|
1566
|
-
if
|
|
1567
|
-
|
|
1725
|
+
if (
|
|
1726
|
+
upstream_blocks_reordered is not None
|
|
1727
|
+
and upstream_blocks != upstream_blocks_reordered
|
|
1728
|
+
):
|
|
1568
1729
|
block.update(
|
|
1569
1730
|
dict(upstream_blocks=upstream_blocks_reordered),
|
|
1570
1731
|
check_upstream_block_order=True,
|
|
@@ -1612,7 +1773,8 @@ class Pipeline:
|
|
|
1612
1773
|
all_block_uuids = {b.get('uuid') for b in self.all_block_configs}
|
|
1613
1774
|
if block.uuid in all_block_uuids:
|
|
1614
1775
|
raise InvalidPipelineError(
|
|
1615
|
-
f'Block with uuid {block.uuid} already exists in pipeline {self.uuid}'
|
|
1776
|
+
f'Block with uuid {block.uuid} already exists in pipeline {self.uuid}'
|
|
1777
|
+
)
|
|
1616
1778
|
|
|
1617
1779
|
if widget:
|
|
1618
1780
|
self.widgets_by_uuid = self.__add_block_to_mapping(
|
|
@@ -1665,9 +1827,8 @@ class Pipeline:
|
|
|
1665
1827
|
|
|
1666
1828
|
self.update_block(
|
|
1667
1829
|
downstream_block,
|
|
1668
|
-
upstream_block_uuids=(
|
|
1669
|
-
|
|
1670
|
-
) + [block.uuid],
|
|
1830
|
+
upstream_block_uuids=(downstream_block.upstream_block_uuids or [])
|
|
1831
|
+
+ [block.uuid],
|
|
1671
1832
|
)
|
|
1672
1833
|
|
|
1673
1834
|
self.validate('A cycle was formed while adding a block')
|
|
@@ -1727,9 +1888,13 @@ class Pipeline:
|
|
|
1727
1888
|
sample_count: int = None,
|
|
1728
1889
|
dynamic_block_index: int = None,
|
|
1729
1890
|
dynamic_block_uuid: str = None,
|
|
1891
|
+
input_data_types: Optional[List[InputDataType]] = None,
|
|
1892
|
+
read_batch_settings: Optional[BatchSettings] = None,
|
|
1893
|
+
read_chunks: Optional[List[ChunkKeyTypeUnion]] = None,
|
|
1894
|
+
write_batch_settings: Optional[BatchSettings] = None,
|
|
1895
|
+
write_chunks: Optional[List[ChunkKeyTypeUnion]] = None,
|
|
1730
1896
|
):
|
|
1731
1897
|
block = self.get_block(block_uuid)
|
|
1732
|
-
|
|
1733
1898
|
data_integration_settings = block.get_data_integration_settings(
|
|
1734
1899
|
from_notebook=from_notebook,
|
|
1735
1900
|
global_vars=global_vars,
|
|
@@ -1757,6 +1922,11 @@ class Pipeline:
|
|
|
1757
1922
|
variable_uuid=variable_name,
|
|
1758
1923
|
dynamic_block_index=dynamic_block_index,
|
|
1759
1924
|
dynamic_block_uuid=dynamic_block_uuid,
|
|
1925
|
+
input_data_types=input_data_types,
|
|
1926
|
+
read_batch_settings=read_batch_settings,
|
|
1927
|
+
read_chunks=read_chunks,
|
|
1928
|
+
write_batch_settings=write_batch_settings,
|
|
1929
|
+
write_chunks=write_chunks,
|
|
1760
1930
|
)
|
|
1761
1931
|
|
|
1762
1932
|
return variable
|
|
@@ -1768,17 +1938,22 @@ class Pipeline:
|
|
|
1768
1938
|
def get_executable_blocks(self):
|
|
1769
1939
|
return [b for b in self.blocks_by_uuid.values() if b.executable]
|
|
1770
1940
|
|
|
1771
|
-
def get_executor_type(self) -> str:
|
|
1772
|
-
if self.
|
|
1773
|
-
|
|
1774
|
-
|
|
1941
|
+
def get_executor_type(self) -> Optional[str]:
|
|
1942
|
+
if self._rendered_executor_type is None:
|
|
1943
|
+
if self.executor_type:
|
|
1944
|
+
return Template(self.executor_type).render(**get_template_vars())
|
|
1945
|
+
else:
|
|
1946
|
+
self._rendered_executor_type = self.executor_type
|
|
1947
|
+
return self._rendered_executor_type
|
|
1775
1948
|
|
|
1776
1949
|
def has_block(self, block_uuid: str, block_type: str = None, extension_uuid: str = None):
|
|
1777
1950
|
if extension_uuid:
|
|
1778
|
-
return
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1951
|
+
return (
|
|
1952
|
+
self.extensions
|
|
1953
|
+
and extension_uuid in self.extensions
|
|
1954
|
+
and 'blocks_by_uuid' in self.extensions[extension_uuid]
|
|
1955
|
+
and block_uuid in self.extensions[extension_uuid]['blocks_by_uuid']
|
|
1956
|
+
)
|
|
1782
1957
|
elif BlockType.CALLBACK == block_type:
|
|
1783
1958
|
return block_uuid in self.callbacks_by_uuid
|
|
1784
1959
|
elif BlockType.CONDITIONAL == block_type:
|
|
@@ -1806,9 +1981,9 @@ class Pipeline:
|
|
|
1806
1981
|
if upstream_block_uuids is not None:
|
|
1807
1982
|
curr_upstream_block_uuids = set(block.upstream_block_uuids)
|
|
1808
1983
|
new_upstream_block_uuids = set(upstream_block_uuids)
|
|
1809
|
-
if curr_upstream_block_uuids != new_upstream_block_uuids or
|
|
1810
|
-
|
|
1811
|
-
|
|
1984
|
+
if curr_upstream_block_uuids != new_upstream_block_uuids or (
|
|
1985
|
+
check_upstream_block_order and block.upstream_block_uuids != upstream_block_uuids
|
|
1986
|
+
):
|
|
1812
1987
|
# Only set upstream block’s downstream to the current block if current block
|
|
1813
1988
|
# is not an extension block and not a callback/conditional block
|
|
1814
1989
|
if not is_extension and not is_callback and not is_conditional:
|
|
@@ -1867,9 +2042,9 @@ class Pipeline:
|
|
|
1867
2042
|
# conditional_blocks field.
|
|
1868
2043
|
block.update_conditional_blocks(conditional_blocks)
|
|
1869
2044
|
elif downstream_block_uuids is not None:
|
|
1870
|
-
block_uuids_to_remove =
|
|
1871
|
-
|
|
1872
|
-
|
|
2045
|
+
block_uuids_to_remove = [
|
|
2046
|
+
uuid for uuid in block.downstream_block_uuids if uuid not in downstream_block_uuids
|
|
2047
|
+
]
|
|
1873
2048
|
|
|
1874
2049
|
for block_uuid in block_uuids_to_remove:
|
|
1875
2050
|
block_inner = self.get_block(block_uuid)
|
|
@@ -1877,10 +2052,12 @@ class Pipeline:
|
|
|
1877
2052
|
continue
|
|
1878
2053
|
block_inner.update(
|
|
1879
2054
|
dict(
|
|
1880
|
-
upstream_blocks=list(
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
2055
|
+
upstream_blocks=list(
|
|
2056
|
+
filter(
|
|
2057
|
+
lambda x, uuid=block.uuid: x != uuid,
|
|
2058
|
+
block_inner.upstream_block_uuids or [],
|
|
2059
|
+
)
|
|
2060
|
+
),
|
|
1884
2061
|
),
|
|
1885
2062
|
check_upstream_block_order=check_upstream_block_order,
|
|
1886
2063
|
)
|
|
@@ -1988,7 +2165,8 @@ class Pipeline:
|
|
|
1988
2165
|
def update_global_variable(self, key, value):
|
|
1989
2166
|
if not is_yaml_serializable(key, value):
|
|
1990
2167
|
raise SerializationError(
|
|
1991
|
-
f'Failed to update variable {key} because the value is not serializable.'
|
|
2168
|
+
f'Failed to update variable {key} because the value is not serializable.'
|
|
2169
|
+
)
|
|
1992
2170
|
if self.variables is None:
|
|
1993
2171
|
self.variables = {}
|
|
1994
2172
|
self.variables[key] = value
|
|
@@ -2051,13 +2229,20 @@ class Pipeline:
|
|
|
2051
2229
|
]
|
|
2052
2230
|
if self.type == PipelineType.INTEGRATION or force:
|
|
2053
2231
|
for downstream_block in block.downstream_blocks:
|
|
2054
|
-
upstream_block_uuids = list(
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2232
|
+
upstream_block_uuids = list(
|
|
2233
|
+
filter(
|
|
2234
|
+
lambda uuid: uuid != block.uuid,
|
|
2235
|
+
downstream_block.upstream_block_uuids,
|
|
2236
|
+
)
|
|
2237
|
+
)
|
|
2238
|
+
downstream_block.update(
|
|
2239
|
+
dict(
|
|
2240
|
+
upstream_blocks=[
|
|
2241
|
+
*upstream_block_uuids,
|
|
2242
|
+
*block.upstream_block_uuids,
|
|
2243
|
+
]
|
|
2244
|
+
)
|
|
2245
|
+
)
|
|
2061
2246
|
elif len(downstream_block_uuids) > 0:
|
|
2062
2247
|
raise HasDownstreamDependencies(
|
|
2063
2248
|
f'Block(s) {downstream_block_uuids} are depending on block {block.uuid}'
|
|
@@ -2107,7 +2292,7 @@ class Pipeline:
|
|
|
2107
2292
|
blocks_current = sorted([b.uuid for b in self.blocks_by_uuid.values()])
|
|
2108
2293
|
|
|
2109
2294
|
if block_uuid is not None:
|
|
2110
|
-
current_pipeline = Pipeline(self.uuid, self.repo_path)
|
|
2295
|
+
current_pipeline = Pipeline(self.uuid, repo_path=self.repo_path)
|
|
2111
2296
|
block = self.get_block(
|
|
2112
2297
|
block_uuid,
|
|
2113
2298
|
block_type=block_type,
|
|
@@ -2163,18 +2348,21 @@ class Pipeline:
|
|
|
2163
2348
|
def should_save_trigger_in_code_automatically(self) -> bool:
|
|
2164
2349
|
from mage_ai.data_preparation.models.project import Project
|
|
2165
2350
|
|
|
2166
|
-
if
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2351
|
+
if (
|
|
2352
|
+
self.settings
|
|
2353
|
+
and self.settings.triggers
|
|
2354
|
+
and self.settings.triggers.save_in_code_automatically is not None
|
|
2355
|
+
):
|
|
2170
2356
|
return self.settings.triggers.save_in_code_automatically
|
|
2171
2357
|
|
|
2172
|
-
project = Project(self.repo_config)
|
|
2358
|
+
project = Project(repo_config=self.repo_config)
|
|
2173
2359
|
|
|
2174
|
-
return
|
|
2175
|
-
project.pipelines
|
|
2176
|
-
project.pipelines.settings
|
|
2177
|
-
project.pipelines.settings.triggers
|
|
2360
|
+
return (
|
|
2361
|
+
project.pipelines
|
|
2362
|
+
and project.pipelines.settings
|
|
2363
|
+
and project.pipelines.settings.triggers
|
|
2364
|
+
and project.pipelines.settings.triggers.save_in_code_automatically
|
|
2365
|
+
)
|
|
2178
2366
|
|
|
2179
2367
|
async def save_async(
|
|
2180
2368
|
self,
|
|
@@ -2231,7 +2419,7 @@ class Pipeline:
|
|
|
2231
2419
|
success = True
|
|
2232
2420
|
with open(test_path, mode='r', encoding='utf-8') as fp:
|
|
2233
2421
|
try:
|
|
2234
|
-
|
|
2422
|
+
load_yaml(fp)
|
|
2235
2423
|
except yaml.scanner.ScannerError:
|
|
2236
2424
|
success = False
|
|
2237
2425
|
|
|
@@ -2281,7 +2469,7 @@ class Pipeline:
|
|
|
2281
2469
|
index += 1
|
|
2282
2470
|
|
|
2283
2471
|
cycle = [frame.uuid for frame in virtual_stack[index:]]
|
|
2284
|
-
return
|
|
2472
|
+
return ' --> '.join(cycle)
|
|
2285
2473
|
|
|
2286
2474
|
def __check_cycle(block: Block):
|
|
2287
2475
|
virtual_stack = [StackFrame(block)]
|
|
@@ -2312,7 +2500,8 @@ class Pipeline:
|
|
|
2312
2500
|
uuid = config.get('uuid')
|
|
2313
2501
|
if uuid in check_block_uuids:
|
|
2314
2502
|
raise InvalidPipelineError(
|
|
2315
|
-
f'Pipeline is invalid: duplicate blocks with uuid {uuid}'
|
|
2503
|
+
f'Pipeline is invalid: duplicate blocks with uuid {uuid}'
|
|
2504
|
+
)
|
|
2316
2505
|
check_block_uuids.add(uuid)
|
|
2317
2506
|
|
|
2318
2507
|
|