mage-ai 0.9.66__py3-none-any.whl → 0.9.68__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/api/monitors/BaseMonitor.py +1 -2
- mage_ai/api/policies/PipelinePolicy.py +2 -0
- mage_ai/api/resources/BlockLayoutItemResource.py +2 -2
- mage_ai/api/resources/BlockResource.py +4 -3
- mage_ai/api/resources/CacheItemResource.py +1 -1
- mage_ai/api/resources/GitBranchResource.py +3 -5
- mage_ai/api/resources/PageBlockLayoutResource.py +2 -2
- mage_ai/api/resources/PipelineResource.py +13 -0
- mage_ai/api/resources/PipelineRunResource.py +10 -1
- mage_ai/cache/tag.py +3 -0
- mage_ai/cluster_manager/manage.py +4 -1
- mage_ai/data_preparation/decorators.py +15 -0
- mage_ai/data_preparation/executors/k8s_block_executor.py +8 -1
- mage_ai/data_preparation/executors/k8s_pipeline_executor.py +12 -1
- mage_ai/data_preparation/executors/streaming_pipeline_executor.py +22 -12
- mage_ai/data_preparation/git/api.py +3 -0
- mage_ai/data_preparation/git/clients/gitlab.py +3 -2
- mage_ai/data_preparation/logging/gcs_logger_manager.py +7 -4
- mage_ai/data_preparation/models/block/__init__.py +45 -86
- mage_ai/data_preparation/models/block/block_factory.py +77 -0
- mage_ai/data_preparation/models/block/dbt/block.py +5 -7
- mage_ai/data_preparation/models/block/global_data_product/__init__.py +9 -3
- mage_ai/data_preparation/models/block/integration/__init__.py +12 -8
- mage_ai/data_preparation/models/block/platform/mixins.py +1 -1
- mage_ai/data_preparation/models/pipeline.py +80 -13
- mage_ai/data_preparation/storage/gcs_storage.py +28 -3
- mage_ai/data_preparation/storage/local_storage.py +18 -3
- mage_ai/data_preparation/storage/s3_storage.py +7 -2
- mage_ai/data_preparation/templates/constants.py +7 -0
- mage_ai/data_preparation/templates/data_loaders/streaming/generic_python.py +23 -0
- mage_ai/data_preparation/templates/template.py +6 -2
- mage_ai/data_preparation/variable_manager.py +2 -1
- mage_ai/io/bigquery.py +2 -0
- mage_ai/io/export_utils.py +3 -0
- mage_ai/io/oracledb.py +152 -5
- mage_ai/io/sql.py +4 -0
- mage_ai/orchestration/db/__init__.py +2 -2
- mage_ai/orchestration/db/models/schedules.py +2 -2
- mage_ai/orchestration/job_manager.py +6 -1
- mage_ai/orchestration/notification/sender.py +8 -0
- mage_ai/orchestration/pipeline_scheduler_original.py +10 -1
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +2 -2
- mage_ai/server/frontend_dist/_next/static/chunks/3548-961ff79ca70038c7.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{4241-ccd0126f5750cc35.js → 4241-4499461184ba0d23.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5627-237a3de578538022.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{7966-5c1786fb7e7a48f5.js → 7966-f07b2913f7326b50.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-08790743315de36a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/index-13760bb72d823b69.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/[user]-8bbfa0c19b5e4cb3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-852d403c7bda21b3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-597b74828bf105db.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a8b61d8d239fd16f.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-bd0aff5a5ed8888c.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-3f5c14076ddde20e.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1417ad1c821d720a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-d1ee961387c58b7f.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-90abafc7ed61c582.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-cb88fd075a357fcf.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-ceb06e1616ee9610.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-8ff16ef9566e911a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-d7a8bc51bb7a1082.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/sign-in-f59d34429fe022ee.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-9cba3211434a8966.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/wxqkF4diPqRxUfP6Ac6ai → frontend_dist/_next/static/i8pymuJDTVHdWjUP1QSh1}/_buildManifest.js +1 -1
- mage_ai/server/frontend_dist/block-layout.html +2 -2
- mage_ai/server/frontend_dist/compute.html +2 -2
- mage_ai/server/frontend_dist/files.html +2 -2
- mage_ai/server/frontend_dist/global-data-products/[...slug].html +2 -2
- mage_ai/server/frontend_dist/global-data-products.html +2 -2
- mage_ai/server/frontend_dist/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist/global-hooks.html +2 -2
- mage_ai/server/frontend_dist/index.html +2 -2
- mage_ai/server/frontend_dist/manage/files.html +2 -2
- mage_ai/server/frontend_dist/manage/settings.html +2 -2
- mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
- mage_ai/server/frontend_dist/manage/users/new.html +2 -2
- mage_ai/server/frontend_dist/manage/users.html +2 -2
- mage_ai/server/frontend_dist/manage.html +2 -2
- mage_ai/server/frontend_dist/oauth.html +3 -3
- mage_ai/server/frontend_dist/overview.html +2 -2
- mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist/pipelines.html +2 -2
- mage_ai/server/frontend_dist/platform/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist/platform/global-hooks.html +2 -2
- mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist/settings/platform/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/platform/settings.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/permissions.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/roles.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
- mage_ai/server/frontend_dist/settings.html +2 -2
- mage_ai/server/frontend_dist/sign-in.html +5 -5
- mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
- mage_ai/server/frontend_dist/templates.html +2 -2
- mage_ai/server/frontend_dist/terminal.html +2 -2
- mage_ai/server/frontend_dist/test.html +2 -2
- mage_ai/server/frontend_dist/triggers.html +2 -2
- mage_ai/server/frontend_dist/version-control.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
- mage_ai/server/{frontend_dist/_next/static/rtugsJoijF2SsCCB5_yKS → frontend_dist_base_path_template/_next/static/CKCvjsYCf2imD2X8zAOBf}/_buildManifest.js +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3548-961ff79ca70038c7.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{4241-ccd0126f5750cc35.js → 4241-4499461184ba0d23.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5627-237a3de578538022.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{7966-5c1786fb7e7a48f5.js → 7966-f07b2913f7326b50.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-08790743315de36a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/index-13760bb72d823b69.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/[user]-8bbfa0c19b5e4cb3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-852d403c7bda21b3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-597b74828bf105db.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a8b61d8d239fd16f.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-bd0aff5a5ed8888c.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-3f5c14076ddde20e.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1417ad1c821d720a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-d1ee961387c58b7f.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-90abafc7ed61c582.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-cb88fd075a357fcf.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-ceb06e1616ee9610.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-8ff16ef9566e911a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-d7a8bc51bb7a1082.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-f59d34429fe022ee.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-9cba3211434a8966.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/compute.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/files.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-data-products.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/global-hooks.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/files.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage/users.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/manage.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/oauth.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/overview.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/pipelines.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/sign-in.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +2 -2
- mage_ai/server/frontend_dist_base_path_template/templates.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/terminal.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/test.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/triggers.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/version-control.html +2 -2
- mage_ai/services/aws/s3/s3.py +8 -2
- mage_ai/services/k8s/job_manager.py +8 -0
- mage_ai/services/slack/slack.py +10 -1
- mage_ai/services/spark/spark.py +9 -2
- mage_ai/settings/backends.py +8 -8
- mage_ai/settings/models/configuration_option.py +10 -9
- mage_ai/settings/server.py +6 -1
- mage_ai/shared/files.py +19 -1
- mage_ai/shared/logger.py +12 -6
- mage_ai/shared/path_fixer.py +3 -0
- mage_ai/streaming/sources/base.py +5 -0
- mage_ai/streaming/sources/base_python.py +30 -0
- mage_ai/streaming/sources/kafka.py +2 -1
- mage_ai/streaming/sources/mongodb.py +4 -0
- mage_ai/streaming/sources/source_factory.py +25 -0
- mage_ai/tests/data_preparation/models/block/dbt/test_block.py +2 -2
- mage_ai/tests/data_preparation/models/block/dbt/test_block_sql.py +1 -1
- mage_ai/tests/data_preparation/models/block/dbt/test_block_yaml.py +1 -1
- mage_ai/tests/data_preparation/models/test_block.py +41 -3
- mage_ai/tests/orchestration/test_pipeline_scheduler.py +2 -0
- mage_ai/tests/settings/models/test_configuration_option.py +2 -2
- {mage_ai-0.9.66.dist-info → mage_ai-0.9.68.dist-info}/METADATA +3 -3
- {mage_ai-0.9.66.dist-info → mage_ai-0.9.68.dist-info}/RECORD +225 -222
- mage_ai/server/frontend_dist/_next/static/chunks/181-e61915415a976861.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3548-13563a1ff815f922.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-913116aa749f7ca6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/index-64851458dde54ad9.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/[user]-d3a5fd3119fdb1e4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-42789d698d28a92f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-d05040edba41b2ac.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-aaf393c86fc1bda3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-d84556cefbe31a1a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-cf656cbe37ecaacc.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1b688d61f8efe07a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-ed3331d22d5cff7d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-d94e48bad89ba1e0.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-f508c2f261297724.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-f99e99aa8f45529c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-6826000cdffc36b8.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-dde29a463495cebb.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/sign-in-7d38b2f7c3e918a1.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-ab98a7b3a678669e.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/181-e61915415a976861.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3548-13563a1ff815f922.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-913116aa749f7ca6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/index-64851458dde54ad9.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/[user]-d3a5fd3119fdb1e4.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-42789d698d28a92f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-d05040edba41b2ac.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-aaf393c86fc1bda3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-d84556cefbe31a1a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-cf656cbe37ecaacc.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-1b688d61f8efe07a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-ed3331d22d5cff7d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-d94e48bad89ba1e0.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-f508c2f261297724.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-f99e99aa8f45529c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-6826000cdffc36b8.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-dde29a463495cebb.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-7d38b2f7c3e918a1.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-ab98a7b3a678669e.js +0 -1
- /mage_ai/server/frontend_dist/_next/static/{rtugsJoijF2SsCCB5_yKS → i8pymuJDTVHdWjUP1QSh1}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{wxqkF4diPqRxUfP6Ac6ai → CKCvjsYCf2imD2X8zAOBf}/_ssgManifest.js +0 -0
- {mage_ai-0.9.66.dist-info → mage_ai-0.9.68.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.66.dist-info → mage_ai-0.9.68.dist-info}/WHEEL +0 -0
- {mage_ai-0.9.66.dist-info → mage_ai-0.9.68.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.66.dist-info → mage_ai-0.9.68.dist-info}/top_level.txt +0 -0
|
@@ -90,7 +90,7 @@ from mage_ai.data_preparation.templates.data_integrations.utils import get_templ
|
|
|
90
90
|
from mage_ai.data_preparation.templates.template import load_template
|
|
91
91
|
from mage_ai.server.kernel_output_parser import DataType
|
|
92
92
|
from mage_ai.services.spark.config import SparkConfig
|
|
93
|
-
from mage_ai.services.spark.spark import get_spark_session
|
|
93
|
+
from mage_ai.services.spark.spark import SPARK_ENABLED, get_spark_session
|
|
94
94
|
from mage_ai.settings.platform.constants import project_platform_activated
|
|
95
95
|
from mage_ai.settings.repo import get_repo_path
|
|
96
96
|
from mage_ai.shared.array import unique_by
|
|
@@ -339,7 +339,6 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
339
339
|
self.upstream_blocks = []
|
|
340
340
|
self.downstream_blocks = []
|
|
341
341
|
self.test_functions = []
|
|
342
|
-
self.global_vars = {}
|
|
343
342
|
self.template_runtime_configuration = {}
|
|
344
343
|
|
|
345
344
|
self.dynamic_block_index = None
|
|
@@ -724,41 +723,6 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
724
723
|
widget=widget,
|
|
725
724
|
)
|
|
726
725
|
|
|
727
|
-
@classmethod
|
|
728
|
-
def block_class_from_type(self, block_type: str, language=None, pipeline=None) -> 'Block':
|
|
729
|
-
from mage_ai.data_preparation.models.block.constants import BLOCK_TYPE_TO_CLASS
|
|
730
|
-
from mage_ai.data_preparation.models.block.integration import (
|
|
731
|
-
DestinationBlock,
|
|
732
|
-
SourceBlock,
|
|
733
|
-
TransformerBlock,
|
|
734
|
-
)
|
|
735
|
-
from mage_ai.data_preparation.models.block.r import RBlock
|
|
736
|
-
from mage_ai.data_preparation.models.block.sql import SQLBlock
|
|
737
|
-
from mage_ai.data_preparation.models.widget import Widget
|
|
738
|
-
|
|
739
|
-
if BlockType.CHART == block_type:
|
|
740
|
-
return Widget
|
|
741
|
-
elif BlockType.DBT == block_type:
|
|
742
|
-
from mage_ai.data_preparation.models.block.dbt import DBTBlock
|
|
743
|
-
|
|
744
|
-
return DBTBlock
|
|
745
|
-
elif pipeline and PipelineType.INTEGRATION == pipeline.type:
|
|
746
|
-
if BlockType.CALLBACK == block_type:
|
|
747
|
-
return CallbackBlock
|
|
748
|
-
elif BlockType.CONDITIONAL == block_type:
|
|
749
|
-
return ConditionalBlock
|
|
750
|
-
elif BlockType.DATA_LOADER == block_type:
|
|
751
|
-
return SourceBlock
|
|
752
|
-
elif BlockType.DATA_EXPORTER == block_type:
|
|
753
|
-
return DestinationBlock
|
|
754
|
-
else:
|
|
755
|
-
return TransformerBlock
|
|
756
|
-
elif BlockLanguage.SQL == language:
|
|
757
|
-
return SQLBlock
|
|
758
|
-
elif BlockLanguage.R == language:
|
|
759
|
-
return RBlock
|
|
760
|
-
return BLOCK_TYPE_TO_CLASS.get(block_type)
|
|
761
|
-
|
|
762
726
|
@classmethod
|
|
763
727
|
def create(
|
|
764
728
|
self,
|
|
@@ -778,6 +742,8 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
778
742
|
widget: bool = False,
|
|
779
743
|
downstream_block_uuids: List[str] = None,
|
|
780
744
|
) -> 'Block':
|
|
745
|
+
from mage_ai.data_preparation.models.block.block_factory import BlockFactory
|
|
746
|
+
|
|
781
747
|
"""
|
|
782
748
|
1. Create a new folder for block_type if not exist
|
|
783
749
|
2. Create a new python file with code template
|
|
@@ -871,7 +837,11 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
871
837
|
language,
|
|
872
838
|
)
|
|
873
839
|
|
|
874
|
-
block =
|
|
840
|
+
block = BlockFactory.block_class_from_type(
|
|
841
|
+
block_type,
|
|
842
|
+
language=language,
|
|
843
|
+
pipeline=pipeline,
|
|
844
|
+
)(
|
|
875
845
|
name,
|
|
876
846
|
uuid,
|
|
877
847
|
block_type,
|
|
@@ -932,34 +902,6 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
932
902
|
block_uuids[t.value].append(f.split('.')[0])
|
|
933
903
|
return block_uuids
|
|
934
904
|
|
|
935
|
-
@classmethod
|
|
936
|
-
def get_block(
|
|
937
|
-
self,
|
|
938
|
-
name,
|
|
939
|
-
uuid,
|
|
940
|
-
block_type,
|
|
941
|
-
configuration=None,
|
|
942
|
-
content=None,
|
|
943
|
-
language=None,
|
|
944
|
-
pipeline=None,
|
|
945
|
-
status=BlockStatus.NOT_EXECUTED,
|
|
946
|
-
) -> 'Block':
|
|
947
|
-
block_class = self.block_class_from_type(
|
|
948
|
-
block_type,
|
|
949
|
-
language=language,
|
|
950
|
-
pipeline=pipeline,
|
|
951
|
-
) or Block
|
|
952
|
-
return block_class(
|
|
953
|
-
name,
|
|
954
|
-
uuid,
|
|
955
|
-
block_type,
|
|
956
|
-
configuration=configuration,
|
|
957
|
-
content=content,
|
|
958
|
-
language=language,
|
|
959
|
-
pipeline=pipeline,
|
|
960
|
-
status=status,
|
|
961
|
-
)
|
|
962
|
-
|
|
963
905
|
@classmethod
|
|
964
906
|
def get_block_from_file_path(self, file_path: str) -> 'Block':
|
|
965
907
|
parts = get_path_parts(file_path)
|
|
@@ -1198,7 +1140,7 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
1198
1140
|
f'Please run upstream blocks {upstream_block_uuids} '
|
|
1199
1141
|
'before running the current block.'
|
|
1200
1142
|
)
|
|
1201
|
-
global_vars = self.
|
|
1143
|
+
global_vars = self.enrich_global_vars(
|
|
1202
1144
|
global_vars,
|
|
1203
1145
|
dynamic_block_index=dynamic_block_index,
|
|
1204
1146
|
)
|
|
@@ -2204,6 +2146,7 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
2204
2146
|
self.pipeline.uuid,
|
|
2205
2147
|
block_uuid,
|
|
2206
2148
|
partition=execution_partition,
|
|
2149
|
+
max_results=DATAFRAME_SAMPLE_COUNT_PREVIEW,
|
|
2207
2150
|
)
|
|
2208
2151
|
|
|
2209
2152
|
if not include_print_outputs:
|
|
@@ -2445,8 +2388,10 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
2445
2388
|
return Template(self.executor_type).render(**get_template_vars())
|
|
2446
2389
|
return self.executor_type
|
|
2447
2390
|
|
|
2448
|
-
def get_pipelines_from_cache(self) -> List[Dict]:
|
|
2449
|
-
|
|
2391
|
+
def get_pipelines_from_cache(self, block_cache: BlockCache = None) -> List[Dict]:
|
|
2392
|
+
if block_cache is None:
|
|
2393
|
+
block_cache = BlockCache()
|
|
2394
|
+
arr = block_cache.get_pipelines(self)
|
|
2450
2395
|
|
|
2451
2396
|
return unique_by(
|
|
2452
2397
|
arr,
|
|
@@ -2497,11 +2442,13 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
2497
2442
|
def to_dict(
|
|
2498
2443
|
self,
|
|
2499
2444
|
include_block_catalog: bool = False,
|
|
2445
|
+
include_block_pipelines: bool = False,
|
|
2500
2446
|
include_callback_blocks: bool = False,
|
|
2501
2447
|
include_content: bool = False,
|
|
2502
2448
|
include_outputs: bool = False,
|
|
2503
2449
|
include_outputs_spark: bool = False,
|
|
2504
2450
|
sample_count: int = None,
|
|
2451
|
+
block_cache: BlockCache = None,
|
|
2505
2452
|
check_if_file_exists: bool = False,
|
|
2506
2453
|
**kwargs,
|
|
2507
2454
|
) -> Dict:
|
|
@@ -2515,6 +2462,9 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
2515
2462
|
if include_block_catalog and self.is_data_integration() and self.pipeline:
|
|
2516
2463
|
data['catalog'] = self.get_catalog_from_file()
|
|
2517
2464
|
|
|
2465
|
+
if include_block_pipelines:
|
|
2466
|
+
data['pipelines'] = self.get_pipelines_from_cache(block_cache=block_cache)
|
|
2467
|
+
|
|
2518
2468
|
if include_outputs:
|
|
2519
2469
|
include_outputs_use = include_outputs
|
|
2520
2470
|
if self.is_using_spark() and self.compute_management_enabled():
|
|
@@ -2551,6 +2501,7 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
2551
2501
|
include_outputs: bool = False,
|
|
2552
2502
|
include_outputs_spark: bool = False,
|
|
2553
2503
|
sample_count: int = None,
|
|
2504
|
+
block_cache: BlockCache = None,
|
|
2554
2505
|
check_if_file_exists: bool = False,
|
|
2555
2506
|
**kwargs,
|
|
2556
2507
|
) -> Dict:
|
|
@@ -2596,7 +2547,7 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
2596
2547
|
data['tags'] = self.tags()
|
|
2597
2548
|
|
|
2598
2549
|
if include_block_pipelines:
|
|
2599
|
-
data['pipelines'] = self.get_pipelines_from_cache()
|
|
2550
|
+
data['pipelines'] = self.get_pipelines_from_cache(block_cache=block_cache)
|
|
2600
2551
|
|
|
2601
2552
|
return data
|
|
2602
2553
|
|
|
@@ -3037,7 +2988,7 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
3037
2988
|
variable_mapping = merge_dict(output_variables, consolidated_print_variables)
|
|
3038
2989
|
return variable_mapping
|
|
3039
2990
|
|
|
3040
|
-
def
|
|
2991
|
+
def enrich_global_vars(
|
|
3041
2992
|
self,
|
|
3042
2993
|
global_vars: Dict = None,
|
|
3043
2994
|
dynamic_block_index: int = None,
|
|
@@ -3093,6 +3044,8 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
3093
3044
|
return global_vars
|
|
3094
3045
|
|
|
3095
3046
|
def get_spark_session(self):
|
|
3047
|
+
if not SPARK_ENABLED:
|
|
3048
|
+
return None
|
|
3096
3049
|
if self.spark_init and (not self.pipeline or
|
|
3097
3050
|
not self.pipeline.spark_config):
|
|
3098
3051
|
return self.spark
|
|
@@ -3658,23 +3611,29 @@ class AddonBlock(Block):
|
|
|
3658
3611
|
global_vars['dynamic_block_index'] = dynamic_block_index
|
|
3659
3612
|
|
|
3660
3613
|
if parent_block:
|
|
3614
|
+
if parent_block.global_vars is None:
|
|
3615
|
+
global_vars_copy = global_vars.copy()
|
|
3616
|
+
parent_block.enrich_global_vars(
|
|
3617
|
+
global_vars=global_vars_copy,
|
|
3618
|
+
dynamic_block_index=dynamic_block_index,
|
|
3619
|
+
)
|
|
3620
|
+
global_vars = merge_dict(parent_block.global_vars, global_vars)
|
|
3661
3621
|
global_vars['parent_block_uuid'] = parent_block.uuid
|
|
3662
3622
|
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
global_vars['destination_table'] = destination_table
|
|
3623
|
+
if parent_block.pipeline and \
|
|
3624
|
+
PipelineType.INTEGRATION == parent_block.pipeline.type:
|
|
3625
|
+
|
|
3626
|
+
template_runtime_configuration = parent_block.template_runtime_configuration
|
|
3627
|
+
index = template_runtime_configuration.get('index', None)
|
|
3628
|
+
is_last_block_run = template_runtime_configuration.get('is_last_block_run', False)
|
|
3629
|
+
selected_streams = template_runtime_configuration.get('selected_streams', [])
|
|
3630
|
+
stream = selected_streams[0] if len(selected_streams) >= 1 else None
|
|
3631
|
+
destination_table = template_runtime_configuration.get('destination_table', stream)
|
|
3632
|
+
|
|
3633
|
+
global_vars['index'] = index
|
|
3634
|
+
global_vars['is_last_block_run'] = is_last_block_run
|
|
3635
|
+
global_vars['stream'] = stream
|
|
3636
|
+
global_vars['destination_table'] = destination_table
|
|
3678
3637
|
|
|
3679
3638
|
return global_vars
|
|
3680
3639
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from mage_ai.data_preparation.models.block import Block, CallbackBlock, ConditionalBlock
|
|
2
|
+
from mage_ai.data_preparation.models.block.constants import BLOCK_TYPE_TO_CLASS
|
|
3
|
+
from mage_ai.data_preparation.models.block.integration import (
|
|
4
|
+
DestinationBlock,
|
|
5
|
+
SourceBlock,
|
|
6
|
+
TransformerBlock,
|
|
7
|
+
)
|
|
8
|
+
from mage_ai.data_preparation.models.block.r import RBlock
|
|
9
|
+
from mage_ai.data_preparation.models.block.sql import SQLBlock
|
|
10
|
+
from mage_ai.data_preparation.models.constants import (
|
|
11
|
+
BlockLanguage,
|
|
12
|
+
BlockStatus,
|
|
13
|
+
BlockType,
|
|
14
|
+
PipelineType,
|
|
15
|
+
)
|
|
16
|
+
from mage_ai.data_preparation.models.widget import Widget
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
from mage_ai.data_preparation.models.block.dbt.block_sql import DBTBlockSQL
|
|
20
|
+
from mage_ai.data_preparation.models.block.dbt.block_yaml import DBTBlockYAML
|
|
21
|
+
except Exception:
|
|
22
|
+
print('DBT library not installed.')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class BlockFactory:
|
|
26
|
+
@classmethod
|
|
27
|
+
def block_class_from_type(self, block_type: str, language=None, pipeline=None) -> 'Block':
|
|
28
|
+
if BlockType.CHART == block_type:
|
|
29
|
+
return Widget
|
|
30
|
+
elif BlockType.DBT == block_type:
|
|
31
|
+
if language == BlockLanguage.YAML:
|
|
32
|
+
return DBTBlockYAML
|
|
33
|
+
return DBTBlockSQL
|
|
34
|
+
elif pipeline and PipelineType.INTEGRATION == pipeline.type:
|
|
35
|
+
if BlockType.CALLBACK == block_type:
|
|
36
|
+
return CallbackBlock
|
|
37
|
+
elif BlockType.CONDITIONAL == block_type:
|
|
38
|
+
return ConditionalBlock
|
|
39
|
+
elif BlockType.DATA_LOADER == block_type:
|
|
40
|
+
return SourceBlock
|
|
41
|
+
elif BlockType.DATA_EXPORTER == block_type:
|
|
42
|
+
return DestinationBlock
|
|
43
|
+
else:
|
|
44
|
+
return TransformerBlock
|
|
45
|
+
elif BlockLanguage.SQL == language:
|
|
46
|
+
return SQLBlock
|
|
47
|
+
elif BlockLanguage.R == language:
|
|
48
|
+
return RBlock
|
|
49
|
+
return BLOCK_TYPE_TO_CLASS.get(block_type)
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def get_block(
|
|
53
|
+
self,
|
|
54
|
+
name,
|
|
55
|
+
uuid,
|
|
56
|
+
block_type,
|
|
57
|
+
configuration=None,
|
|
58
|
+
content=None,
|
|
59
|
+
language=None,
|
|
60
|
+
pipeline=None,
|
|
61
|
+
status=BlockStatus.NOT_EXECUTED,
|
|
62
|
+
) -> 'Block':
|
|
63
|
+
block_class = BlockFactory.block_class_from_type(
|
|
64
|
+
block_type,
|
|
65
|
+
language=language,
|
|
66
|
+
pipeline=pipeline,
|
|
67
|
+
) or Block
|
|
68
|
+
return block_class(
|
|
69
|
+
name,
|
|
70
|
+
uuid,
|
|
71
|
+
block_type,
|
|
72
|
+
configuration=configuration,
|
|
73
|
+
content=content,
|
|
74
|
+
language=language,
|
|
75
|
+
pipeline=pipeline,
|
|
76
|
+
status=status,
|
|
77
|
+
)
|
|
@@ -26,19 +26,17 @@ from mage_ai.shared.parsers import encode_complex
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class DBTBlock(Block):
|
|
29
|
-
|
|
29
|
+
@classmethod
|
|
30
|
+
def create(cls, *args, **kwargs) -> 'DBTBlock':
|
|
30
31
|
"""
|
|
31
32
|
Factory for the child blocks
|
|
32
33
|
"""
|
|
33
34
|
# Import Child blocks here to prevent cycle import
|
|
34
35
|
from mage_ai.data_preparation.models.block.dbt.block_sql import DBTBlockSQL
|
|
35
36
|
from mage_ai.data_preparation.models.block.dbt.block_yaml import DBTBlockYAML
|
|
36
|
-
if
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return super(DBTBlock, cls).__new__(DBTBlockSQL)
|
|
40
|
-
else:
|
|
41
|
-
return super(DBTBlock, cls).__new__(cls, *args, **kwargs)
|
|
37
|
+
if kwargs.get('language', BlockLanguage.SQL) == BlockLanguage.YAML:
|
|
38
|
+
return DBTBlockYAML(*args, **kwargs)
|
|
39
|
+
return DBTBlockSQL(*args, **kwargs)
|
|
42
40
|
|
|
43
41
|
@property
|
|
44
42
|
def base_project_path(self) -> Union[str, os.PathLike]:
|
|
@@ -2,12 +2,15 @@ from logging import Logger
|
|
|
2
2
|
from typing import Dict, List
|
|
3
3
|
|
|
4
4
|
from mage_ai.data_preparation.models.block import Block
|
|
5
|
-
from mage_ai.data_preparation.models.global_data_product import GlobalDataProduct
|
|
6
|
-
from mage_ai.orchestration.triggers import global_data_product as trigger
|
|
7
5
|
|
|
8
6
|
|
|
9
7
|
class GlobalDataProductBlock(Block):
|
|
10
|
-
def get_global_data_product(self)
|
|
8
|
+
def get_global_data_product(self):
|
|
9
|
+
# Avoid circular dependency of Pipeline class
|
|
10
|
+
from mage_ai.data_preparation.models.global_data_product import (
|
|
11
|
+
GlobalDataProduct,
|
|
12
|
+
)
|
|
13
|
+
|
|
11
14
|
override_configuration = (self.configuration or {}).get('global_data_product', {})
|
|
12
15
|
global_data_product = GlobalDataProduct.get(override_configuration.get('uuid'))
|
|
13
16
|
|
|
@@ -31,6 +34,9 @@ class GlobalDataProductBlock(Block):
|
|
|
31
34
|
logging_tags: Dict = None,
|
|
32
35
|
**kwargs,
|
|
33
36
|
) -> List:
|
|
37
|
+
# Avoid circular dependency of Pipeline class
|
|
38
|
+
from mage_ai.orchestration.triggers import global_data_product as trigger
|
|
39
|
+
|
|
34
40
|
trigger.trigger_and_check_status(
|
|
35
41
|
self.get_global_data_product(),
|
|
36
42
|
block=self,
|
|
@@ -416,9 +416,10 @@ class SourceBlock(IntegrationBlock):
|
|
|
416
416
|
class DestinationBlock(IntegrationBlock):
|
|
417
417
|
def to_dict(
|
|
418
418
|
self,
|
|
419
|
-
include_content=False,
|
|
420
|
-
include_outputs=False,
|
|
421
|
-
|
|
419
|
+
include_content: bool = False,
|
|
420
|
+
include_outputs: bool = False,
|
|
421
|
+
include_block_pipelines: bool = False,
|
|
422
|
+
sample_count: int = None,
|
|
422
423
|
check_if_file_exists: bool = False,
|
|
423
424
|
destination_table: str = None,
|
|
424
425
|
state_stream: str = None,
|
|
@@ -444,6 +445,7 @@ class DestinationBlock(IntegrationBlock):
|
|
|
444
445
|
super().to_dict(
|
|
445
446
|
include_content=include_content,
|
|
446
447
|
include_outputs=include_outputs,
|
|
448
|
+
include_block_pipelines=include_block_pipelines,
|
|
447
449
|
sample_count=sample_count,
|
|
448
450
|
check_if_file_exists=check_if_file_exists,
|
|
449
451
|
),
|
|
@@ -452,9 +454,10 @@ class DestinationBlock(IntegrationBlock):
|
|
|
452
454
|
|
|
453
455
|
async def to_dict_async(
|
|
454
456
|
self,
|
|
455
|
-
include_content=False,
|
|
456
|
-
include_outputs=False,
|
|
457
|
-
|
|
457
|
+
include_content: bool = False,
|
|
458
|
+
include_outputs: bool = False,
|
|
459
|
+
include_block_pipelines: bool = False,
|
|
460
|
+
sample_count: int = None,
|
|
458
461
|
check_if_file_exists: bool = False,
|
|
459
462
|
destination_table: str = None,
|
|
460
463
|
state_stream: str = None,
|
|
@@ -463,13 +466,14 @@ class DestinationBlock(IntegrationBlock):
|
|
|
463
466
|
return self.to_dict(
|
|
464
467
|
include_content=include_content,
|
|
465
468
|
include_outputs=include_outputs,
|
|
469
|
+
include_block_pipelines=include_block_pipelines,
|
|
466
470
|
sample_count=sample_count,
|
|
467
471
|
check_if_file_exists=check_if_file_exists,
|
|
468
472
|
destination_table=destination_table,
|
|
469
473
|
state_stream=state_stream,
|
|
470
474
|
)
|
|
471
475
|
|
|
472
|
-
def update(self, data, update_state=False):
|
|
476
|
+
def update(self, data, update_state=False, **kwargs):
|
|
473
477
|
if update_state:
|
|
474
478
|
from mage_ai.data_preparation.models.pipelines.integration_pipeline import (
|
|
475
479
|
IntegrationPipeline,
|
|
@@ -493,7 +497,7 @@ class DestinationBlock(IntegrationBlock):
|
|
|
493
497
|
bookmark_values=bookmark_values
|
|
494
498
|
)
|
|
495
499
|
|
|
496
|
-
return super().update(data)
|
|
500
|
+
return super().update(data, **kwargs)
|
|
497
501
|
|
|
498
502
|
def output_variables(self, execution_partition: str = None) -> List[str]:
|
|
499
503
|
return []
|
|
@@ -15,8 +15,10 @@ import yaml
|
|
|
15
15
|
from jinja2 import Template
|
|
16
16
|
|
|
17
17
|
from mage_ai.authentication.permissions.constants import EntityName
|
|
18
|
+
from mage_ai.cache.block import BlockCache
|
|
18
19
|
from mage_ai.cache.pipeline import PipelineCache
|
|
19
20
|
from mage_ai.data_preparation.models.block import Block, run_blocks, run_blocks_sync
|
|
21
|
+
from mage_ai.data_preparation.models.block.block_factory import BlockFactory
|
|
20
22
|
from mage_ai.data_preparation.models.block.data_integration.utils import (
|
|
21
23
|
convert_outputs_to_data,
|
|
22
24
|
)
|
|
@@ -82,6 +84,8 @@ class Pipeline:
|
|
|
82
84
|
repo_config=None,
|
|
83
85
|
catalog=None,
|
|
84
86
|
use_repo_path: bool = False,
|
|
87
|
+
description: str = None,
|
|
88
|
+
tags: List[str] = None,
|
|
85
89
|
):
|
|
86
90
|
self.block_configs = []
|
|
87
91
|
self.blocks_by_uuid = {}
|
|
@@ -90,7 +94,7 @@ class Pipeline:
|
|
|
90
94
|
self.concurrency_config = dict()
|
|
91
95
|
self.created_at = None
|
|
92
96
|
self.data_integration = None
|
|
93
|
-
self.description =
|
|
97
|
+
self.description = description
|
|
94
98
|
self.executor_config = dict()
|
|
95
99
|
self.executor_type = None
|
|
96
100
|
self.extensions = {}
|
|
@@ -101,7 +105,7 @@ class Pipeline:
|
|
|
101
105
|
self.run_pipeline_in_one_process = False
|
|
102
106
|
self.schedules = []
|
|
103
107
|
self.settings = {}
|
|
104
|
-
self.tags = []
|
|
108
|
+
self.tags = tags or []
|
|
105
109
|
self.type = PipelineType.PYTHON
|
|
106
110
|
self.use_repo_path = use_repo_path
|
|
107
111
|
self.uuid = uuid
|
|
@@ -215,7 +219,14 @@ class Pipeline:
|
|
|
215
219
|
self.widget_configs
|
|
216
220
|
|
|
217
221
|
@classmethod
|
|
218
|
-
def create(
|
|
222
|
+
def create(
|
|
223
|
+
self,
|
|
224
|
+
name: str,
|
|
225
|
+
description: str = None,
|
|
226
|
+
pipeline_type: PipelineType = PipelineType.PYTHON,
|
|
227
|
+
repo_path: str = None,
|
|
228
|
+
tags: List[str] = None,
|
|
229
|
+
):
|
|
219
230
|
"""
|
|
220
231
|
1. Create a new folder for pipeline
|
|
221
232
|
2. Create a new yaml file to store pipeline config
|
|
@@ -231,14 +242,20 @@ class Pipeline:
|
|
|
231
242
|
with open(os.path.join(pipeline_path, PIPELINE_CONFIG_FILE), 'w') as fp:
|
|
232
243
|
yaml.dump(dict(
|
|
233
244
|
created_at=str(datetime.now(tz=pytz.UTC)),
|
|
245
|
+
description=description,
|
|
234
246
|
name=name,
|
|
247
|
+
tags=tags or [],
|
|
235
248
|
uuid=uuid,
|
|
236
249
|
type=format_enum(pipeline_type or PipelineType.PYTHON),
|
|
237
250
|
), fp)
|
|
251
|
+
|
|
238
252
|
pipeline = Pipeline(
|
|
239
253
|
uuid,
|
|
254
|
+
description=description,
|
|
240
255
|
repo_path=repo_path,
|
|
256
|
+
tags=tags or [],
|
|
241
257
|
)
|
|
258
|
+
|
|
242
259
|
return pipeline
|
|
243
260
|
|
|
244
261
|
@classmethod
|
|
@@ -368,6 +385,54 @@ class Pipeline:
|
|
|
368
385
|
IntegrationPipeline,
|
|
369
386
|
)
|
|
370
387
|
|
|
388
|
+
config_path, repo_path = self._get_config_path(
|
|
389
|
+
uuid,
|
|
390
|
+
repo_path=repo_path,
|
|
391
|
+
all_projects=all_projects,
|
|
392
|
+
use_repo_path=use_repo_path,
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
if check_if_exists and not os.path.exists(config_path):
|
|
396
|
+
return None
|
|
397
|
+
|
|
398
|
+
pipeline = self(uuid, repo_path=repo_path, use_repo_path=use_repo_path)
|
|
399
|
+
if PipelineType.INTEGRATION == pipeline.type:
|
|
400
|
+
pipeline = IntegrationPipeline(uuid, repo_path=repo_path)
|
|
401
|
+
|
|
402
|
+
return pipeline
|
|
403
|
+
|
|
404
|
+
@classmethod
|
|
405
|
+
def get_config(
|
|
406
|
+
self,
|
|
407
|
+
uuid,
|
|
408
|
+
repo_path: str = None,
|
|
409
|
+
all_projects: bool = False,
|
|
410
|
+
use_repo_path: bool = False,
|
|
411
|
+
):
|
|
412
|
+
config_path, _ = self._get_config_path(
|
|
413
|
+
uuid,
|
|
414
|
+
repo_path=repo_path,
|
|
415
|
+
all_projects=all_projects,
|
|
416
|
+
use_repo_path=use_repo_path,
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
metadata_path = os.path.join(config_path, PIPELINE_CONFIG_FILE)
|
|
420
|
+
|
|
421
|
+
if not os.path.exists(metadata_path):
|
|
422
|
+
return None
|
|
423
|
+
|
|
424
|
+
with open(metadata_path) as fp:
|
|
425
|
+
config = yaml.full_load(fp) or {}
|
|
426
|
+
return config
|
|
427
|
+
|
|
428
|
+
@classmethod
|
|
429
|
+
def _get_config_path(
|
|
430
|
+
self,
|
|
431
|
+
uuid,
|
|
432
|
+
repo_path: str = None,
|
|
433
|
+
all_projects: bool = False,
|
|
434
|
+
use_repo_path: bool = False,
|
|
435
|
+
) -> Tuple[str, str]:
|
|
371
436
|
if all_projects and not use_repo_path and project_platform_activated():
|
|
372
437
|
from mage_ai.settings.platform.utils import get_pipeline_config_path
|
|
373
438
|
|
|
@@ -379,15 +444,7 @@ class Pipeline:
|
|
|
379
444
|
PIPELINES_FOLDER,
|
|
380
445
|
uuid,
|
|
381
446
|
)
|
|
382
|
-
|
|
383
|
-
if check_if_exists and not os.path.exists(config_path):
|
|
384
|
-
return None
|
|
385
|
-
|
|
386
|
-
pipeline = self(uuid, repo_path=repo_path, use_repo_path=use_repo_path)
|
|
387
|
-
if PipelineType.INTEGRATION == pipeline.type:
|
|
388
|
-
pipeline = IntegrationPipeline(uuid, repo_path=repo_path)
|
|
389
|
-
|
|
390
|
-
return pipeline
|
|
447
|
+
return config_path, repo_path
|
|
391
448
|
|
|
392
449
|
@classmethod
|
|
393
450
|
async def load_metadata(
|
|
@@ -717,7 +774,8 @@ class Pipeline:
|
|
|
717
774
|
)
|
|
718
775
|
|
|
719
776
|
language = c.get('language')
|
|
720
|
-
|
|
777
|
+
|
|
778
|
+
return BlockFactory.block_class_from_type(block_type, language=language, pipeline=self)(
|
|
721
779
|
c.get('name'),
|
|
722
780
|
c.get('uuid'),
|
|
723
781
|
block_type,
|
|
@@ -931,6 +989,8 @@ class Pipeline:
|
|
|
931
989
|
include_outputs=include_outputs,
|
|
932
990
|
sample_count=sample_count,
|
|
933
991
|
)
|
|
992
|
+
if include_block_pipelines:
|
|
993
|
+
shared_kwargs['block_cache'] = BlockCache()
|
|
934
994
|
blocks_data = await asyncio.gather(
|
|
935
995
|
*[b.to_dict_async(**merge_dict(shared_kwargs, dict(
|
|
936
996
|
include_block_catalog=include_block_catalog,
|
|
@@ -991,6 +1051,7 @@ class Pipeline:
|
|
|
991
1051
|
old_uuid = None
|
|
992
1052
|
blocks_to_remove_from_cache = []
|
|
993
1053
|
block_uuids_to_add_to_cache = []
|
|
1054
|
+
tags_to_remove_from_cache = []
|
|
994
1055
|
should_update_block_cache = False
|
|
995
1056
|
should_update_tag_cache = False
|
|
996
1057
|
|
|
@@ -1043,6 +1104,10 @@ class Pipeline:
|
|
|
1043
1104
|
old_tags = self.tags or []
|
|
1044
1105
|
|
|
1045
1106
|
if sorted(new_tags) != sorted(old_tags):
|
|
1107
|
+
tags_diff = set(old_tags).symmetric_difference(set(new_tags))
|
|
1108
|
+
for tag in tags_diff:
|
|
1109
|
+
if tag in old_tags:
|
|
1110
|
+
tags_to_remove_from_cache.append(tag)
|
|
1046
1111
|
self.tags = new_tags
|
|
1047
1112
|
should_save = True
|
|
1048
1113
|
should_update_tag_cache = True
|
|
@@ -1296,6 +1361,8 @@ class Pipeline:
|
|
|
1296
1361
|
|
|
1297
1362
|
cache = await TagCache.initialize_cache()
|
|
1298
1363
|
|
|
1364
|
+
for tag_uuid in tags_to_remove_from_cache:
|
|
1365
|
+
cache.remove_pipeline(tag_uuid, self.uuid, self.repo_path)
|
|
1299
1366
|
for tag_uuid in self.tags:
|
|
1300
1367
|
if old_uuid:
|
|
1301
1368
|
cache.remove_pipeline(tag_uuid, old_uuid, self.repo_path)
|
|
@@ -29,11 +29,36 @@ class GCSStorage(BaseStorage):
|
|
|
29
29
|
path += '/'
|
|
30
30
|
return self.path_exists(path)
|
|
31
31
|
|
|
32
|
-
def listdir(
|
|
32
|
+
def listdir(
|
|
33
|
+
self,
|
|
34
|
+
path: str,
|
|
35
|
+
suffix: str = None,
|
|
36
|
+
max_results: int = None,
|
|
37
|
+
) -> List[str]:
|
|
33
38
|
if not path.endswith('/'):
|
|
34
39
|
path += '/'
|
|
35
40
|
path = gcs_url_path(path)
|
|
36
|
-
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
NOTE: The number of results returned by the GCS bucket list_blobs method may
|
|
44
|
+
be lower than the number entered for the max_results argument, since this
|
|
45
|
+
method recursively fetches files inside of subdirectories at the path
|
|
46
|
+
specified, not just the directories themselves at the top level of the path.
|
|
47
|
+
|
|
48
|
+
As a result, when fetching block output folders in a remote variables directory,
|
|
49
|
+
the json or parquet files inside of the block output folders (e.g. the "type.json"
|
|
50
|
+
file in folder "output_0") are counted towards the "max_results" limit. If max_results
|
|
51
|
+
is set to 10, less than 10 output folders may be returned due to there being multiple
|
|
52
|
+
json or other files in each output folder. We do not increase the max_results or
|
|
53
|
+
include a "delimiter" argument because it would increase load times to unacceptable levels.
|
|
54
|
+
|
|
55
|
+
Example block output path in GCS:
|
|
56
|
+
gs://mage_demo/pipelines/example_pipeline/.variables/example_block/output_0/
|
|
57
|
+
"""
|
|
58
|
+
blobs = self.bucket.list_blobs(
|
|
59
|
+
prefix=path,
|
|
60
|
+
max_results=max_results,
|
|
61
|
+
)
|
|
37
62
|
keys = []
|
|
38
63
|
for blob in blobs:
|
|
39
64
|
# Avoid finding files recursevively in the dir path.
|
|
@@ -123,7 +148,7 @@ class GCSStorage(BaseStorage):
|
|
|
123
148
|
df.write_parquet(buffer)
|
|
124
149
|
buffer.seek(0)
|
|
125
150
|
blob = self.bucket.blob(gcs_url_path(file_path))
|
|
126
|
-
blob.upload_from_string(buffer)
|
|
151
|
+
blob.upload_from_string(buffer.getvalue())
|
|
127
152
|
|
|
128
153
|
@contextmanager
|
|
129
154
|
def open_to_write(self, file_path: str) -> None:
|