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.
- 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/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 -138
- 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 +46 -9
- 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/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 +250 -123
- mage_ai/api/resources/PipelineRunResource.py +11 -3
- mage_ai/api/resources/PipelineScheduleResource.py +7 -2
- mage_ai/api/resources/PipelineTriggerResource.py +6 -1
- mage_ai/api/resources/ProjectResource.py +18 -7
- 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 +1 -1
- 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 +32 -4
- 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/manage.py +1 -1
- mage_ai/cluster_manager/workspace/base.py +1 -1
- mage_ai/command_center/applications/factory.py +10 -7
- mage_ai/command_center/files/factory.py +17 -15
- 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/streaming_pipeline_executor.py +1 -1
- mage_ai/data_preparation/git/__init__.py +27 -7
- mage_ai/data_preparation/git/api.py +7 -1
- mage_ai/data_preparation/git/utils.py +22 -16
- mage_ai/data_preparation/logging/logger_manager.py +4 -3
- mage_ai/data_preparation/models/block/__init__.py +1542 -878
- 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 +291 -168
- 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 +10 -1
- 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/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 +127 -70
- mage_ai/data_preparation/models/constants.py +19 -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 +88 -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 +365 -180
- 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 +120 -24
- 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 +6 -3
- 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/models/dynamic/__init__.py +0 -0
- mage_ai/orchestration/db/models/dynamic/controller.py +67 -0
- mage_ai/orchestration/db/models/oauth.py +2 -9
- mage_ai/orchestration/db/models/projects.py +10 -0
- mage_ai/orchestration/db/models/schedules.py +204 -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 +1 -0
- mage_ai/orchestration/pipeline_scheduler_original.py +32 -8
- 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 +12 -1
- 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 +5 -1
- mage_ai/server/api/triggers.py +3 -1
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +5 -5
- 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-b3502f3f1aa92ac7.js → 1557-25a7d985d5564fd3.js} +1 -1
- 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_base_path_template/_next/static/chunks/3763-61b542dafdbf5754.js → frontend_dist/_next/static/chunks/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/{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_base_path_template/_next/static/chunks/pages/overview-597b74828bf105db.js → frontend_dist/_next/static/chunks/pages/overview-9f1ac4ec003884f3.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-7181b086c93784d2.js → [...slug]-7e737f6fc7e83e9b.js} +1 -1
- 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/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-32985f3f7c7dd3ab.js → frontend_dist/_next/static/chunks/pages/settings/platform/preferences-b603d7fe4b175256.js} +1 -1
- 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/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 +12 -12
- 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 +5 -5
- 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-b3502f3f1aa92ac7.js → 1557-25a7d985d5564fd3.js} +1 -1
- 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/_next/static/chunks/3763-61b542dafdbf5754.js → frontend_dist_base_path_template/_next/static/chunks/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/{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/_next/static/chunks/pages/overview-597b74828bf105db.js → frontend_dist_base_path_template/_next/static/chunks/pages/overview-9f1ac4ec003884f3.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-7181b086c93784d2.js → [...slug]-7e737f6fc7e83e9b.js} +1 -1
- 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/settings/account/{profile-3f0df3decc856ee9.js → profile-3ae43c932537b254.js} +1 -1
- 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
- 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/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 +12 -12
- 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 +9 -0
- mage_ai/server/server.py +35 -31
- 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/k8s/config.py +23 -0
- mage_ai/services/k8s/job_manager.py +6 -1
- 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 +141 -15
- 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/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 +9 -2
- 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 +3 -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 +3 -2
- mage_ai/tests/orchestration/triggers/test_utils.py +3 -2
- mage_ai/tests/services/k8s/test_job_manager.py +18 -0
- 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-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/METADATA +5 -2
- {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/RECORD +513 -417
- mage_ai/data_preparation/models/global_data_product/constants.py +0 -6
- mage_ai/server/frontend_dist/_next/static/RhDiJSkcjCsh4xxX4BFBk/_buildManifest.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-b9b85ba10667e654.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/9832-67896490f6e8a014.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-2a69553d8c6eeb53.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/pipelines/[pipeline]/dashboard-95ffcd3e2b27e567.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-b645a6d13ab9fe3a.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/settings/workspace/preferences-349af617d05f001b.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-60d01d3887e31136.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-3433c8b22e8342aa.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/TdpLLFome13qvM0gXvpHs/_buildManifest.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-b9b85ba10667e654.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/9832-67896490f6e8a014.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-2a69553d8c6eeb53.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/pipelines/[pipeline]/dashboard-95ffcd3e2b27e567.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-b645a6d13ab9fe3a.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/settings/workspace/preferences-349af617d05f001b.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-60d01d3887e31136.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-3433c8b22e8342aa.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/{RhDiJSkcjCsh4xxX4BFBk → UZLabyPgcxtZvp0O0EUUS}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{TdpLLFome13qvM0gXvpHs → kcptwoOU-JJJg6Vwpkfmx}/_ssgManifest.js +0 -0
- /mage_ai/tests/data_preparation/{shared → storage/shared}/test_secrets.py +0 -0
- {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/WHEEL +0 -0
- {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.70.dist-info → mage_ai-0.9.71.dist-info}/top_level.txt +0 -0
|
@@ -11,12 +11,13 @@ 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,
|
|
@@ -103,6 +113,14 @@ class Pipeline:
|
|
|
103
113
|
self.extensions = {}
|
|
104
114
|
self.name = None
|
|
105
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
|
+
|
|
106
124
|
self.repo_path = repo_path or get_repo_path()
|
|
107
125
|
self.retry_config = {}
|
|
108
126
|
self.run_pipeline_in_one_process = False
|
|
@@ -130,17 +148,28 @@ class Pipeline:
|
|
|
130
148
|
# Used for showing the operation history. For example: recently viewed pipelines.
|
|
131
149
|
self.history = []
|
|
132
150
|
|
|
151
|
+
# Path of the pipeline metadata.yaml file
|
|
152
|
+
self._config_path = None
|
|
133
153
|
if config is None:
|
|
134
154
|
self.load_config_from_yaml()
|
|
135
155
|
else:
|
|
136
156
|
self.load_config(config, catalog=catalog)
|
|
137
157
|
|
|
138
|
-
|
|
139
|
-
|
|
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:
|
|
140
165
|
if project_platform_activated() and not use_repo_path:
|
|
141
166
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
142
167
|
|
|
143
|
-
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
|
+
)
|
|
144
173
|
if config_path:
|
|
145
174
|
return config_path
|
|
146
175
|
|
|
@@ -153,14 +182,25 @@ class Pipeline:
|
|
|
153
182
|
|
|
154
183
|
@property
|
|
155
184
|
def config_path(self):
|
|
156
|
-
|
|
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
|
|
157
193
|
|
|
158
194
|
@property
|
|
159
195
|
def catalog_config_path(self):
|
|
160
196
|
if project_platform_activated() and not self.use_repo_path:
|
|
161
197
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
162
198
|
|
|
163
|
-
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
|
+
)
|
|
164
204
|
if config_path:
|
|
165
205
|
return os.path.join(os.path.dirname(config_path), DATA_INTEGRATION_CATALOG_FILE)
|
|
166
206
|
|
|
@@ -198,6 +238,16 @@ class Pipeline:
|
|
|
198
238
|
self.uuid,
|
|
199
239
|
)
|
|
200
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
|
+
|
|
201
251
|
@property
|
|
202
252
|
def remote_variables_dir(self):
|
|
203
253
|
remote_variables_dir = self.repo_config.remote_variables_dir
|
|
@@ -216,18 +266,20 @@ class Pipeline:
|
|
|
216
266
|
|
|
217
267
|
@property
|
|
218
268
|
def all_block_configs(self) -> List[Dict]:
|
|
219
|
-
return
|
|
220
|
-
self.
|
|
221
|
-
self.
|
|
222
|
-
self.
|
|
269
|
+
return (
|
|
270
|
+
self.block_configs
|
|
271
|
+
+ self.conditional_configs
|
|
272
|
+
+ self.callback_configs
|
|
273
|
+
+ self.widget_configs
|
|
274
|
+
)
|
|
223
275
|
|
|
224
276
|
@classmethod
|
|
225
277
|
def create(
|
|
226
278
|
self,
|
|
227
279
|
name: str,
|
|
280
|
+
repo_path: str = None,
|
|
228
281
|
description: str = None,
|
|
229
282
|
pipeline_type: PipelineType = PipelineType.PYTHON,
|
|
230
|
-
repo_path: str = None,
|
|
231
283
|
tags: List[str] = None,
|
|
232
284
|
):
|
|
233
285
|
"""
|
|
@@ -235,6 +287,8 @@ class Pipeline:
|
|
|
235
287
|
2. Create a new yaml file to store pipeline config
|
|
236
288
|
3. Create other files: requirements.txt, __init__.py
|
|
237
289
|
"""
|
|
290
|
+
warn_for_repo_path(repo_path)
|
|
291
|
+
|
|
238
292
|
uuid = clean_name(name)
|
|
239
293
|
pipeline_path = os.path.join(repo_path, PIPELINES_FOLDER, uuid)
|
|
240
294
|
if os.path.exists(pipeline_path):
|
|
@@ -243,14 +297,17 @@ class Pipeline:
|
|
|
243
297
|
copy_template_directory('pipeline', pipeline_path)
|
|
244
298
|
# Update metadata.yaml with pipeline config
|
|
245
299
|
with open(os.path.join(pipeline_path, PIPELINE_CONFIG_FILE), 'w') as fp:
|
|
246
|
-
yaml.dump(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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
|
+
)
|
|
254
311
|
|
|
255
312
|
pipeline = Pipeline(
|
|
256
313
|
uuid,
|
|
@@ -269,10 +326,13 @@ class Pipeline:
|
|
|
269
326
|
zip_size = sum(e.file_size for e in zipf.infolist()) # calc zip size in bytes
|
|
270
327
|
if zip_size / 1000 > PIPELINE_MAX_FILE_SIZE: # prevention against zip-bombs
|
|
271
328
|
raise PipelineZipTooLargeError(
|
|
272
|
-
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
|
+
)
|
|
273
331
|
|
|
274
332
|
# Ignore `__MACOSX` for zips created on macOS systems
|
|
275
|
-
zip_contents = [
|
|
333
|
+
zip_contents = [
|
|
334
|
+
path for path in zipf.namelist() if not path.startswith('__MACOSX')
|
|
335
|
+
]
|
|
276
336
|
# Verify if zip contents are part of a root folder
|
|
277
337
|
prefix = os.path.commonpath(zip_contents)
|
|
278
338
|
|
|
@@ -302,7 +362,9 @@ class Pipeline:
|
|
|
302
362
|
raise FileWriteError(f'Failed to write pipeline file to {destination}.')
|
|
303
363
|
|
|
304
364
|
# return the pipeline configuration file
|
|
305
|
-
config_destination_path = pipeline_files[0][
|
|
365
|
+
config_destination_path = pipeline_files[0][
|
|
366
|
+
1
|
|
367
|
+
] # First item is the pipeline config path
|
|
306
368
|
ret_file = File.from_path(config_destination_path)
|
|
307
369
|
ret_file.filename = new_pipeline_uuid
|
|
308
370
|
|
|
@@ -332,8 +394,10 @@ class Pipeline:
|
|
|
332
394
|
repo_path=source_pipeline.repo_path,
|
|
333
395
|
)
|
|
334
396
|
|
|
335
|
-
if
|
|
336
|
-
|
|
397
|
+
if (
|
|
398
|
+
source_pipeline.type == PipelineType.INTEGRATION
|
|
399
|
+
and source_pipeline.data_integration is not None
|
|
400
|
+
):
|
|
337
401
|
with open(duplicate_pipeline.catalog_config_path, 'w') as fp:
|
|
338
402
|
json.dump(source_pipeline.data_integration, fp)
|
|
339
403
|
|
|
@@ -358,7 +422,7 @@ class Pipeline:
|
|
|
358
422
|
|
|
359
423
|
block_cache = await BlockCache.initialize_cache()
|
|
360
424
|
for block in blocks:
|
|
361
|
-
block_cache.add_pipeline(block, duplicate_pipeline)
|
|
425
|
+
block_cache.add_pipeline(block, duplicate_pipeline, duplicate_pipeline.repo_path)
|
|
362
426
|
|
|
363
427
|
return cls.get(
|
|
364
428
|
duplicate_pipeline_uuid,
|
|
@@ -377,30 +441,46 @@ class Pipeline:
|
|
|
377
441
|
|
|
378
442
|
@classmethod
|
|
379
443
|
def get(
|
|
380
|
-
|
|
444
|
+
cls,
|
|
381
445
|
uuid,
|
|
382
446
|
repo_path: str = None,
|
|
447
|
+
repo_config=None,
|
|
383
448
|
check_if_exists: bool = False,
|
|
384
449
|
all_projects: bool = False,
|
|
450
|
+
context_data: Dict = None,
|
|
385
451
|
use_repo_path: bool = False,
|
|
386
452
|
):
|
|
387
|
-
|
|
388
|
-
IntegrationPipeline,
|
|
389
|
-
)
|
|
453
|
+
warn_for_repo_path(repo_path)
|
|
390
454
|
|
|
391
|
-
config_path, repo_path =
|
|
455
|
+
config_path, repo_path = cls._get_config_path(
|
|
392
456
|
uuid,
|
|
393
457
|
repo_path=repo_path,
|
|
394
458
|
all_projects=all_projects,
|
|
459
|
+
context_data=context_data,
|
|
395
460
|
use_repo_path=use_repo_path,
|
|
396
461
|
)
|
|
397
462
|
|
|
398
|
-
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)):
|
|
399
464
|
return None
|
|
400
465
|
|
|
401
|
-
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
|
+
)
|
|
402
473
|
if PipelineType.INTEGRATION == pipeline.type:
|
|
403
|
-
|
|
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
|
+
)
|
|
404
484
|
|
|
405
485
|
return pipeline
|
|
406
486
|
|
|
@@ -425,7 +505,7 @@ class Pipeline:
|
|
|
425
505
|
return None
|
|
426
506
|
|
|
427
507
|
with open(metadata_path) as fp:
|
|
428
|
-
config =
|
|
508
|
+
config = load_yaml(fp) or {}
|
|
429
509
|
return config
|
|
430
510
|
|
|
431
511
|
@classmethod
|
|
@@ -434,12 +514,17 @@ class Pipeline:
|
|
|
434
514
|
uuid,
|
|
435
515
|
repo_path: str = None,
|
|
436
516
|
all_projects: bool = False,
|
|
517
|
+
context_data: Dict = None,
|
|
437
518
|
use_repo_path: bool = False,
|
|
438
519
|
) -> Tuple[str, str]:
|
|
439
520
|
if all_projects and not use_repo_path and project_platform_activated():
|
|
440
521
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
441
522
|
|
|
442
|
-
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
|
+
)
|
|
443
528
|
else:
|
|
444
529
|
repo_path = repo_path or get_repo_path()
|
|
445
530
|
config_path = os.path.join(
|
|
@@ -479,7 +564,7 @@ class Pipeline:
|
|
|
479
564
|
|
|
480
565
|
config = None
|
|
481
566
|
async with aiofiles.open(config_path, mode='r') as f:
|
|
482
|
-
config =
|
|
567
|
+
config = load_yaml(await f.read()) or {}
|
|
483
568
|
except Exception as e:
|
|
484
569
|
if raise_exception:
|
|
485
570
|
raise e
|
|
@@ -496,16 +581,19 @@ class Pipeline:
|
|
|
496
581
|
uuid,
|
|
497
582
|
repo_path: str = None,
|
|
498
583
|
all_projects: bool = False,
|
|
584
|
+
context_data: Dict = None,
|
|
499
585
|
use_repo_path: bool = False,
|
|
500
586
|
):
|
|
501
|
-
|
|
502
|
-
IntegrationPipeline,
|
|
503
|
-
)
|
|
587
|
+
warn_for_repo_path(repo_path)
|
|
504
588
|
|
|
505
589
|
if all_projects and not use_repo_path and project_platform_activated():
|
|
506
590
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
507
591
|
|
|
508
|
-
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
|
+
)
|
|
509
597
|
else:
|
|
510
598
|
repo_path = repo_path or get_repo_path()
|
|
511
599
|
config_path = os.path.join(
|
|
@@ -515,12 +603,16 @@ class Pipeline:
|
|
|
515
603
|
PIPELINE_CONFIG_FILE,
|
|
516
604
|
)
|
|
517
605
|
|
|
518
|
-
if not os.path.exists(config_path):
|
|
606
|
+
if not config_path or not os.path.exists(config_path):
|
|
519
607
|
raise Exception(f'Pipeline {uuid} does not exist.')
|
|
520
608
|
async with aiofiles.open(config_path, mode='r', encoding='utf-8') as f:
|
|
521
|
-
config =
|
|
609
|
+
config = load_yaml(await f.read()) or {}
|
|
522
610
|
|
|
523
611
|
if PipelineType.INTEGRATION == config.get('type'):
|
|
612
|
+
from mage_ai.data_preparation.models.pipelines.integration_pipeline import (
|
|
613
|
+
IntegrationPipeline,
|
|
614
|
+
)
|
|
615
|
+
|
|
524
616
|
catalog = None
|
|
525
617
|
catalog_config_path = os.path.join(
|
|
526
618
|
repo_path,
|
|
@@ -554,9 +646,15 @@ class Pipeline:
|
|
|
554
646
|
**kwargs,
|
|
555
647
|
) -> Union[List[str], List[Tuple[str, str]]]:
|
|
556
648
|
if project_platform_activated():
|
|
557
|
-
repo_paths = [
|
|
558
|
-
|
|
559
|
-
|
|
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
|
+
]
|
|
560
658
|
|
|
561
659
|
return Pipeline.get_all_pipelines(
|
|
562
660
|
*args,
|
|
@@ -572,6 +670,7 @@ class Pipeline:
|
|
|
572
670
|
repo_paths: List[str] = None,
|
|
573
671
|
disable_pipelines_folder_creation: bool = False,
|
|
574
672
|
include_repo_path: bool = False,
|
|
673
|
+
**kwargs,
|
|
575
674
|
) -> Union[List[str], List[Tuple[str, str]]]:
|
|
576
675
|
arr = []
|
|
577
676
|
|
|
@@ -581,7 +680,7 @@ class Pipeline:
|
|
|
581
680
|
if repo_paths:
|
|
582
681
|
paths.extend(repo_paths)
|
|
583
682
|
|
|
584
|
-
for path in paths:
|
|
683
|
+
for path in set(paths):
|
|
585
684
|
pipelines_folder = os.path.join(path, PIPELINES_FOLDER)
|
|
586
685
|
pipelines_folder_exists = os.path.exists(pipelines_folder)
|
|
587
686
|
if not pipelines_folder_exists and not disable_pipelines_folder_creation:
|
|
@@ -599,7 +698,10 @@ class Pipeline:
|
|
|
599
698
|
return arr
|
|
600
699
|
|
|
601
700
|
@classmethod
|
|
602
|
-
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)
|
|
603
705
|
repo_path = repo_path or get_repo_path()
|
|
604
706
|
pipelines_folder = os.path.join(repo_path, PIPELINES_FOLDER)
|
|
605
707
|
pipelines = []
|
|
@@ -690,6 +792,7 @@ class Pipeline:
|
|
|
690
792
|
from mage_ai.data_preparation.executors.streaming_pipeline_executor import (
|
|
691
793
|
StreamingPipelineExecutor,
|
|
692
794
|
)
|
|
795
|
+
|
|
693
796
|
StreamingPipelineExecutor(self).execute(
|
|
694
797
|
build_block_output_stdout=build_block_output_stdout,
|
|
695
798
|
global_vars=global_vars,
|
|
@@ -721,7 +824,7 @@ class Pipeline:
|
|
|
721
824
|
if not os.path.exists(self.config_path):
|
|
722
825
|
raise Exception(f'Pipeline {self.uuid} does not exist in repo_path {self.repo_path}.')
|
|
723
826
|
with open(self.config_path, encoding='utf-8') as fp:
|
|
724
|
-
config =
|
|
827
|
+
config = load_yaml(fp) or {}
|
|
725
828
|
return config
|
|
726
829
|
|
|
727
830
|
def get_catalog_from_json(self):
|
|
@@ -790,7 +893,9 @@ class Pipeline:
|
|
|
790
893
|
|
|
791
894
|
language = c.get('language')
|
|
792
895
|
|
|
793
|
-
return BlockFactory.block_class_from_type(
|
|
896
|
+
return BlockFactory.block_class_from_type(
|
|
897
|
+
block_type, language=language, pipeline=self
|
|
898
|
+
)(
|
|
794
899
|
c.get('name'),
|
|
795
900
|
c.get('uuid'),
|
|
796
901
|
block_type,
|
|
@@ -839,17 +944,28 @@ class Pipeline:
|
|
|
839
944
|
|
|
840
945
|
for extension_uuid, extension_config in config.get('extensions', {}).items():
|
|
841
946
|
extension_configs = extension_config.get('blocks') or []
|
|
842
|
-
extension_blocks = [
|
|
843
|
-
|
|
844
|
-
|
|
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
|
+
]
|
|
845
958
|
|
|
846
|
-
self.extensions[extension_uuid] = merge_dict(
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
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
|
+
),
|
|
851
967
|
),
|
|
852
|
-
)
|
|
968
|
+
)
|
|
853
969
|
|
|
854
970
|
blocks_with_callbacks = {}
|
|
855
971
|
for callback_block in self.callbacks_by_uuid.values():
|
|
@@ -883,11 +999,13 @@ class Pipeline:
|
|
|
883
999
|
for b in configs:
|
|
884
1000
|
block = blocks_by_uuid[b['uuid']]
|
|
885
1001
|
block.downstream_blocks = [
|
|
886
|
-
all_blocks_by_uuid[uuid]
|
|
1002
|
+
all_blocks_by_uuid[uuid]
|
|
1003
|
+
for uuid in b.get('downstream_blocks', [])
|
|
887
1004
|
if uuid in all_blocks_by_uuid
|
|
888
1005
|
]
|
|
889
1006
|
block.upstream_blocks = [
|
|
890
|
-
all_blocks_by_uuid[uuid]
|
|
1007
|
+
all_blocks_by_uuid[uuid]
|
|
1008
|
+
for uuid in b.get('upstream_blocks', [])
|
|
891
1009
|
if uuid in all_blocks_by_uuid
|
|
892
1010
|
]
|
|
893
1011
|
|
|
@@ -941,7 +1059,9 @@ class Pipeline:
|
|
|
941
1059
|
|
|
942
1060
|
blocks_data = [b.to_dict(**shared_kwargs) for b in self.blocks_by_uuid.values()]
|
|
943
1061
|
callbacks_data = [b.to_dict(**shared_kwargs) for b in self.callbacks_by_uuid.values()]
|
|
944
|
-
conditionals_data = [
|
|
1062
|
+
conditionals_data = [
|
|
1063
|
+
b.to_dict(**shared_kwargs) for b in self.conditionals_by_uuid.values()
|
|
1064
|
+
]
|
|
945
1065
|
widgets_data = [b.to_dict(**shared_kwargs) for b in self.widgets_by_uuid.values()]
|
|
946
1066
|
|
|
947
1067
|
data = dict(
|
|
@@ -962,13 +1082,17 @@ class Pipeline:
|
|
|
962
1082
|
include_outputs=include_outputs,
|
|
963
1083
|
include_outputs_spark=include_outputs_spark,
|
|
964
1084
|
sample_count=sample_count,
|
|
965
|
-
|
|
1085
|
+
)
|
|
1086
|
+
for b in extension['blocks_by_uuid'].values()
|
|
966
1087
|
]
|
|
967
1088
|
extensions_data[extension_uuid] = merge_dict(
|
|
968
|
-
ignore_keys(
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1089
|
+
ignore_keys(
|
|
1090
|
+
extension,
|
|
1091
|
+
[
|
|
1092
|
+
'blocks',
|
|
1093
|
+
'blocks_by_uuid',
|
|
1094
|
+
],
|
|
1095
|
+
),
|
|
972
1096
|
dict(
|
|
973
1097
|
blocks=blocks,
|
|
974
1098
|
),
|
|
@@ -992,7 +1116,10 @@ class Pipeline:
|
|
|
992
1116
|
include_extensions: bool = False,
|
|
993
1117
|
include_outputs: bool = False,
|
|
994
1118
|
include_outputs_spark: bool = False,
|
|
995
|
-
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,
|
|
996
1123
|
):
|
|
997
1124
|
shared_kwargs = dict(
|
|
998
1125
|
check_if_file_exists=True,
|
|
@@ -1006,26 +1133,36 @@ class Pipeline:
|
|
|
1006
1133
|
)
|
|
1007
1134
|
if include_block_pipelines:
|
|
1008
1135
|
shared_kwargs['block_cache'] = BlockCache()
|
|
1009
|
-
blocks_data = await asyncio.gather(
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
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(
|
|
1024
1160
|
include_content=include_content,
|
|
1025
1161
|
include_outputs=include_outputs,
|
|
1026
1162
|
sample_count=sample_count,
|
|
1027
|
-
|
|
1028
|
-
|
|
1163
|
+
)
|
|
1164
|
+
for b in self.widgets_by_uuid.values()
|
|
1165
|
+
])
|
|
1029
1166
|
data = dict(
|
|
1030
1167
|
blocks=blocks_data,
|
|
1031
1168
|
callbacks=callbacks_data,
|
|
@@ -1038,18 +1175,22 @@ class Pipeline:
|
|
|
1038
1175
|
for extension_uuid, extension in self.extensions.items():
|
|
1039
1176
|
blocks = []
|
|
1040
1177
|
if 'blocks_by_uuid' in extension:
|
|
1041
|
-
blocks = await asyncio.gather(
|
|
1042
|
-
|
|
1178
|
+
blocks = await asyncio.gather(*[
|
|
1179
|
+
b.to_dict_async(
|
|
1043
1180
|
include_content=include_content,
|
|
1044
1181
|
include_outputs=include_outputs,
|
|
1045
1182
|
sample_count=sample_count,
|
|
1046
|
-
|
|
1047
|
-
|
|
1183
|
+
)
|
|
1184
|
+
for b in extension['blocks_by_uuid'].values()
|
|
1185
|
+
])
|
|
1048
1186
|
extensions_data[extension_uuid] = merge_dict(
|
|
1049
|
-
ignore_keys(
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1187
|
+
ignore_keys(
|
|
1188
|
+
extension,
|
|
1189
|
+
[
|
|
1190
|
+
'blocks',
|
|
1191
|
+
'blocks_by_uuid',
|
|
1192
|
+
],
|
|
1193
|
+
),
|
|
1053
1194
|
dict(
|
|
1054
1195
|
blocks=blocks,
|
|
1055
1196
|
),
|
|
@@ -1087,6 +1228,8 @@ class Pipeline:
|
|
|
1087
1228
|
self.uuid = new_uuid
|
|
1088
1229
|
new_pipeline_path = self.dir_path
|
|
1089
1230
|
os.rename(old_pipeline_path, new_pipeline_path)
|
|
1231
|
+
# Force updating the config path
|
|
1232
|
+
self._config_path = None
|
|
1090
1233
|
await self.save_async()
|
|
1091
1234
|
transfer_related_models_for_pipeline(old_uuid, new_uuid)
|
|
1092
1235
|
|
|
@@ -1100,7 +1243,7 @@ class Pipeline:
|
|
|
1100
1243
|
should_update_tag_cache = True
|
|
1101
1244
|
|
|
1102
1245
|
cache = PipelineCache()
|
|
1103
|
-
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)
|
|
1104
1247
|
|
|
1105
1248
|
should_save = False
|
|
1106
1249
|
|
|
@@ -1108,11 +1251,12 @@ class Pipeline:
|
|
|
1108
1251
|
for extension_uuid, extension in data['extensions'].items():
|
|
1109
1252
|
if extension_uuid not in self.extensions:
|
|
1110
1253
|
self.extensions[extension_uuid] = {}
|
|
1111
|
-
self.extensions[extension_uuid]
|
|
1112
|
-
self.extensions[extension_uuid]
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
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
|
|
1116
1260
|
|
|
1117
1261
|
if 'tags' in data:
|
|
1118
1262
|
new_tags = data.get('tags', [])
|
|
@@ -1138,16 +1282,17 @@ class Pipeline:
|
|
|
1138
1282
|
|
|
1139
1283
|
for key in [
|
|
1140
1284
|
'cache_block_output_in_memory',
|
|
1285
|
+
'concurrency_config',
|
|
1141
1286
|
'data_integration',
|
|
1142
1287
|
'executor_type',
|
|
1143
1288
|
'retry_config',
|
|
1144
1289
|
'run_pipeline_in_one_process',
|
|
1145
1290
|
]:
|
|
1146
|
-
if key in data:
|
|
1291
|
+
if key in data and data.get(key) != getattr(self, key):
|
|
1147
1292
|
setattr(self, key, data.get(key))
|
|
1148
1293
|
should_save = True
|
|
1149
1294
|
|
|
1150
|
-
if 'settings' in data:
|
|
1295
|
+
if 'settings' in data and data.get('settings') != self.settings.to_dict():
|
|
1151
1296
|
self.settings = PipelineSettings.load(**(data.get('settings') or {}))
|
|
1152
1297
|
should_save = True
|
|
1153
1298
|
|
|
@@ -1225,7 +1370,7 @@ class Pipeline:
|
|
|
1225
1370
|
)
|
|
1226
1371
|
|
|
1227
1372
|
if hooks:
|
|
1228
|
-
for hook in
|
|
1373
|
+
for hook in hooks or []:
|
|
1229
1374
|
output = hook.output
|
|
1230
1375
|
if not output:
|
|
1231
1376
|
continue
|
|
@@ -1243,25 +1388,31 @@ class Pipeline:
|
|
|
1243
1388
|
old_block_content = await block.content_async()
|
|
1244
1389
|
if block_data['content'] != old_block_content:
|
|
1245
1390
|
if cache_block_action_object is None:
|
|
1246
|
-
cache_block_action_object =
|
|
1391
|
+
cache_block_action_object = (
|
|
1247
1392
|
await BlockActionObjectCache.initialize_cache()
|
|
1393
|
+
)
|
|
1248
1394
|
|
|
1249
1395
|
await block.update_content_async(block_data['content'], widget=widget)
|
|
1250
1396
|
|
|
1251
1397
|
cache_block_action_object.update_block(block)
|
|
1252
1398
|
|
|
1253
|
-
if 'callback_content' in block_data
|
|
1254
|
-
and block.callback_block:
|
|
1399
|
+
if 'callback_content' in block_data and block.callback_block:
|
|
1255
1400
|
await block.callback_block.update_content_async(
|
|
1256
1401
|
block_data['callback_content'],
|
|
1257
1402
|
widget=widget,
|
|
1258
1403
|
)
|
|
1259
|
-
if
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
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
|
+
)
|
|
1265
1416
|
|
|
1266
1417
|
name = block_data.get('name')
|
|
1267
1418
|
|
|
@@ -1273,7 +1424,7 @@ class Pipeline:
|
|
|
1273
1424
|
block.update(extract(block_data, ['color']))
|
|
1274
1425
|
|
|
1275
1426
|
configuration = block_data.get('configuration')
|
|
1276
|
-
if configuration:
|
|
1427
|
+
if configuration and configuration != block.configuration:
|
|
1277
1428
|
block.configuration = configuration
|
|
1278
1429
|
should_save_async = should_save_async or True
|
|
1279
1430
|
|
|
@@ -1283,42 +1434,50 @@ class Pipeline:
|
|
|
1283
1434
|
if name and name != block.name:
|
|
1284
1435
|
keys_to_update.append('name')
|
|
1285
1436
|
|
|
1286
|
-
|
|
1437
|
+
upstream_blocks = block_data.get('upstream_blocks') or []
|
|
1438
|
+
if upstream_blocks != block.upstream_block_uuids:
|
|
1287
1439
|
keys_to_update.append('upstream_blocks')
|
|
1288
1440
|
block_data['upstream_blocks'] = [
|
|
1289
|
-
block_uuid_mapping.get(b, b)
|
|
1290
|
-
for b in block_data['upstream_blocks']
|
|
1441
|
+
block_uuid_mapping.get(b, b) for b in block_data['upstream_blocks']
|
|
1291
1442
|
]
|
|
1292
|
-
|
|
1293
1443
|
if len(keys_to_update) >= 1:
|
|
1294
1444
|
block.update(extract(block_data, keys_to_update))
|
|
1445
|
+
should_save_async = should_save_async or True
|
|
1295
1446
|
|
|
1296
|
-
should_save_async = should_save_async or True
|
|
1297
1447
|
elif name and name != block.name:
|
|
1298
1448
|
from mage_ai.cache.block_action_object import (
|
|
1299
1449
|
BlockActionObjectCache,
|
|
1300
1450
|
)
|
|
1301
1451
|
|
|
1302
1452
|
if cache_block_action_object is None:
|
|
1303
|
-
cache_block_action_object =
|
|
1453
|
+
cache_block_action_object = (
|
|
1304
1454
|
await BlockActionObjectCache.initialize_cache()
|
|
1455
|
+
)
|
|
1305
1456
|
cache_block_action_object.update_block(block, remove=True)
|
|
1306
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
|
+
|
|
1307
1470
|
block_update_payload = extract(block_data, ['name'])
|
|
1308
|
-
configuration = copy.deepcopy(block_data).get('configuration', {})
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
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
|
+
|
|
1317
1479
|
blocks_to_remove_from_cache.append(block.to_dict())
|
|
1318
|
-
block.update(
|
|
1319
|
-
block_update_payload,
|
|
1320
|
-
detach=block_data.get('detach', False)
|
|
1321
|
-
)
|
|
1480
|
+
block.update(block_update_payload, detach=block_data.get('detach', False))
|
|
1322
1481
|
|
|
1323
1482
|
block_uuids_to_add_to_cache.append(block.uuid)
|
|
1324
1483
|
cache_block_action_object.update_block(block)
|
|
@@ -1336,9 +1495,9 @@ class Pipeline:
|
|
|
1336
1495
|
# we need to update mage_sources.yml
|
|
1337
1496
|
if any(
|
|
1338
1497
|
(
|
|
1339
|
-
BlockType.DBT != block.type
|
|
1340
|
-
block.language in [BlockLanguage.SQL, BlockLanguage.PYTHON, BlockLanguage.R]
|
|
1341
|
-
any(
|
|
1498
|
+
BlockType.DBT != block.type
|
|
1499
|
+
and block.language in [BlockLanguage.SQL, BlockLanguage.PYTHON, BlockLanguage.R]
|
|
1500
|
+
and any(
|
|
1342
1501
|
BlockType.DBT == downstream_block.type
|
|
1343
1502
|
for downstream_block in block.downstream_blocks
|
|
1344
1503
|
)
|
|
@@ -1371,7 +1530,7 @@ class Pipeline:
|
|
|
1371
1530
|
old_uuid,
|
|
1372
1531
|
self.repo_path,
|
|
1373
1532
|
)
|
|
1374
|
-
cache.update_pipeline(block.to_dict(), self)
|
|
1533
|
+
cache.update_pipeline(block.to_dict(), self, self.repo_path)
|
|
1375
1534
|
|
|
1376
1535
|
if should_update_tag_cache:
|
|
1377
1536
|
from mage_ai.cache.tag import TagCache
|
|
@@ -1453,8 +1612,7 @@ class Pipeline:
|
|
|
1453
1612
|
|
|
1454
1613
|
files_to_be_written = []
|
|
1455
1614
|
with open(config_zip_path, 'r') as pipeline_config:
|
|
1456
|
-
|
|
1457
|
-
config = yaml.safe_load(pipeline_config)
|
|
1615
|
+
config = load_yaml(pipeline_config)
|
|
1458
1616
|
|
|
1459
1617
|
# check if pipeline exists with same uuid and generate new one if necessary
|
|
1460
1618
|
if not overwrite:
|
|
@@ -1564,8 +1722,10 @@ class Pipeline:
|
|
|
1564
1722
|
|
|
1565
1723
|
if block_uuid in self.blocks_by_uuid:
|
|
1566
1724
|
block = self.blocks_by_uuid[block_uuid]
|
|
1567
|
-
if
|
|
1568
|
-
|
|
1725
|
+
if (
|
|
1726
|
+
upstream_blocks_reordered is not None
|
|
1727
|
+
and upstream_blocks != upstream_blocks_reordered
|
|
1728
|
+
):
|
|
1569
1729
|
block.update(
|
|
1570
1730
|
dict(upstream_blocks=upstream_blocks_reordered),
|
|
1571
1731
|
check_upstream_block_order=True,
|
|
@@ -1613,7 +1773,8 @@ class Pipeline:
|
|
|
1613
1773
|
all_block_uuids = {b.get('uuid') for b in self.all_block_configs}
|
|
1614
1774
|
if block.uuid in all_block_uuids:
|
|
1615
1775
|
raise InvalidPipelineError(
|
|
1616
|
-
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
|
+
)
|
|
1617
1778
|
|
|
1618
1779
|
if widget:
|
|
1619
1780
|
self.widgets_by_uuid = self.__add_block_to_mapping(
|
|
@@ -1666,9 +1827,8 @@ class Pipeline:
|
|
|
1666
1827
|
|
|
1667
1828
|
self.update_block(
|
|
1668
1829
|
downstream_block,
|
|
1669
|
-
upstream_block_uuids=(
|
|
1670
|
-
|
|
1671
|
-
) + [block.uuid],
|
|
1830
|
+
upstream_block_uuids=(downstream_block.upstream_block_uuids or [])
|
|
1831
|
+
+ [block.uuid],
|
|
1672
1832
|
)
|
|
1673
1833
|
|
|
1674
1834
|
self.validate('A cycle was formed while adding a block')
|
|
@@ -1728,9 +1888,13 @@ class Pipeline:
|
|
|
1728
1888
|
sample_count: int = None,
|
|
1729
1889
|
dynamic_block_index: int = None,
|
|
1730
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,
|
|
1731
1896
|
):
|
|
1732
1897
|
block = self.get_block(block_uuid)
|
|
1733
|
-
|
|
1734
1898
|
data_integration_settings = block.get_data_integration_settings(
|
|
1735
1899
|
from_notebook=from_notebook,
|
|
1736
1900
|
global_vars=global_vars,
|
|
@@ -1758,6 +1922,11 @@ class Pipeline:
|
|
|
1758
1922
|
variable_uuid=variable_name,
|
|
1759
1923
|
dynamic_block_index=dynamic_block_index,
|
|
1760
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,
|
|
1761
1930
|
)
|
|
1762
1931
|
|
|
1763
1932
|
return variable
|
|
@@ -1779,10 +1948,12 @@ class Pipeline:
|
|
|
1779
1948
|
|
|
1780
1949
|
def has_block(self, block_uuid: str, block_type: str = None, extension_uuid: str = None):
|
|
1781
1950
|
if extension_uuid:
|
|
1782
|
-
return
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
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
|
+
)
|
|
1786
1957
|
elif BlockType.CALLBACK == block_type:
|
|
1787
1958
|
return block_uuid in self.callbacks_by_uuid
|
|
1788
1959
|
elif BlockType.CONDITIONAL == block_type:
|
|
@@ -1810,9 +1981,9 @@ class Pipeline:
|
|
|
1810
1981
|
if upstream_block_uuids is not None:
|
|
1811
1982
|
curr_upstream_block_uuids = set(block.upstream_block_uuids)
|
|
1812
1983
|
new_upstream_block_uuids = set(upstream_block_uuids)
|
|
1813
|
-
if curr_upstream_block_uuids != new_upstream_block_uuids or
|
|
1814
|
-
|
|
1815
|
-
|
|
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
|
+
):
|
|
1816
1987
|
# Only set upstream block’s downstream to the current block if current block
|
|
1817
1988
|
# is not an extension block and not a callback/conditional block
|
|
1818
1989
|
if not is_extension and not is_callback and not is_conditional:
|
|
@@ -1871,9 +2042,9 @@ class Pipeline:
|
|
|
1871
2042
|
# conditional_blocks field.
|
|
1872
2043
|
block.update_conditional_blocks(conditional_blocks)
|
|
1873
2044
|
elif downstream_block_uuids is not None:
|
|
1874
|
-
block_uuids_to_remove =
|
|
1875
|
-
|
|
1876
|
-
|
|
2045
|
+
block_uuids_to_remove = [
|
|
2046
|
+
uuid for uuid in block.downstream_block_uuids if uuid not in downstream_block_uuids
|
|
2047
|
+
]
|
|
1877
2048
|
|
|
1878
2049
|
for block_uuid in block_uuids_to_remove:
|
|
1879
2050
|
block_inner = self.get_block(block_uuid)
|
|
@@ -1881,10 +2052,12 @@ class Pipeline:
|
|
|
1881
2052
|
continue
|
|
1882
2053
|
block_inner.update(
|
|
1883
2054
|
dict(
|
|
1884
|
-
upstream_blocks=list(
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
2055
|
+
upstream_blocks=list(
|
|
2056
|
+
filter(
|
|
2057
|
+
lambda x, uuid=block.uuid: x != uuid,
|
|
2058
|
+
block_inner.upstream_block_uuids or [],
|
|
2059
|
+
)
|
|
2060
|
+
),
|
|
1888
2061
|
),
|
|
1889
2062
|
check_upstream_block_order=check_upstream_block_order,
|
|
1890
2063
|
)
|
|
@@ -1992,7 +2165,8 @@ class Pipeline:
|
|
|
1992
2165
|
def update_global_variable(self, key, value):
|
|
1993
2166
|
if not is_yaml_serializable(key, value):
|
|
1994
2167
|
raise SerializationError(
|
|
1995
|
-
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
|
+
)
|
|
1996
2170
|
if self.variables is None:
|
|
1997
2171
|
self.variables = {}
|
|
1998
2172
|
self.variables[key] = value
|
|
@@ -2055,13 +2229,20 @@ class Pipeline:
|
|
|
2055
2229
|
]
|
|
2056
2230
|
if self.type == PipelineType.INTEGRATION or force:
|
|
2057
2231
|
for downstream_block in block.downstream_blocks:
|
|
2058
|
-
upstream_block_uuids = list(
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
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
|
+
)
|
|
2065
2246
|
elif len(downstream_block_uuids) > 0:
|
|
2066
2247
|
raise HasDownstreamDependencies(
|
|
2067
2248
|
f'Block(s) {downstream_block_uuids} are depending on block {block.uuid}'
|
|
@@ -2111,7 +2292,7 @@ class Pipeline:
|
|
|
2111
2292
|
blocks_current = sorted([b.uuid for b in self.blocks_by_uuid.values()])
|
|
2112
2293
|
|
|
2113
2294
|
if block_uuid is not None:
|
|
2114
|
-
current_pipeline = Pipeline(self.uuid, self.repo_path)
|
|
2295
|
+
current_pipeline = Pipeline(self.uuid, repo_path=self.repo_path)
|
|
2115
2296
|
block = self.get_block(
|
|
2116
2297
|
block_uuid,
|
|
2117
2298
|
block_type=block_type,
|
|
@@ -2167,18 +2348,21 @@ class Pipeline:
|
|
|
2167
2348
|
def should_save_trigger_in_code_automatically(self) -> bool:
|
|
2168
2349
|
from mage_ai.data_preparation.models.project import Project
|
|
2169
2350
|
|
|
2170
|
-
if
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2351
|
+
if (
|
|
2352
|
+
self.settings
|
|
2353
|
+
and self.settings.triggers
|
|
2354
|
+
and self.settings.triggers.save_in_code_automatically is not None
|
|
2355
|
+
):
|
|
2174
2356
|
return self.settings.triggers.save_in_code_automatically
|
|
2175
2357
|
|
|
2176
|
-
project = Project(self.repo_config)
|
|
2358
|
+
project = Project(repo_config=self.repo_config)
|
|
2177
2359
|
|
|
2178
|
-
return
|
|
2179
|
-
project.pipelines
|
|
2180
|
-
project.pipelines.settings
|
|
2181
|
-
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
|
+
)
|
|
2182
2366
|
|
|
2183
2367
|
async def save_async(
|
|
2184
2368
|
self,
|
|
@@ -2235,7 +2419,7 @@ class Pipeline:
|
|
|
2235
2419
|
success = True
|
|
2236
2420
|
with open(test_path, mode='r', encoding='utf-8') as fp:
|
|
2237
2421
|
try:
|
|
2238
|
-
|
|
2422
|
+
load_yaml(fp)
|
|
2239
2423
|
except yaml.scanner.ScannerError:
|
|
2240
2424
|
success = False
|
|
2241
2425
|
|
|
@@ -2285,7 +2469,7 @@ class Pipeline:
|
|
|
2285
2469
|
index += 1
|
|
2286
2470
|
|
|
2287
2471
|
cycle = [frame.uuid for frame in virtual_stack[index:]]
|
|
2288
|
-
return
|
|
2472
|
+
return ' --> '.join(cycle)
|
|
2289
2473
|
|
|
2290
2474
|
def __check_cycle(block: Block):
|
|
2291
2475
|
virtual_stack = [StackFrame(block)]
|
|
@@ -2316,7 +2500,8 @@ class Pipeline:
|
|
|
2316
2500
|
uuid = config.get('uuid')
|
|
2317
2501
|
if uuid in check_block_uuids:
|
|
2318
2502
|
raise InvalidPipelineError(
|
|
2319
|
-
f'Pipeline is invalid: duplicate blocks with uuid {uuid}'
|
|
2503
|
+
f'Pipeline is invalid: duplicate blocks with uuid {uuid}'
|
|
2504
|
+
)
|
|
2320
2505
|
check_block_uuids.add(uuid)
|
|
2321
2506
|
|
|
2322
2507
|
|