mage-ai 0.9.12__py3-none-any.whl → 0.9.14__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/generator.py +1 -1
- mage_ai/ai/generator_cmds.py +1 -1
- mage_ai/ai/llm_pipeline_wizard.py +31 -17
- mage_ai/api/policies/BlockPolicy.py +1 -0
- mage_ai/api/policies/PipelineRunPolicy.py +1 -0
- mage_ai/api/policies/PipelineSchedulePolicy.py +12 -0
- mage_ai/api/policies/TagPolicy.py +18 -0
- mage_ai/api/presenters/BlockRunPresenter.py +4 -1
- mage_ai/api/presenters/PipelineRunPresenter.py +2 -0
- mage_ai/api/presenters/PipelineSchedulePresenter.py +9 -2
- mage_ai/api/presenters/TagPresenter.py +3 -0
- mage_ai/api/resources/BackfillResource.py +6 -3
- mage_ai/api/resources/BlockResource.py +2 -0
- mage_ai/api/resources/BlockRunResource.py +18 -12
- mage_ai/api/resources/DatabaseResource.py +23 -0
- mage_ai/api/resources/GitBranchResource.py +8 -1
- mage_ai/api/resources/GlobalDataProductResource.py +5 -2
- mage_ai/api/resources/PipelineResource.py +30 -14
- mage_ai/api/resources/PipelineScheduleResource.py +157 -1
- mage_ai/api/resources/SearchResultResource.py +1 -0
- mage_ai/api/resources/TagResource.py +16 -3
- mage_ai/data_integrations/sources/constants.py +1 -0
- mage_ai/data_preparation/git/__init__.py +18 -0
- mage_ai/data_preparation/models/block/__init__.py +34 -11
- mage_ai/data_preparation/models/block/dbt/utils/__init__.py +37 -10
- mage_ai/data_preparation/models/block/integration/__init__.py +1 -1
- mage_ai/data_preparation/models/block/sql/__init__.py +44 -2
- mage_ai/data_preparation/models/custom_templates/utils.py +14 -4
- mage_ai/data_preparation/models/global_data_product/__init__.py +8 -0
- mage_ai/data_preparation/models/pipeline.py +4 -0
- mage_ai/data_preparation/models/variable.py +5 -2
- mage_ai/data_preparation/repo_manager.py +28 -16
- mage_ai/io/clickhouse.py +9 -6
- mage_ai/io/redshift.py +9 -10
- mage_ai/io/utils.py +3 -1
- mage_ai/orchestration/db/migrations/README.md +39 -2
- mage_ai/orchestration/db/migrations/env.py +1 -0
- mage_ai/orchestration/db/migrations/versions/386bcfebd48d_create_tag_and_tagassociation_tables.py +59 -0
- mage_ai/orchestration/db/models/schedules.py +29 -2
- mage_ai/orchestration/db/models/tags.py +57 -0
- mage_ai/orchestration/pipeline_scheduler.py +7 -7
- mage_ai/orchestration/triggers/global_data_product.py +41 -40
- mage_ai/orchestration/triggers/utils.py +11 -1
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +2 -2
- mage_ai/server/frontend_dist/404.html.html +2 -2
- mage_ai/server/frontend_dist/_next/static/CNjkRIWPaAu1yJUmIaX_q/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1005-a2f0e3ee378ef02b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1424-fca78f21a81a7183.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1484-87d4d4a698ac63dc.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/2485-39885e5335888821.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/2786-f71862671f66d948.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3391-6f0a0a5c254cd7f2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3881-131cf690e54c23a3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/437-331193bd9b2fe777.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/4822-045cc7cdd7c95163.js → frontend_dist/_next/static/chunks/4822-ee62acb1927c8150.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/547-bd961ea93f3eb98b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/6299-fcb702d0f3d3291b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/6422-0cdd6e596dcd43b6.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{6786-77c7e36678abb2c6.js → 6786-55e1bca3c897d5ee.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7496-7e4dd11e3f3b8e79.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7722-76c724a66240561b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7815-8b68b0eb665fcd2d.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/8190-d38ed1133030797d.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/8952-9d6fa18fa9378989.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9605-9332e1686c46da7d.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-9dae6fa5126cf001.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/files-2dc2a0dfc0ff620d.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-6d3d53624debede6.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-2756fe6d9decae4a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/settings-6577159a0af52a78.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-6815a3ece7dc1678.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-7f790238fe70d9ab.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-33c7f2550add0719.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-07e4a3a674e83578.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-b8b4bed1e8e50068.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-54cb4936accdd2d9.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-d331e98ad103b13e.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-d87d0c21758a2d7c.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-68e1b861ef4fc0d7.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-9fa0c4ce1c921a41.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-d5ef19ca1f9931de.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-4a2671811a153411.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-8872a6e00280f58c.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-484581ae34a1c596.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-ce11db27e4af7869.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-624a2d7cbe6303b4.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-1169f4eecf752033.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-d2224a447987fa69.js → frontend_dist/_next/static/chunks/pages/settings/account/profile-c3ff06a12baa40a2.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-60b4398d7ae00206.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-dd827816bf4a7908.js → frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-05b53444f0e7449b.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-097aa0bef1e34cdb.js → frontend_dist/_next/static/chunks/pages/sign-in-a5e9561a6c0d2e38.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/templates/{[...slug]-78a07e7fe8973811.js → [...slug]-c21b269750441494.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/templates-19df643f52679d5a.js → frontend_dist/_next/static/chunks/pages/templates-ce2a29d477a6ce94.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-71bbb30dd9b57f80.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-1dc780d52fbd1573.js +1 -0
- 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/index.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/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]/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/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/sync-data.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 +11 -11
- 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 +3 -3
- 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_base_path_template/404.html.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1005-a2f0e3ee378ef02b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1424-fca78f21a81a7183.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1484-87d4d4a698ac63dc.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2485-39885e5335888821.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2786-f71862671f66d948.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3391-6f0a0a5c254cd7f2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3881-131cf690e54c23a3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/437-331193bd9b2fe777.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/4822-045cc7cdd7c95163.js → frontend_dist_base_path_template/_next/static/chunks/4822-ee62acb1927c8150.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/547-bd961ea93f3eb98b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6299-fcb702d0f3d3291b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6422-0cdd6e596dcd43b6.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{6786-77c7e36678abb2c6.js → 6786-55e1bca3c897d5ee.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7496-7e4dd11e3f3b8e79.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7722-76c724a66240561b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7815-8b68b0eb665fcd2d.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8190-d38ed1133030797d.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8952-9d6fa18fa9378989.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9605-9332e1686c46da7d.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-9dae6fa5126cf001.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-2dc2a0dfc0ff620d.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-6d3d53624debede6.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-2756fe6d9decae4a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/settings-6577159a0af52a78.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-6815a3ece7dc1678.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-7f790238fe70d9ab.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-33c7f2550add0719.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-07e4a3a674e83578.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-b8b4bed1e8e50068.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-54cb4936accdd2d9.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-d331e98ad103b13e.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-d87d0c21758a2d7c.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-68e1b861ef4fc0d7.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-9fa0c4ce1c921a41.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-d5ef19ca1f9931de.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-4a2671811a153411.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-8872a6e00280f58c.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-484581ae34a1c596.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-ce11db27e4af7869.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-624a2d7cbe6303b4.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-1169f4eecf752033.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/account/profile-d2224a447987fa69.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-c3ff06a12baa40a2.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-60b4398d7ae00206.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-dd827816bf4a7908.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-05b53444f0e7449b.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/sign-in-097aa0bef1e34cdb.js → frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-a5e9561a6c0d2e38.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/templates/{[...slug]-78a07e7fe8973811.js → [...slug]-c21b269750441494.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/templates-19df643f52679d5a.js → frontend_dist_base_path_template/_next/static/chunks/pages/templates-ce2a29d477a6ce94.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-71bbb30dd9b57f80.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-1dc780d52fbd1573.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/yJvL-3bfsNF3WCStZ10Dm/_buildManifest.js +1 -0
- 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/index.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/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]/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/settings/account/profile.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/sync-data.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 +11 -11
- 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 +3 -3
- 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/server/server.py +53 -27
- mage_ai/services/spark/spark.py +75 -2
- mage_ai/streaming/constants.py +1 -0
- mage_ai/streaming/sources/kafka.py +17 -9
- mage_ai/tests/data_preparation/models/custom_templates/__init__.py +0 -0
- mage_ai/tests/data_preparation/models/custom_templates/test_utils.py +36 -0
- mage_ai/tests/data_preparation/models/test_block.py +48 -0
- mage_ai/tests/data_preparation/test_repo_manager.py +19 -1
- mage_ai/tests/server/test_server.py +20 -2
- mage_ai/tests/services/spark/__init__.py +0 -0
- mage_ai/tests/services/spark/test_spark.py +52 -0
- {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/METADATA +1 -1
- {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/RECORD +245 -233
- mage_ai/server/frontend_dist/_next/static/RdDEYzOW6lfmOEilKsz4V/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1005-2f8ef0e28c917767.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1424-a2cd1bfc708a323b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1484-a07f74ae5c40141c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2485-b569baad92049d6b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2786-acce6ea0d9b4898e.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3654-14ee3eacc42b118a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3881-0eb04f7f7a244347.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/437-d43ccff3a064a528.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/547-4ad2cdae967055b6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/6299-cf188c1b7a1bc33c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7496-ab1be388ae09d362.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7722-a74e6f977993e75e.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7815-fbd99c8f259d9e8b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/8952-98e54b14c1af492f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-74805cf1296fd50f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/files-bcdaa82adcca891d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-abdbda772d94c386.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-01f8ef10e87ec236.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/settings-950fbcb72961eb3c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-c6fd44191c812edf.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-6e46ed84cf3f4e9d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-1d52bba72442c53f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-8c33956a28fb4fa8.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-b28d151c32c2a469.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-e1708e5576cd26d1.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-0f3468d52020dcbf.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-489d02937d5f4695.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-544475d8e841638f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e117a99f334b6022.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-f1ef481c7beb8aef.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-ab52e3174c3dcf64.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-3e290f7d76c68b3f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-1ac4dc91ec394c6d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-4753de69f7e366c5.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-cf285c43759e9b2a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-3f86e7f1c8d63beb.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-b2354688508b0755.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-cacb24e3632cfdfc.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-5a6e3a62fef551f1.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/4dbzHNz2XwS_s6Z0qsIGO/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1005-2f8ef0e28c917767.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1424-a2cd1bfc708a323b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1484-a07f74ae5c40141c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2485-b569baad92049d6b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2786-acce6ea0d9b4898e.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3654-14ee3eacc42b118a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3881-0eb04f7f7a244347.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/437-d43ccff3a064a528.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/547-4ad2cdae967055b6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6299-cf188c1b7a1bc33c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7496-ab1be388ae09d362.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7722-a74e6f977993e75e.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7815-fbd99c8f259d9e8b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8952-98e54b14c1af492f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-74805cf1296fd50f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-bcdaa82adcca891d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-abdbda772d94c386.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-01f8ef10e87ec236.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/settings-950fbcb72961eb3c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-c6fd44191c812edf.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-6e46ed84cf3f4e9d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-1d52bba72442c53f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-8c33956a28fb4fa8.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-b28d151c32c2a469.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-e1708e5576cd26d1.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-0f3468d52020dcbf.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-489d02937d5f4695.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-544475d8e841638f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e117a99f334b6022.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-f1ef481c7beb8aef.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-ab52e3174c3dcf64.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-3e290f7d76c68b3f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-1ac4dc91ec394c6d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-4753de69f7e366c5.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-cf285c43759e9b2a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-3f86e7f1c8d63beb.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-b2354688508b0755.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-cacb24e3632cfdfc.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-5a6e3a62fef551f1.js +0 -1
- /mage_ai/server/frontend_dist/_next/static/{RdDEYzOW6lfmOEilKsz4V → CNjkRIWPaAu1yJUmIaX_q}/_middlewareManifest.js +0 -0
- /mage_ai/server/frontend_dist/_next/static/{RdDEYzOW6lfmOEilKsz4V → CNjkRIWPaAu1yJUmIaX_q}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{4dbzHNz2XwS_s6Z0qsIGO → yJvL-3bfsNF3WCStZ10Dm}/_middlewareManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{4dbzHNz2XwS_s6Z0qsIGO → yJvL-3bfsNF3WCStZ10Dm}/_ssgManifest.js +0 -0
- {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/WHEEL +0 -0
- {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/top_level.txt +0 -0
mage_ai/server/server.py
CHANGED
|
@@ -22,8 +22,9 @@ from mage_ai.data_preparation.preferences import get_preferences
|
|
|
22
22
|
from mage_ai.data_preparation.repo_manager import (
|
|
23
23
|
ProjectType,
|
|
24
24
|
get_project_type,
|
|
25
|
+
get_variables_dir,
|
|
26
|
+
init_project_uuid,
|
|
25
27
|
init_repo,
|
|
26
|
-
update_project_uuid,
|
|
27
28
|
)
|
|
28
29
|
from mage_ai.data_preparation.shared.constants import MANAGE_ENV_VAR
|
|
29
30
|
from mage_ai.data_preparation.sync import GitConfig
|
|
@@ -52,6 +53,7 @@ from mage_ai.server.constants import DATA_PREP_SERVER_PORT
|
|
|
52
53
|
from mage_ai.server.docs_server import run_docs_server
|
|
53
54
|
from mage_ai.server.kernel_output_parser import parse_output_message
|
|
54
55
|
from mage_ai.server.kernels import DEFAULT_KERNEL_NAME
|
|
56
|
+
from mage_ai.server.logger import Logger
|
|
55
57
|
from mage_ai.server.scheduler_manager import (
|
|
56
58
|
SCHEDULER_AUTO_RESTART_INTERVAL,
|
|
57
59
|
check_scheduler_status,
|
|
@@ -74,7 +76,7 @@ from mage_ai.settings import (
|
|
|
74
76
|
SHELL_COMMAND,
|
|
75
77
|
USE_UNIQUE_TERMINAL,
|
|
76
78
|
)
|
|
77
|
-
from mage_ai.settings.repo import set_repo_path
|
|
79
|
+
from mage_ai.settings.repo import DEFAULT_MAGE_DATA_DIR, get_repo_name, set_repo_path
|
|
78
80
|
from mage_ai.shared.constants import InstanceType
|
|
79
81
|
from mage_ai.shared.logger import LoggingLevel
|
|
80
82
|
from mage_ai.shared.utils import is_port_in_use
|
|
@@ -85,9 +87,11 @@ BASE_PATH_EXPORTS_FOLDER = 'frontend_dist_base_path'
|
|
|
85
87
|
BASE_PATH_TEMPLATE_EXPORTS_FOLDER = 'frontend_dist_base_path_template'
|
|
86
88
|
BASE_PATH_PLACEHOLDER = 'CLOUD_NOTEBOOK_BASE_PATH_PLACEHOLDER_'
|
|
87
89
|
|
|
90
|
+
logger = Logger().new_server_logger(__name__)
|
|
91
|
+
|
|
88
92
|
|
|
89
93
|
class MainPageHandler(tornado.web.RequestHandler):
|
|
90
|
-
def get(self, *args):
|
|
94
|
+
def get(self, *args, **kwargs):
|
|
91
95
|
self.render('index.html')
|
|
92
96
|
|
|
93
97
|
|
|
@@ -113,16 +117,26 @@ class ApiSchedulerHandler(BaseHandler):
|
|
|
113
117
|
self.write(dict(scheduler=dict(status=scheduler_manager.get_status())))
|
|
114
118
|
|
|
115
119
|
|
|
116
|
-
def replace_base_path(base_path: str) ->
|
|
120
|
+
def replace_base_path(base_path: str) -> str:
|
|
117
121
|
"""
|
|
118
|
-
This function will create
|
|
122
|
+
This function will create the BASE_PATH_EXPORTS_FOLDER and replace all the
|
|
119
123
|
occurrences of CLOUD_NOTEBOOK_BASE_PATH_PLACEHOLDER_ with the base_path parameter.
|
|
120
124
|
|
|
121
125
|
Args:
|
|
122
126
|
base_path (str): The base path to replace the placeholder with.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
str: The path of the frontend static export folder with the replaced base paths.
|
|
123
130
|
"""
|
|
124
131
|
src = os.path.join(os.path.dirname(__file__), BASE_PATH_TEMPLATE_EXPORTS_FOLDER)
|
|
125
|
-
|
|
132
|
+
|
|
133
|
+
directory = get_variables_dir()
|
|
134
|
+
# get_variables_dir can return an s3 path. In that case, use the DEFAULT_MAGE_DATA_DIR
|
|
135
|
+
# directory.
|
|
136
|
+
if directory.startswith('s3'):
|
|
137
|
+
directory = os.path.join(os.path.expanduser(DEFAULT_MAGE_DATA_DIR), get_repo_name())
|
|
138
|
+
os.makedirs(directory, exist_ok=True)
|
|
139
|
+
dst = os.path.join(directory, BASE_PATH_EXPORTS_FOLDER)
|
|
126
140
|
if os.path.exists(dst):
|
|
127
141
|
shutil.rmtree(dst)
|
|
128
142
|
shutil.copytree(src, dst)
|
|
@@ -138,9 +152,10 @@ def replace_base_path(base_path: str) -> None:
|
|
|
138
152
|
# replace favicon
|
|
139
153
|
with open(filepath, 'w', encoding='utf-8') as f:
|
|
140
154
|
f.write(s)
|
|
155
|
+
return dst
|
|
141
156
|
|
|
142
157
|
|
|
143
|
-
def make_app(update_routes: bool = False):
|
|
158
|
+
def make_app(template_dir: str = None, update_routes: bool = False):
|
|
144
159
|
shell_command = SHELL_COMMAND
|
|
145
160
|
if shell_command is None:
|
|
146
161
|
shell_command = 'bash'
|
|
@@ -151,7 +166,8 @@ def make_app(update_routes: bool = False):
|
|
|
151
166
|
term_klass = MageUniqueTermManager
|
|
152
167
|
term_manager = term_klass(shell_command=[shell_command])
|
|
153
168
|
|
|
154
|
-
|
|
169
|
+
if template_dir is None:
|
|
170
|
+
template_dir = os.path.join(os.path.dirname(__file__), EXPORTS_FOLDER)
|
|
155
171
|
routes = [
|
|
156
172
|
(r'/', MainPageHandler),
|
|
157
173
|
(r'/files', MainPageHandler),
|
|
@@ -171,22 +187,22 @@ def make_app(update_routes: bool = False):
|
|
|
171
187
|
(
|
|
172
188
|
r'/_next/static/(.*)',
|
|
173
189
|
tornado.web.StaticFileHandler,
|
|
174
|
-
{'path': os.path.join(
|
|
190
|
+
{'path': os.path.join(template_dir, '_next/static')},
|
|
175
191
|
),
|
|
176
192
|
(
|
|
177
193
|
r'/fonts/(.*)',
|
|
178
194
|
tornado.web.StaticFileHandler,
|
|
179
|
-
{'path': os.path.join(
|
|
195
|
+
{'path': os.path.join(template_dir, 'fonts')},
|
|
180
196
|
),
|
|
181
197
|
(
|
|
182
198
|
r'/images/(.*)',
|
|
183
199
|
tornado.web.StaticFileHandler,
|
|
184
|
-
{'path': os.path.join(
|
|
200
|
+
{'path': os.path.join(template_dir, 'images')},
|
|
185
201
|
),
|
|
186
202
|
(
|
|
187
203
|
r'/(favicon.ico)',
|
|
188
204
|
tornado.web.StaticFileHandler,
|
|
189
|
-
{'path':
|
|
205
|
+
{'path': template_dir},
|
|
190
206
|
),
|
|
191
207
|
(r'/websocket/', WebSocketServer),
|
|
192
208
|
(r'/websocket/terminal', TerminalWebsocketServer, {'term_manager': term_manager}),
|
|
@@ -231,7 +247,9 @@ def make_app(update_routes: bool = False):
|
|
|
231
247
|
(r'/api/(?P<resource>\w+)/(?P<pk>.+)', ApiResourceDetailHandler),
|
|
232
248
|
(r'/files', MainPageHandler),
|
|
233
249
|
(r'/global-data-products', MainPageHandler),
|
|
250
|
+
(r'/global-data-products/(?P<uuid>\w+)', MainPageHandler),
|
|
234
251
|
(r'/templates', MainPageHandler),
|
|
252
|
+
(r'/templates/(?P<uuid>\w+)', MainPageHandler),
|
|
235
253
|
(r'/version-control', MainPageHandler),
|
|
236
254
|
]
|
|
237
255
|
|
|
@@ -249,7 +267,7 @@ def make_app(update_routes: bool = False):
|
|
|
249
267
|
return tornado.web.Application(
|
|
250
268
|
updated_routes,
|
|
251
269
|
autoreload=True,
|
|
252
|
-
template_path=
|
|
270
|
+
template_path=template_dir,
|
|
253
271
|
)
|
|
254
272
|
|
|
255
273
|
|
|
@@ -262,15 +280,22 @@ async def main(
|
|
|
262
280
|
|
|
263
281
|
# Update base path if environment variable is set
|
|
264
282
|
update_routes = False
|
|
265
|
-
|
|
283
|
+
template_dir = None
|
|
266
284
|
if BASE_PATH:
|
|
267
285
|
try:
|
|
268
|
-
replace_base_path(BASE_PATH)
|
|
286
|
+
template_dir = replace_base_path(BASE_PATH)
|
|
269
287
|
update_routes = True
|
|
270
288
|
except Exception:
|
|
271
|
-
|
|
289
|
+
logger.warning(
|
|
290
|
+
'Server failed to replace base path with error:\n%s',
|
|
291
|
+
traceback.format_exc(),
|
|
292
|
+
)
|
|
293
|
+
logger.warning('Continuing with default routes...')
|
|
272
294
|
|
|
273
|
-
app = make_app(
|
|
295
|
+
app = make_app(
|
|
296
|
+
update_routes=update_routes,
|
|
297
|
+
template_dir=template_dir,
|
|
298
|
+
)
|
|
274
299
|
|
|
275
300
|
port = int(port)
|
|
276
301
|
max_port = port + 100
|
|
@@ -290,7 +315,7 @@ async def main(
|
|
|
290
315
|
if update_routes:
|
|
291
316
|
url = f'{url}/{BASE_PATH}'
|
|
292
317
|
webbrowser.open_new_tab(url)
|
|
293
|
-
|
|
318
|
+
logger.info(f'Mage is running at {url} and serving project {project}')
|
|
294
319
|
|
|
295
320
|
db_connection.start_session(force=True)
|
|
296
321
|
|
|
@@ -302,18 +327,18 @@ async def main(
|
|
|
302
327
|
try:
|
|
303
328
|
sync = GitSync(sync_config)
|
|
304
329
|
sync.sync_data()
|
|
305
|
-
|
|
330
|
+
logger.info(
|
|
306
331
|
f'Successfully synced data from git repo: {sync_config.remote_repo_link}'
|
|
307
332
|
f', branch: {sync_config.branch}'
|
|
308
333
|
)
|
|
309
334
|
except Exception as err:
|
|
310
|
-
|
|
335
|
+
logger.info(
|
|
311
336
|
f'Failed to sync data from git repo: {sync_config.remote_repo_link}'
|
|
312
337
|
f', branch: {sync_config.branch} with error: {str(err)}'
|
|
313
338
|
)
|
|
314
339
|
|
|
315
340
|
if REQUIRE_USER_AUTHENTICATION:
|
|
316
|
-
|
|
341
|
+
logger.info('User authentication is enabled.')
|
|
317
342
|
# We need to sleep for a few seconds after creating all the tables or else there
|
|
318
343
|
# may be an error trying to create users.
|
|
319
344
|
sleep(5)
|
|
@@ -327,7 +352,7 @@ async def main(
|
|
|
327
352
|
default_owner_role = Role.get_role(Role.DefaultRole.OWNER)
|
|
328
353
|
owner_users = default_owner_role.users if default_owner_role else []
|
|
329
354
|
if not legacy_owner_user and len(owner_users) == 0:
|
|
330
|
-
|
|
355
|
+
logger.info('User with owner permission doesn’t exist, creating owner user.')
|
|
331
356
|
if AUTHENTICATION_MODE.lower() == 'ldap':
|
|
332
357
|
user = User.create(
|
|
333
358
|
roles_new=[default_owner_role],
|
|
@@ -352,7 +377,8 @@ async def main(
|
|
|
352
377
|
Oauth2Application.client_id == OAUTH2_APPLICATION_CLIENT_ID,
|
|
353
378
|
).first()
|
|
354
379
|
if not oauth_client:
|
|
355
|
-
|
|
380
|
+
logger.info(
|
|
381
|
+
'OAuth2 application doesn’t exist for frontend, creating OAuth2 application.')
|
|
356
382
|
oauth_client = Oauth2Application.create(
|
|
357
383
|
client_id=OAUTH2_APPLICATION_CLIENT_ID,
|
|
358
384
|
client_type=Oauth2Application.ClientType.PUBLIC,
|
|
@@ -360,13 +386,13 @@ async def main(
|
|
|
360
386
|
user_id=owner_user.id,
|
|
361
387
|
)
|
|
362
388
|
|
|
363
|
-
|
|
389
|
+
logger.info('Initializing block cache.')
|
|
364
390
|
await BlockCache.initialize_cache(replace=True)
|
|
365
391
|
|
|
366
|
-
|
|
392
|
+
logger.info('Initializing tag cache.')
|
|
367
393
|
await TagCache.initialize_cache(replace=True)
|
|
368
394
|
|
|
369
|
-
|
|
395
|
+
logger.info('Initializing block action object cache.')
|
|
370
396
|
await BlockActionObjectCache.initialize_cache(replace=True)
|
|
371
397
|
|
|
372
398
|
# Check scheduler status periodically
|
|
@@ -414,7 +440,7 @@ def start_server(
|
|
|
414
440
|
project_uuid=project_uuid,
|
|
415
441
|
)
|
|
416
442
|
set_repo_path(project)
|
|
417
|
-
|
|
443
|
+
init_project_uuid()
|
|
418
444
|
|
|
419
445
|
asyncio.run(UsageStatisticLogger().project_impression())
|
|
420
446
|
|
mage_ai/services/spark/spark.py
CHANGED
|
@@ -1,8 +1,63 @@
|
|
|
1
1
|
from mage_ai.services.spark.config import SparkConfig
|
|
2
|
+
from typing import List
|
|
2
3
|
import os
|
|
3
4
|
|
|
4
5
|
|
|
6
|
+
def get_file_names(jars: List) -> List:
|
|
7
|
+
"""
|
|
8
|
+
Extracts file names from a list of jar files.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
jars (List): A list of jar files.
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
List: A list of file names.
|
|
15
|
+
"""
|
|
16
|
+
if jars is None:
|
|
17
|
+
return None
|
|
18
|
+
|
|
19
|
+
return [os.path.basename(jar) for jar in jars]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def contains_same_jars(jars_1: List, jars_2: List) -> bool:
|
|
23
|
+
"""
|
|
24
|
+
Checks if two lists of jar files contain the same jars.
|
|
25
|
+
The order of the jars in the list does not matter.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
jars_1 (List): A list of jar files.
|
|
29
|
+
jars_2 (List): A list of jar files.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
bool: True if the lists contain the same jars, False otherwise.
|
|
33
|
+
"""
|
|
34
|
+
if jars_1 is None and jars_2 is None:
|
|
35
|
+
return True
|
|
36
|
+
|
|
37
|
+
if jars_1 is None or jars_2 is None:
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
if len(jars_1) != len(jars_2):
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
file_names_1 = get_file_names(jars_1)
|
|
44
|
+
file_names_2 = get_file_names(jars_2)
|
|
45
|
+
|
|
46
|
+
return set(file_names_1) == set(file_names_2)
|
|
47
|
+
|
|
48
|
+
|
|
5
49
|
def has_same_spark_config(spark_session, spark_config: SparkConfig) -> bool:
|
|
50
|
+
"""
|
|
51
|
+
Checks if the spark session has the same configuration as the spark config.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
spark_session (SparkSession): The spark session.
|
|
55
|
+
spark_config (SparkConfig): The spark config.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
bool: True if the spark session has the same configuration as the
|
|
59
|
+
spark config, False otherwise.
|
|
60
|
+
"""
|
|
6
61
|
if spark_session is None:
|
|
7
62
|
return False
|
|
8
63
|
|
|
@@ -24,8 +79,8 @@ def has_same_spark_config(spark_session, spark_config: SparkConfig) -> bool:
|
|
|
24
79
|
if spark_session.conf.get(f'spark.executorEnv.{key}') != value:
|
|
25
80
|
print(f'Different spark.executorEnv.{key} found!')
|
|
26
81
|
return False
|
|
27
|
-
if (spark_config.spark_jars and
|
|
28
|
-
|
|
82
|
+
if (spark_config.spark_jars and not contains_same_jars(
|
|
83
|
+
spark_config.spark_jars, spark_session.conf.get('spark.jars'))):
|
|
29
84
|
print('Different spark.jars found!')
|
|
30
85
|
return False
|
|
31
86
|
if spark_config.others:
|
|
@@ -37,6 +92,24 @@ def has_same_spark_config(spark_session, spark_config: SparkConfig) -> bool:
|
|
|
37
92
|
|
|
38
93
|
|
|
39
94
|
def get_spark_session(spark_config: SparkConfig):
|
|
95
|
+
"""
|
|
96
|
+
Gets a Spark session.
|
|
97
|
+
If the given spark_config is None, then create a Spark session with the
|
|
98
|
+
default configuration.
|
|
99
|
+
If the given spark_config is not None, then check if the active Spark
|
|
100
|
+
session has the same configuration as the given spark_config.
|
|
101
|
+
If the active Spark session has the same configuration as the given
|
|
102
|
+
spark_config, then reuse the active Spark session.
|
|
103
|
+
If the active Spark session does not have the same configuration as the
|
|
104
|
+
given spark_config, then create a new Spark session with the given
|
|
105
|
+
spark_config.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
spark_config (SparkConfig): The Spark configuration.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
SparkSession: The Spark session.
|
|
112
|
+
"""
|
|
40
113
|
from pyspark.conf import SparkConf
|
|
41
114
|
from pyspark.sql import SparkSession
|
|
42
115
|
|
mage_ai/streaming/constants.py
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import json
|
|
3
|
+
import time
|
|
1
4
|
from dataclasses import dataclass
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import Callable, Dict
|
|
7
|
+
|
|
2
8
|
from kafka import KafkaConsumer
|
|
9
|
+
|
|
3
10
|
from mage_ai.shared.config import BaseConfig
|
|
4
|
-
from mage_ai.streaming.constants import DEFAULT_BATCH_SIZE
|
|
11
|
+
from mage_ai.streaming.constants import DEFAULT_BATCH_SIZE, DEFAULT_TIMEOUT_MS
|
|
5
12
|
from mage_ai.streaming.sources.base import BaseSource
|
|
6
|
-
from mage_ai.streaming.sources.shared import
|
|
7
|
-
from enum import Enum
|
|
8
|
-
from typing import Callable, Dict
|
|
9
|
-
import importlib
|
|
10
|
-
import json
|
|
11
|
-
import time
|
|
13
|
+
from mage_ai.streaming.sources.shared import SerDeConfig, SerializationMethod
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class SecurityProtocol(str, Enum):
|
|
@@ -39,6 +41,7 @@ class KafkaConfig(BaseConfig):
|
|
|
39
41
|
topic: str
|
|
40
42
|
api_version: str = '0.10.2'
|
|
41
43
|
batch_size: int = DEFAULT_BATCH_SIZE
|
|
44
|
+
timeout_ms: int = DEFAULT_TIMEOUT_MS
|
|
42
45
|
security_protocol: SecurityProtocol = None
|
|
43
46
|
ssl_config: SSLConfig = None
|
|
44
47
|
sasl_config: SASLConfig = None
|
|
@@ -138,16 +141,21 @@ class KafkaSource(BaseSource):
|
|
|
138
141
|
batch_size = self.config.batch_size
|
|
139
142
|
else:
|
|
140
143
|
batch_size = DEFAULT_BATCH_SIZE
|
|
144
|
+
if self.config.timeout_ms > 0:
|
|
145
|
+
timeout_ms = self.config.timeout_ms
|
|
146
|
+
else:
|
|
147
|
+
timeout_ms = DEFAULT_TIMEOUT_MS
|
|
148
|
+
|
|
141
149
|
while True:
|
|
142
150
|
# Response format is {TopicPartiton('topic1', 1): [msg1, msg2]}
|
|
143
151
|
msg_pack = self.consumer.poll(
|
|
144
152
|
max_records=batch_size,
|
|
145
|
-
timeout_ms=
|
|
153
|
+
timeout_ms=timeout_ms,
|
|
146
154
|
)
|
|
147
155
|
|
|
148
156
|
message_values = []
|
|
149
157
|
msg_printed = False
|
|
150
|
-
for
|
|
158
|
+
for _tp, messages in msg_pack.items():
|
|
151
159
|
for message in messages:
|
|
152
160
|
if not msg_printed:
|
|
153
161
|
self.__print_message(message)
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from mage_ai.data_preparation.models.custom_templates.custom_block_template import (
|
|
5
|
+
CustomBlockTemplate,
|
|
6
|
+
)
|
|
7
|
+
from mage_ai.data_preparation.models.custom_templates.utils import group_and_hydrate_files
|
|
8
|
+
from mage_ai.shared.array import find
|
|
9
|
+
from mage_ai.tests.base_test import DBTestCase
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CustomTemplatesUtilsTest(DBTestCase):
|
|
13
|
+
def test_group_and_hydrate_files(self):
|
|
14
|
+
file_dicts = [
|
|
15
|
+
None,
|
|
16
|
+
dict(parent_names=None),
|
|
17
|
+
dict(parent_names=[]),
|
|
18
|
+
dict(parent_names=[None]),
|
|
19
|
+
dict(parent_names=['mage']),
|
|
20
|
+
dict(parent_names=['mage', 'fire']),
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
def load(template_uuid: str):
|
|
24
|
+
return CustomBlockTemplate(template_uuid=template_uuid)
|
|
25
|
+
|
|
26
|
+
with patch.object(
|
|
27
|
+
CustomBlockTemplate,
|
|
28
|
+
'load',
|
|
29
|
+
load,
|
|
30
|
+
):
|
|
31
|
+
arr = group_and_hydrate_files(file_dicts, CustomBlockTemplate)
|
|
32
|
+
|
|
33
|
+
self.assertTrue(find(lambda x: x.template_uuid == '', arr))
|
|
34
|
+
self.assertTrue(find(lambda x: x.template_uuid == 'None', arr))
|
|
35
|
+
self.assertTrue(find(lambda x: x.template_uuid == 'mage', arr))
|
|
36
|
+
self.assertTrue(find(lambda x: x.template_uuid == 'mage/fire', arr))
|
|
@@ -542,3 +542,51 @@ SELECT 1 AS id;
|
|
|
542
542
|
|
|
543
543
|
block2 = pipeline.get_block('test_transformer')
|
|
544
544
|
self.assertEqual([], block2.upstream_block_uuids)
|
|
545
|
+
|
|
546
|
+
def test_execute_block_from_notebook(self):
|
|
547
|
+
pipeline = Pipeline.create(
|
|
548
|
+
'test_pipeline_execute_block_function_from_notebook',
|
|
549
|
+
repo_path=self.repo_path,
|
|
550
|
+
)
|
|
551
|
+
block = Block.create('test_data_loader', 'data_loader', self.repo_path, pipeline=pipeline)
|
|
552
|
+
|
|
553
|
+
with open(block.file_path, 'w') as file:
|
|
554
|
+
file.write("""import pandas as pd
|
|
555
|
+
if 'data_loader' not in globals():
|
|
556
|
+
from mage_ai.data_preparation.decorators import data_loader
|
|
557
|
+
|
|
558
|
+
@data_loader
|
|
559
|
+
def load_data():
|
|
560
|
+
data = {'col1': [1, 3], 'col2': [2, 4]}
|
|
561
|
+
df = pd.DataFrame(data)
|
|
562
|
+
return df
|
|
563
|
+
""")
|
|
564
|
+
|
|
565
|
+
output = block._execute_block(dict(), from_notebook=True)
|
|
566
|
+
self.assertIsNotNone(block.module)
|
|
567
|
+
self.assertEqual(len(output), 1)
|
|
568
|
+
|
|
569
|
+
def test_execute_block_from_notebook_no_decorator_definition(self):
|
|
570
|
+
pipeline = Pipeline.create(
|
|
571
|
+
'test_pipeline_execute_block_function_from_notebook_no_decorator_definition',
|
|
572
|
+
repo_path=self.repo_path,
|
|
573
|
+
)
|
|
574
|
+
block = Block.create('test_data_loader', 'data_loader', self.repo_path, pipeline=pipeline)
|
|
575
|
+
|
|
576
|
+
with open(block.file_path, 'w') as file:
|
|
577
|
+
file.write("""import pandas as pd
|
|
578
|
+
|
|
579
|
+
@data_loader
|
|
580
|
+
def load_data():
|
|
581
|
+
data = {'col1': [1, 3], 'col2': [2, 4]}
|
|
582
|
+
df = pd.DataFrame(data)
|
|
583
|
+
return df
|
|
584
|
+
|
|
585
|
+
@test
|
|
586
|
+
def test_output(output, *args) -> None:
|
|
587
|
+
assert output is not None, 'The output is undefined'
|
|
588
|
+
""")
|
|
589
|
+
|
|
590
|
+
output = block._execute_block(dict(), from_notebook=True)
|
|
591
|
+
self.assertIsNotNone(block.module)
|
|
592
|
+
self.assertEqual(len(output), 1)
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import shutil
|
|
3
3
|
import uuid
|
|
4
|
+
from unittest.mock import patch
|
|
4
5
|
|
|
5
6
|
import yaml
|
|
6
7
|
|
|
7
|
-
from mage_ai.data_preparation.repo_manager import
|
|
8
|
+
from mage_ai.data_preparation.repo_manager import (
|
|
9
|
+
RepoConfig,
|
|
10
|
+
get_project_uuid,
|
|
11
|
+
set_project_uuid_from_metadata,
|
|
12
|
+
)
|
|
8
13
|
from mage_ai.settings.repo import MAGE_DATA_DIR_ENV_VAR
|
|
9
14
|
from mage_ai.tests.base_test import DBTestCase
|
|
10
15
|
|
|
@@ -71,3 +76,16 @@ class RepoManagerTest(DBTestCase):
|
|
|
71
76
|
)
|
|
72
77
|
test_dir = os.path.expanduser(f'~/{dir_name}')
|
|
73
78
|
shutil.rmtree(test_dir)
|
|
79
|
+
|
|
80
|
+
def test_set_project_uuid_from_metadata(self):
|
|
81
|
+
test_metadata_file = os.path.join(self.repo_path, 'test_repo_manager.yaml')
|
|
82
|
+
with open(test_metadata_file, 'w', encoding='utf-8') as f:
|
|
83
|
+
yaml.dump(dict(project_uuid='123456789'), f)
|
|
84
|
+
|
|
85
|
+
with patch(
|
|
86
|
+
'mage_ai.data_preparation.repo_manager.get_metadata_path',
|
|
87
|
+
return_value=test_metadata_file
|
|
88
|
+
):
|
|
89
|
+
set_project_uuid_from_metadata()
|
|
90
|
+
self.assertEqual(get_project_uuid(), '123456789')
|
|
91
|
+
os.remove(test_metadata_file)
|
|
@@ -52,7 +52,9 @@ class ServerTests(TestCase):
|
|
|
52
52
|
self.assertIsNone(handler)
|
|
53
53
|
|
|
54
54
|
@patch('mage_ai.server.server.BASE_PATH', 'random-test-string-1hasdfh')
|
|
55
|
-
|
|
55
|
+
@patch('mage_ai.server.server.get_variables_dir')
|
|
56
|
+
def test_replace_base_path(self, mock_variables_dir):
|
|
57
|
+
mock_variables_dir.return_value = os.path.dirname(server_module.__file__)
|
|
56
58
|
with patch(
|
|
57
59
|
'mage_ai.server.server.BASE_PATH_EXPORTS_FOLDER',
|
|
58
60
|
'base_path_test',
|
|
@@ -66,7 +68,9 @@ class ServerTests(TestCase):
|
|
|
66
68
|
shutil.rmtree(test_dir)
|
|
67
69
|
|
|
68
70
|
@patch('mage_ai.server.server.BASE_PATH', 'test_prefix')
|
|
69
|
-
|
|
71
|
+
@patch('mage_ai.server.server.get_variables_dir')
|
|
72
|
+
def test_replace_base_path_directory_exists(self, mock_variables_dir):
|
|
73
|
+
mock_variables_dir.return_value = os.path.dirname(server_module.__file__)
|
|
70
74
|
test_dir = os.path.join(os.path.dirname(server_module.__file__), 'base_path_test')
|
|
71
75
|
os.makedirs(test_dir)
|
|
72
76
|
with patch(
|
|
@@ -77,3 +81,17 @@ class ServerTests(TestCase):
|
|
|
77
81
|
|
|
78
82
|
self.assertTrue(len(os.listdir(test_dir)) > 0)
|
|
79
83
|
shutil.rmtree(test_dir)
|
|
84
|
+
|
|
85
|
+
@patch('mage_ai.server.server.BASE_PATH', 'test_prefix')
|
|
86
|
+
@patch('mage_ai.server.server.get_variables_dir')
|
|
87
|
+
def test_replace_base_path_s3_directory(self, mock_variables_dir):
|
|
88
|
+
mock_variables_dir.return_value = 's3://test-bucket/test-prefix'
|
|
89
|
+
test_dir = os.path.join(self.repo_path, 'base_path_test')
|
|
90
|
+
with patch(
|
|
91
|
+
'mage_ai.server.server.DEFAULT_MAGE_DATA_DIR',
|
|
92
|
+
test_dir,
|
|
93
|
+
):
|
|
94
|
+
replace_base_path(base_path='test_prefix')
|
|
95
|
+
|
|
96
|
+
self.assertTrue(len(os.listdir(os.path.join(test_dir, 'test'))) > 0)
|
|
97
|
+
shutil.rmtree(test_dir)
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from mage_ai.services.spark.spark import contains_same_jars, get_file_names
|
|
2
|
+
from mage_ai.tests.base_test import TestCase
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SparkTests(TestCase):
|
|
6
|
+
def test_get_file_names(self):
|
|
7
|
+
self.assertEqual(
|
|
8
|
+
get_file_names(['/home/spark-jars/aws-java-sdk-core-1.11.1026.jar']),
|
|
9
|
+
['aws-java-sdk-core-1.11.1026.jar']
|
|
10
|
+
)
|
|
11
|
+
self.assertEqual(
|
|
12
|
+
get_file_names(['spark://************:2222/jars/aws-java-sdk-core-1.11.1026.jar']),
|
|
13
|
+
['aws-java-sdk-core-1.11.1026.jar']
|
|
14
|
+
)
|
|
15
|
+
self.assertEqual(
|
|
16
|
+
get_file_names(['/home/spark-jars/test1.jar', '/home/spark-jars/test2.jar']),
|
|
17
|
+
['test1.jar', 'test2.jar']
|
|
18
|
+
)
|
|
19
|
+
self.assertEqual(
|
|
20
|
+
get_file_names([
|
|
21
|
+
'spark://************:2222/jars/test1.jar',
|
|
22
|
+
'spark://************:2222/jars/test2.jar']),
|
|
23
|
+
['test1.jar', 'test2.jar']
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def test_contains_same_jars(self):
|
|
27
|
+
self.assertTrue(
|
|
28
|
+
contains_same_jars(
|
|
29
|
+
['/home/spark-jars/aws-java-sdk-core-1.11.1026.jar'],
|
|
30
|
+
['aws-java-sdk-core-1.11.1026.jar'])
|
|
31
|
+
)
|
|
32
|
+
self.assertTrue(
|
|
33
|
+
contains_same_jars(
|
|
34
|
+
['spark://************:2222/jars/aws-java-sdk-core-1.11.1026.jar'],
|
|
35
|
+
['aws-java-sdk-core-1.11.1026.jar'])
|
|
36
|
+
)
|
|
37
|
+
self.assertTrue(
|
|
38
|
+
contains_same_jars(
|
|
39
|
+
['/home/spark-jars/aws-java-sdk-core-1.11.1026.jar'],
|
|
40
|
+
['spark://************:2222/jars/aws-java-sdk-core-1.11.1026.jar'])
|
|
41
|
+
)
|
|
42
|
+
self.assertTrue(
|
|
43
|
+
contains_same_jars(
|
|
44
|
+
['/home/spark-jars/test1.jar', '/home/spark-jars/test2.jar'],
|
|
45
|
+
['spark://************:2222/jars/test2.jar',
|
|
46
|
+
'spark://************:2222/jars/test1.jar'])
|
|
47
|
+
)
|
|
48
|
+
self.assertFalse(
|
|
49
|
+
contains_same_jars(
|
|
50
|
+
['/home/spark-jars/test1.jar', '/home/spark-jars/test2.jar'],
|
|
51
|
+
['spark://************:2222/jars/test1.jar'])
|
|
52
|
+
)
|