mage-ai 0.9.68__py3-none-any.whl → 0.9.70__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/policies/BackfillPolicy.py +1 -0
- mage_ai/api/policies/PipelinePolicy.py +1 -0
- mage_ai/api/policies/WorkspacePolicy.py +1 -0
- mage_ai/api/presenters/BackfillPresenter.py +1 -0
- mage_ai/api/resources/GitBranchResource.py +56 -23
- mage_ai/api/resources/GitCustomBranchResource.py +29 -1
- mage_ai/api/resources/OauthResource.py +1 -1
- mage_ai/api/resources/PipelineResource.py +11 -5
- mage_ai/api/resources/PipelineRunResource.py +41 -4
- mage_ai/api/resources/PipelineScheduleResource.py +4 -0
- mage_ai/api/resources/PullRequestResource.py +6 -4
- mage_ai/api/resources/SeedResource.py +2 -1
- mage_ai/api/resources/SessionResource.py +13 -1
- mage_ai/api/resources/WorkspaceResource.py +5 -4
- mage_ai/authentication/permissions/constants.py +2 -0
- mage_ai/authentication/permissions/seed.py +32 -21
- mage_ai/authentication/providers/active_directory.py +4 -3
- mage_ai/authentication/providers/okta.py +22 -83
- mage_ai/cache/block_action_object/__init__.py +1 -1
- mage_ai/cluster_manager/kubernetes/workload_manager.py +52 -1
- mage_ai/cluster_manager/workspace/base.py +6 -0
- mage_ai/cluster_manager/workspace/kubernetes.py +22 -1
- mage_ai/command_center/applications/utils.py +2 -2
- mage_ai/command_center/presenters/text.py +1 -1
- mage_ai/data_preparation/executors/k8s_block_executor.py +30 -7
- mage_ai/data_preparation/executors/k8s_pipeline_executor.py +30 -7
- mage_ai/data_preparation/executors/streaming_pipeline_executor.py +78 -8
- mage_ai/data_preparation/git/__init__.py +50 -22
- mage_ai/data_preparation/git/api.py +62 -7
- mage_ai/data_preparation/git/utils.py +45 -21
- mage_ai/data_preparation/models/block/__init__.py +31 -8
- mage_ai/data_preparation/models/block/data_integration/mixins.py +16 -5
- mage_ai/data_preparation/models/block/dynamic/child.py +3 -0
- mage_ai/data_preparation/models/block/dynamic/utils.py +9 -4
- mage_ai/data_preparation/models/block/dynamic/variables.py +2 -2
- mage_ai/data_preparation/models/block/extension/utils.py +1 -0
- mage_ai/data_preparation/models/block/global_data_product/__init__.py +25 -2
- mage_ai/data_preparation/models/block/integration/__init__.py +1 -1
- mage_ai/data_preparation/models/block/remote/__init__.py +0 -0
- mage_ai/data_preparation/models/block/remote/models.py +58 -0
- mage_ai/data_preparation/models/block/sql/__init__.py +1 -1
- mage_ai/data_preparation/models/block/utils.py +38 -0
- mage_ai/data_preparation/models/constants.py +2 -0
- mage_ai/data_preparation/models/global_data_product/__init__.py +12 -0
- mage_ai/data_preparation/models/pipeline.py +31 -11
- mage_ai/data_preparation/models/triggers/__init__.py +4 -2
- mage_ai/data_preparation/models/utils.py +6 -0
- mage_ai/data_preparation/models/variable.py +18 -4
- mage_ai/data_preparation/repo_manager.py +3 -2
- mage_ai/data_preparation/shared/utils.py +1 -1
- mage_ai/data_preparation/storage/local_storage.py +12 -6
- mage_ai/data_preparation/templates/data_exporters/mysql.py +2 -2
- mage_ai/data_preparation/templates/data_exporters/oracledb.py +27 -0
- mage_ai/data_preparation/templates/repo/metadata.yaml +1 -0
- mage_ai/io/bigquery.py +131 -58
- mage_ai/io/mysql.py +38 -6
- mage_ai/io/snowflake.py +152 -29
- mage_ai/orchestration/db/migrations/versions/42a14d6143f1_update_token_column_type.py +54 -0
- mage_ai/orchestration/db/models/oauth.py +14 -13
- mage_ai/orchestration/db/models/schedules.py +30 -2
- mage_ai/orchestration/job_manager.py +6 -0
- mage_ai/orchestration/notification/sender.py +37 -15
- mage_ai/orchestration/pipeline_scheduler_original.py +48 -31
- mage_ai/orchestration/queue/celery_queue.py +8 -1
- mage_ai/orchestration/queue/process_queue.py +67 -4
- mage_ai/orchestration/queue/queue.py +8 -0
- mage_ai/orchestration/triggers/api.py +29 -1
- mage_ai/orchestration/triggers/global_data_product.py +9 -4
- mage_ai/orchestration/triggers/utils.py +10 -1
- mage_ai/orchestration/utils/resources.py +3 -0
- mage_ai/server/api/downloads.py +4 -1
- mage_ai/server/api/runs.py +151 -0
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +6 -6
- mage_ai/server/frontend_dist/_next/static/{i8pymuJDTVHdWjUP1QSh1 → RhDiJSkcjCsh4xxX4BFBk}/_buildManifest.js +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1557-b3502f3f1aa92ac7.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/2717-d9200be634dd6766.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3548-9d26185b3fb663b1.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/5699-6d708c6b2153ea08.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7361-8a23dd8360593e7a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/7966-b9b85ba10667e654.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/9624-8b8e100079ab69e1.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-2a69553d8c6eeb53.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/index-4e12783b064c1cfe.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-4bfc84ff07d7656f.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-a66b4c7641ae03eb.js → frontend_dist/_next/static/chunks/pages/pipeline-runs-6d183f91a2ff6668.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-7181b086c93784d2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-38e1fbcfbfc1014e.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-b645a6d13ab9fe3a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-59aca25a5b1d3998.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-eb11c5390c982b49.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-cb88fd075a357fcf.js → triggers-4612d15a65c35912.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-3591d035bb3bb2b8.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-32985f3f7c7dd3ab.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/settings-c2e9ef989c8bfa73.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-349af617d05f001b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-60d01d3887e31136.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{users-86814e581acaf5db.js → users-a4db8710f703c729.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/sign-in-09414a8b66fb6f06.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/triggers-9cba3211434a8966.js → frontend_dist/_next/static/chunks/pages/triggers-a599c6ac89be8c8d.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-3433c8b22e8342aa.js +1 -0
- 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 +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]/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 +6 -6
- 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 +6 -6
- mage_ai/server/frontend_dist_base_path_template/_next/static/{CKCvjsYCf2imD2X8zAOBf → TdpLLFome13qvM0gXvpHs}/_buildManifest.js +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1557-b3502f3f1aa92ac7.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-d9200be634dd6766.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3548-9d26185b3fb663b1.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5699-6d708c6b2153ea08.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7361-8a23dd8360593e7a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7966-b9b85ba10667e654.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-8b8e100079ab69e1.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-2a69553d8c6eeb53.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/index-4e12783b064c1cfe.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-4bfc84ff07d7656f.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipeline-runs-a66b4c7641ae03eb.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-6d183f91a2ff6668.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-7181b086c93784d2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-38e1fbcfbfc1014e.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-b645a6d13ab9fe3a.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-59aca25a5b1d3998.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-eb11c5390c982b49.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-cb88fd075a357fcf.js → triggers-4612d15a65c35912.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-3591d035bb3bb2b8.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-32985f3f7c7dd3ab.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-c2e9ef989c8bfa73.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-349af617d05f001b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-60d01d3887e31136.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{users-86814e581acaf5db.js → users-a4db8710f703c729.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-09414a8b66fb6f06.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/triggers-9cba3211434a8966.js → frontend_dist_base_path_template/_next/static/chunks/pages/triggers-a599c6ac89be8c8d.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-3433c8b22e8342aa.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 +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]/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 +6 -6
- 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/server/scheduler_manager.py +9 -0
- mage_ai/server/server.py +47 -17
- mage_ai/server/utils/output_display.py +2 -2
- mage_ai/server/websocket_server.py +1 -0
- mage_ai/services/aws/ecs/ecs.py +1 -0
- mage_ai/services/k8s/config.py +4 -4
- mage_ai/services/k8s/utils.py +97 -0
- mage_ai/settings/keys/auth.py +2 -0
- mage_ai/settings/server.py +1 -1
- mage_ai/shared/parsers.py +6 -1
- mage_ai/streaming/sources/influxdb.py +2 -0
- mage_ai/streaming/sources/kafka.py +1 -1
- mage_ai/tests/api/endpoints/mixins.py +10 -9
- mage_ai/tests/api/endpoints/test_seeds.py +24 -0
- mage_ai/tests/api/operations/base/mixins.py +1 -1
- mage_ai/tests/api/operations/test_sessions.py +53 -2
- mage_ai/tests/api/resources/test_pipeline_resource.py +2 -2
- mage_ai/tests/authentication/oauth/test_utils.py +1 -1
- mage_ai/tests/authentication/providers/test_okta.py +43 -0
- mage_ai/tests/data_preparation/models/block/test_global_data_product.py +2 -0
- mage_ai/tests/orchestration/db/models/test_oauth.py +3 -3
- mage_ai/tests/orchestration/queue/test_process_queue.py +1 -0
- mage_ai/tests/orchestration/triggers/test_global_data_product.py +138 -136
- mage_ai/tests/server/test_server.py +27 -4
- mage_ai/tests/services/k8s/test_job_manager.py +9 -6
- mage_ai/version_control/branch/utils.py +2 -1
- mage_ai/version_control/models.py +3 -2
- {mage_ai-0.9.68.dist-info → mage_ai-0.9.70.dist-info}/METADATA +5 -5
- {mage_ai-0.9.68.dist-info → mage_ai-0.9.70.dist-info}/RECORD +272 -264
- mage_ai/server/frontend_dist/_next/static/chunks/1557-01f0843dc6ac4971.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2717-b5f9575799b594d5.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3548-961ff79ca70038c7.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/5699-6efc749f2f8ddd20.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7361-18d9d8be96e1ce97.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/7966-f07b2913f7326b50.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9624-59b2f803f9c88cd6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-08790743315de36a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/index-13760bb72d823b69.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-852d403c7bda21b3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a8b61d8d239fd16f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-bd0aff5a5ed8888c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-d1ee961387c58b7f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-f028ef3880ed856c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-ceb06e1616ee9610.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-8ff16ef9566e911a.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/settings-74d76300942dcee8.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-d7a8bc51bb7a1082.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-79a4cf66a623e667.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/sign-in-f59d34429fe022ee.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1557-01f0843dc6ac4971.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-b5f9575799b594d5.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3548-961ff79ca70038c7.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/5699-6efc749f2f8ddd20.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7361-18d9d8be96e1ce97.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7966-f07b2913f7326b50.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9624-59b2f803f9c88cd6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-08790743315de36a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/index-13760bb72d823b69.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-852d403c7bda21b3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-a8b61d8d239fd16f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-bd0aff5a5ed8888c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-d1ee961387c58b7f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-f028ef3880ed856c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-ceb06e1616ee9610.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-8ff16ef9566e911a.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-74d76300942dcee8.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-d7a8bc51bb7a1082.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-79a4cf66a623e667.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-f59d34429fe022ee.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +0 -1
- /mage_ai/server/frontend_dist/_next/static/{i8pymuJDTVHdWjUP1QSh1 → RhDiJSkcjCsh4xxX4BFBk}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{CKCvjsYCf2imD2X8zAOBf → TdpLLFome13qvM0gXvpHs}/_ssgManifest.js +0 -0
- {mage_ai-0.9.68.dist-info → mage_ai-0.9.70.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.68.dist-info → mage_ai-0.9.70.dist-info}/WHEEL +0 -0
- {mage_ai-0.9.68.dist-info → mage_ai-0.9.70.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.68.dist-info → mage_ai-0.9.70.dist-info}/top_level.txt +0 -0
|
@@ -19,9 +19,11 @@ from mage_ai.data_preparation.git.utils import (
|
|
|
19
19
|
check_connection_async,
|
|
20
20
|
create_ssh_keys,
|
|
21
21
|
get_access_token,
|
|
22
|
+
get_oauth_access_token_for_user,
|
|
22
23
|
get_provider_from_remote_url,
|
|
23
24
|
poll_process_with_timeout,
|
|
24
25
|
run_command,
|
|
26
|
+
validate_authentication_for_remote_url,
|
|
25
27
|
)
|
|
26
28
|
from mage_ai.data_preparation.preferences import get_preferences
|
|
27
29
|
from mage_ai.data_preparation.sync import AuthType, GitConfig
|
|
@@ -79,8 +81,7 @@ class Git:
|
|
|
79
81
|
if setup_repo:
|
|
80
82
|
self.__setup_repo()
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
self.__set_git_config()
|
|
84
|
+
self.__set_git_config()
|
|
84
85
|
|
|
85
86
|
if self.remote_repo_link and self.repo:
|
|
86
87
|
try:
|
|
@@ -162,6 +163,9 @@ class Git:
|
|
|
162
163
|
|
|
163
164
|
git_config = GitConfig.load(config=config)
|
|
164
165
|
|
|
166
|
+
if auth_type is None:
|
|
167
|
+
auth_type = git_config.auth_type
|
|
168
|
+
|
|
165
169
|
return Git(
|
|
166
170
|
auth_type=auth_type,
|
|
167
171
|
git_config=git_config,
|
|
@@ -182,8 +186,11 @@ class Git:
|
|
|
182
186
|
|
|
183
187
|
return [branch.name for branch in self.repo.branches]
|
|
184
188
|
|
|
185
|
-
async def check_connection(self) -> None:
|
|
186
|
-
|
|
189
|
+
async def check_connection(self, remote_url: str = None) -> None:
|
|
190
|
+
if remote_url:
|
|
191
|
+
await validate_authentication_for_remote_url(self.repo.git, remote_url)
|
|
192
|
+
else:
|
|
193
|
+
await check_connection_async(self.repo.git, self.origin.name)
|
|
187
194
|
|
|
188
195
|
def _remote_command(func: Callable) -> None:
|
|
189
196
|
"""
|
|
@@ -224,19 +231,19 @@ class Git:
|
|
|
224
231
|
elif self.auth_type == AuthType.HTTPS:
|
|
225
232
|
token = self.get_access_token()
|
|
226
233
|
url_original = list(self.origin.urls)[0]
|
|
234
|
+
remote_repo_link = self.remote_repo_link
|
|
227
235
|
if self.git_config and self.remote_repo_link and token:
|
|
228
|
-
|
|
236
|
+
remote_repo_link = build_authenticated_remote_url(
|
|
229
237
|
self.remote_repo_link,
|
|
230
238
|
self.git_config.username,
|
|
231
239
|
token,
|
|
232
240
|
)
|
|
233
|
-
self.origin.set_url(
|
|
241
|
+
self.origin.set_url(remote_repo_link)
|
|
234
242
|
try:
|
|
235
|
-
asyncio.run(self.check_connection())
|
|
243
|
+
asyncio.run(self.check_connection(remote_url=remote_repo_link))
|
|
236
244
|
return func(self, *args, **kwargs)
|
|
237
245
|
finally:
|
|
238
246
|
self.origin.set_url(url_original)
|
|
239
|
-
self.remote_repo_link = url_original
|
|
240
247
|
return wrapper
|
|
241
248
|
|
|
242
249
|
def add_remote(self, name: str, url: str) -> None:
|
|
@@ -432,6 +439,10 @@ class Git:
|
|
|
432
439
|
self.repo.git.reset('--hard', f'{remote.name}/{branch}')
|
|
433
440
|
self.__pip_install()
|
|
434
441
|
|
|
442
|
+
@_remote_command
|
|
443
|
+
def fetch(self) -> None:
|
|
444
|
+
self.origin.fetch()
|
|
445
|
+
|
|
435
446
|
@_remote_command
|
|
436
447
|
def push(self) -> None:
|
|
437
448
|
self.repo.git.push(
|
|
@@ -564,7 +575,7 @@ class Git:
|
|
|
564
575
|
if len(remote_refs) == 0 and user:
|
|
565
576
|
from mage_ai.data_preparation.git import api
|
|
566
577
|
|
|
567
|
-
access_token =
|
|
578
|
+
access_token = get_oauth_access_token_for_user(user)
|
|
568
579
|
if access_token:
|
|
569
580
|
|
|
570
581
|
if remote_exists:
|
|
@@ -685,15 +696,22 @@ class Git:
|
|
|
685
696
|
elif remote:
|
|
686
697
|
# For remote branches, switch to the local branch if it exists. Otherwise create a new
|
|
687
698
|
# branch using the remote branch as the starting point.
|
|
688
|
-
|
|
689
|
-
branch = branch[len(remote) + 1:]
|
|
690
|
-
if branch in self.repo.heads:
|
|
691
|
-
self.repo.git.switch(branch)
|
|
692
|
-
else:
|
|
693
|
-
self.repo.git.switch('-c', branch, f'{remote}/{branch}')
|
|
699
|
+
self._switch_remote_branch(branch, remote)
|
|
694
700
|
else:
|
|
695
701
|
self.repo.git.switch('-c', branch)
|
|
696
702
|
|
|
703
|
+
@_remote_command
|
|
704
|
+
def _switch_remote_branch(self, branch: str, remote: str) -> None:
|
|
705
|
+
self.switch_remote_branch(branch, remote)
|
|
706
|
+
|
|
707
|
+
def switch_remote_branch(self, branch: str, remote: str) -> None:
|
|
708
|
+
if branch.startswith(remote):
|
|
709
|
+
branch = branch[len(remote) + 1:]
|
|
710
|
+
if branch in self.repo.heads:
|
|
711
|
+
self.repo.git.switch(branch)
|
|
712
|
+
else:
|
|
713
|
+
self.repo.git.switch('-c', branch, f'{remote}/{branch}')
|
|
714
|
+
|
|
697
715
|
@_remote_command
|
|
698
716
|
def clone(self, sync_submodules: bool = False) -> None:
|
|
699
717
|
from git import Repo
|
|
@@ -729,13 +747,23 @@ class Git:
|
|
|
729
747
|
shutil.rmtree(tmp_path)
|
|
730
748
|
|
|
731
749
|
def __set_git_config(self):
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
750
|
+
from git.config import GitConfigParser
|
|
751
|
+
if self.git_config:
|
|
752
|
+
if self.git_config.username:
|
|
753
|
+
self.repo.config_writer().set_value(
|
|
754
|
+
'user', 'name', self.git_config.username).release()
|
|
755
|
+
if self.git_config.email:
|
|
756
|
+
self.repo.config_writer().set_value(
|
|
757
|
+
'user', 'email', self.git_config.email).release()
|
|
758
|
+
|
|
759
|
+
# This GitConfigParser is created in the same way that GitPython creates a
|
|
760
|
+
# global config parser. We create it this way to avoid needing to create a
|
|
761
|
+
# git.Repo object.
|
|
762
|
+
global_config = GitConfigParser(
|
|
763
|
+
os.path.normpath(os.path.expanduser("~/.gitconfig")),
|
|
764
|
+
read_only=False,
|
|
765
|
+
)
|
|
766
|
+
global_config.set_value(
|
|
739
767
|
'safe', 'directory', Path(self.repo_path).as_posix()).release()
|
|
740
768
|
|
|
741
769
|
def __pip_install(self) -> None:
|
|
@@ -3,9 +3,6 @@ import shutil
|
|
|
3
3
|
import uuid
|
|
4
4
|
from typing import Dict
|
|
5
5
|
|
|
6
|
-
from git.remote import RemoteProgress
|
|
7
|
-
from git.repo.base import Repo
|
|
8
|
-
|
|
9
6
|
from mage_ai.authentication.oauth.constants import ProviderName, get_ghe_hostname
|
|
10
7
|
from mage_ai.authentication.oauth.utils import access_tokens_for_client
|
|
11
8
|
from mage_ai.data_preparation.git.clients.base import Client as GitClient
|
|
@@ -33,13 +30,51 @@ def get_access_token_for_user(user: User, provider: str = None) -> Oauth2AccessT
|
|
|
33
30
|
return access_tokens[0]
|
|
34
31
|
|
|
35
32
|
|
|
33
|
+
def switch_branch(
|
|
34
|
+
remote_name: str,
|
|
35
|
+
remote_url: str,
|
|
36
|
+
branch_name: str,
|
|
37
|
+
token: str,
|
|
38
|
+
config_overwrite: Dict = None,
|
|
39
|
+
user: User = None,
|
|
40
|
+
):
|
|
41
|
+
from mage_ai.data_preparation.git import Git
|
|
42
|
+
provider = get_provider_from_remote_url(remote_url)
|
|
43
|
+
username = get_username(token, user=user, provider=provider)
|
|
44
|
+
|
|
45
|
+
url = build_authenticated_remote_url(remote_url, username, token)
|
|
46
|
+
git_manager = Git.get_manager(user=user, config_overwrite=config_overwrite)
|
|
47
|
+
|
|
48
|
+
remote = git_manager.repo.remotes[remote_name]
|
|
49
|
+
url_original = list(remote.urls)[0]
|
|
50
|
+
remote.set_url(url)
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
git_manager.switch_remote_branch(branch_name, remote_name)
|
|
54
|
+
except Exception as err:
|
|
55
|
+
raise err
|
|
56
|
+
finally:
|
|
57
|
+
try:
|
|
58
|
+
remote.set_url(url_original)
|
|
59
|
+
except Exception as err:
|
|
60
|
+
print('WARNING (mage_ai.data_preparation.git.api):')
|
|
61
|
+
print(err)
|
|
62
|
+
|
|
63
|
+
|
|
36
64
|
def fetch(
|
|
37
65
|
remote_name: str,
|
|
38
66
|
remote_url: str,
|
|
39
67
|
token: str,
|
|
40
68
|
user: User = None,
|
|
41
69
|
config_overwrite: Dict = None,
|
|
42
|
-
)
|
|
70
|
+
):
|
|
71
|
+
"""
|
|
72
|
+
Returns:
|
|
73
|
+
git.remote.RemoteProgress: Custom progress object that can be used to monitor the
|
|
74
|
+
fetch progress.
|
|
75
|
+
"""
|
|
76
|
+
from git.remote import RemoteProgress
|
|
77
|
+
|
|
43
78
|
from mage_ai.data_preparation.git import Git
|
|
44
79
|
|
|
45
80
|
custom_progress = RemoteProgress()
|
|
@@ -74,7 +109,14 @@ def pull(
|
|
|
74
109
|
token: str,
|
|
75
110
|
user: User = None,
|
|
76
111
|
config_overwrite: Dict = None,
|
|
77
|
-
)
|
|
112
|
+
):
|
|
113
|
+
"""
|
|
114
|
+
Returns:
|
|
115
|
+
git.remote.RemoteProgress: Custom progress object that can be used to monitor the
|
|
116
|
+
pull progress.
|
|
117
|
+
"""
|
|
118
|
+
from git.remote import RemoteProgress
|
|
119
|
+
|
|
78
120
|
from mage_ai.data_preparation.git import Git
|
|
79
121
|
|
|
80
122
|
custom_progress = RemoteProgress()
|
|
@@ -110,7 +152,13 @@ def push_raw(
|
|
|
110
152
|
token: str,
|
|
111
153
|
user: User = None,
|
|
112
154
|
**kwargs,
|
|
113
|
-
)
|
|
155
|
+
):
|
|
156
|
+
"""
|
|
157
|
+
Returns:
|
|
158
|
+
git.remote.RemoteProgress: Custom progress object that can be used to monitor the
|
|
159
|
+
push progress.
|
|
160
|
+
"""
|
|
161
|
+
from git.remote import RemoteProgress
|
|
114
162
|
custom_progress = RemoteProgress()
|
|
115
163
|
provider = get_provider_from_remote_url(remote_url)
|
|
116
164
|
username = get_username(token, user=user, provider=provider)
|
|
@@ -142,7 +190,12 @@ def push(
|
|
|
142
190
|
token: str,
|
|
143
191
|
user: User = None,
|
|
144
192
|
config_overwrite: Dict = None,
|
|
145
|
-
)
|
|
193
|
+
):
|
|
194
|
+
"""
|
|
195
|
+
Returns:
|
|
196
|
+
git.remote.RemoteProgress: Custom progress object that can be used to monitor the
|
|
197
|
+
push progress.
|
|
198
|
+
"""
|
|
146
199
|
from mage_ai.data_preparation.git import Git
|
|
147
200
|
|
|
148
201
|
git_manager = Git.get_manager(user=user, config_overwrite=config_overwrite)
|
|
@@ -213,6 +266,8 @@ def clone(
|
|
|
213
266
|
tmp_path = f'{git_manager.repo_path}_{uuid.uuid4().hex}'
|
|
214
267
|
os.mkdir(tmp_path)
|
|
215
268
|
try:
|
|
269
|
+
from git.repo.base import Repo
|
|
270
|
+
|
|
216
271
|
# Clone to a tmp folder first, then copy the folder to the actual repo path. Git
|
|
217
272
|
# won't allow you to clone to a folder that is not empty.
|
|
218
273
|
Repo.clone_from(
|
|
@@ -6,16 +6,20 @@ from typing import Callable
|
|
|
6
6
|
from urllib.parse import urlparse, urlsplit, urlunsplit
|
|
7
7
|
|
|
8
8
|
from mage_ai.authentication.oauth.constants import ProviderName, get_ghe_hostname
|
|
9
|
+
from mage_ai.authentication.oauth.utils import access_tokens_for_client
|
|
9
10
|
from mage_ai.data_preparation.git.constants import (
|
|
10
11
|
DEFAULT_KNOWN_HOSTS_FILE,
|
|
11
12
|
DEFAULT_SSH_KEY_DIRECTORY,
|
|
12
13
|
)
|
|
14
|
+
from mage_ai.data_preparation.repo_manager import get_project_uuid
|
|
13
15
|
from mage_ai.data_preparation.shared.secrets import get_secret_value
|
|
14
16
|
from mage_ai.data_preparation.sync import AuthType, GitConfig
|
|
15
|
-
from mage_ai.
|
|
17
|
+
from mage_ai.orchestration.db.models.oauth import Oauth2AccessToken, User
|
|
18
|
+
from mage_ai.settings import get_bool_value, get_settings_value
|
|
16
19
|
from mage_ai.settings.keys import (
|
|
17
20
|
BITBUCKET_HOST,
|
|
18
21
|
GIT_ACCESS_TOKEN,
|
|
22
|
+
GIT_OVERWRITE_WITH_PROJECT_SETTINGS,
|
|
19
23
|
GIT_SSH_PRIVATE_KEY,
|
|
20
24
|
GIT_SSH_PUBLIC_KEY,
|
|
21
25
|
GITLAB_HOST,
|
|
@@ -52,19 +56,23 @@ def get_provider_from_remote_url(remote_url: str) -> str:
|
|
|
52
56
|
return ProviderName.GITHUB
|
|
53
57
|
|
|
54
58
|
|
|
55
|
-
def create_ssh_keys(
|
|
59
|
+
def create_ssh_keys(
|
|
60
|
+
git_config: GitConfig, repo_path: str, overwrite: bool = False
|
|
61
|
+
) -> str:
|
|
56
62
|
if not os.path.exists(DEFAULT_SSH_KEY_DIRECTORY):
|
|
57
63
|
os.mkdir(DEFAULT_SSH_KEY_DIRECTORY, 0o700)
|
|
58
64
|
pubk_secret_name = git_config.ssh_public_key_secret_name
|
|
65
|
+
overwrite_with_project_settings = get_bool_value(
|
|
66
|
+
get_settings_value(GIT_OVERWRITE_WITH_PROJECT_SETTINGS)
|
|
67
|
+
)
|
|
59
68
|
if pubk_secret_name:
|
|
60
69
|
public_key_file = os.path.join(
|
|
61
|
-
DEFAULT_SSH_KEY_DIRECTORY,
|
|
62
|
-
f'id_rsa_{pubk_secret_name}.pub'
|
|
70
|
+
DEFAULT_SSH_KEY_DIRECTORY, f'id_rsa_{pubk_secret_name}.pub'
|
|
63
71
|
)
|
|
64
72
|
if not os.path.exists(public_key_file) or overwrite:
|
|
65
73
|
try:
|
|
66
74
|
public_key = get_settings_value(GIT_SSH_PUBLIC_KEY)
|
|
67
|
-
if not public_key:
|
|
75
|
+
if not public_key or overwrite_with_project_settings:
|
|
68
76
|
public_key = get_secret_value(
|
|
69
77
|
pubk_secret_name,
|
|
70
78
|
repo_name=repo_path,
|
|
@@ -80,13 +88,12 @@ def create_ssh_keys(git_config: GitConfig, repo_path: str, overwrite: bool = Fal
|
|
|
80
88
|
private_key_file = os.path.join(DEFAULT_SSH_KEY_DIRECTORY, 'id_rsa')
|
|
81
89
|
if pk_secret_name:
|
|
82
90
|
custom_private_key_file = os.path.join(
|
|
83
|
-
DEFAULT_SSH_KEY_DIRECTORY,
|
|
84
|
-
f'id_rsa_{pk_secret_name}'
|
|
91
|
+
DEFAULT_SSH_KEY_DIRECTORY, f'id_rsa_{pk_secret_name}'
|
|
85
92
|
)
|
|
86
93
|
if not os.path.exists(custom_private_key_file) or overwrite:
|
|
87
94
|
try:
|
|
88
95
|
private_key = get_settings_value(GIT_SSH_PRIVATE_KEY)
|
|
89
|
-
if not private_key:
|
|
96
|
+
if not private_key or overwrite_with_project_settings:
|
|
90
97
|
private_key = get_secret_value(
|
|
91
98
|
pk_secret_name,
|
|
92
99
|
repo_name=repo_path,
|
|
@@ -142,11 +149,16 @@ def add_host_to_known_hosts(remote_repo_link: str):
|
|
|
142
149
|
|
|
143
150
|
def get_access_token(git_config, repo_path: str = None) -> str:
|
|
144
151
|
token = get_settings_value(GIT_ACCESS_TOKEN)
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
overwrite_with_project_settings = get_bool_value(
|
|
153
|
+
get_settings_value(GIT_OVERWRITE_WITH_PROJECT_SETTINGS)
|
|
154
|
+
)
|
|
155
|
+
if git_config and git_config.access_token_secret_name:
|
|
156
|
+
token_from_secrets = get_secret_value(
|
|
147
157
|
git_config.access_token_secret_name,
|
|
148
158
|
repo_name=repo_path or get_repo_path(),
|
|
149
159
|
)
|
|
160
|
+
if not token or overwrite_with_project_settings:
|
|
161
|
+
token = token_from_secrets
|
|
150
162
|
|
|
151
163
|
return token
|
|
152
164
|
|
|
@@ -179,10 +191,7 @@ async def poll_process_with_timeout(
|
|
|
179
191
|
if return_code is not None:
|
|
180
192
|
out, err = proc.communicate()
|
|
181
193
|
if return_code != 0:
|
|
182
|
-
message = (
|
|
183
|
-
err.decode('UTF-8') if err
|
|
184
|
-
else error_message
|
|
185
|
-
)
|
|
194
|
+
message = err.decode('UTF-8') if err else error_message
|
|
186
195
|
raise ChildProcessError(message)
|
|
187
196
|
else:
|
|
188
197
|
return out.decode('UTF-8') if out else None
|
|
@@ -205,17 +214,16 @@ async def check_connection_async(git, remote_name: str) -> None:
|
|
|
205
214
|
'Error connecting to remote, make sure your access token or SSH key is '
|
|
206
215
|
'set up properly.'
|
|
207
216
|
),
|
|
217
|
+
timeout=5,
|
|
208
218
|
)
|
|
209
219
|
|
|
210
220
|
|
|
211
221
|
async def validate_authentication_for_remote_url(git, remote_url: str) -> None:
|
|
212
222
|
proc = git.ls_remote(remote_url, as_process=True)
|
|
213
223
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
error_message='Error connecting to remote, make sure your access is valid.',
|
|
218
|
-
)
|
|
224
|
+
await poll_process_with_timeout(
|
|
225
|
+
proc,
|
|
226
|
+
error_message='Error connecting to remote, make sure your access is valid.',
|
|
219
227
|
)
|
|
220
228
|
|
|
221
229
|
|
|
@@ -258,14 +266,30 @@ def execute_on_remote_branch(func: Callable, branch) -> None:
|
|
|
258
266
|
if hostname:
|
|
259
267
|
await __add_host_to_known_hosts(remote_name)
|
|
260
268
|
else:
|
|
261
|
-
raise TimeoutError(
|
|
269
|
+
raise TimeoutError(
|
|
270
|
+
"""
|
|
262
271
|
Connecting to remote timed out, make sure your SSH key is set up properly
|
|
263
272
|
and your repository host is added as a known host. More information
|
|
264
273
|
here: https://docs.mage.ai/developing-in-the-cloud/setting-up-git#5-add-github-com-to-known-hosts
|
|
265
|
-
"""
|
|
274
|
+
"""
|
|
275
|
+
)
|
|
266
276
|
return await func(*args, **kwargs)
|
|
267
277
|
else:
|
|
268
278
|
await check_connection_async(git, remote_name)
|
|
269
279
|
return await func(*args, **kwargs)
|
|
270
280
|
|
|
271
281
|
return wrapper
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def get_oauth_client_id(provider: str) -> str:
|
|
285
|
+
return f'{provider}_{get_project_uuid()}'
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def get_oauth_access_token_for_user(
|
|
289
|
+
user: User, provider: str = None
|
|
290
|
+
) -> Oauth2AccessToken:
|
|
291
|
+
if not provider:
|
|
292
|
+
provider = ProviderName.GHE if get_ghe_hostname() else ProviderName.GITHUB
|
|
293
|
+
access_tokens = access_tokens_for_client(get_oauth_client_id(provider), user=user)
|
|
294
|
+
if access_tokens:
|
|
295
|
+
return access_tokens[0]
|
|
@@ -907,10 +907,11 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
907
907
|
parts = get_path_parts(file_path)
|
|
908
908
|
|
|
909
909
|
if parts and len(parts) >= 3:
|
|
910
|
+
from mage_ai.data_preparation.models.block.block_factory import BlockFactory
|
|
911
|
+
|
|
910
912
|
# If file_path == transformers/test4.py
|
|
911
913
|
# parts ==
|
|
912
914
|
# ('/home/src/default_repo/default_platform2/project3', 'transformers', 'test4.py')
|
|
913
|
-
|
|
914
915
|
# If project platform platform activated, then parts ==
|
|
915
916
|
# ('/home/src', 'default_repo', 'data_loaders/astral_violet.py')
|
|
916
917
|
|
|
@@ -929,7 +930,7 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
929
930
|
configuration = dict(file_path=file_path, file_source=dict(path=file_path))
|
|
930
931
|
language = FILE_EXTENSION_TO_BLOCK_LANGUAGE.get(extension)
|
|
931
932
|
|
|
932
|
-
return
|
|
933
|
+
return BlockFactory.get_block(
|
|
933
934
|
block_uuid,
|
|
934
935
|
block_uuid,
|
|
935
936
|
block_type,
|
|
@@ -1121,6 +1122,7 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
1121
1122
|
data_integration_runtime_settings: Dict = None,
|
|
1122
1123
|
execution_partition_previous: str = None,
|
|
1123
1124
|
metadata: Dict = None,
|
|
1125
|
+
override_outputs: bool = True,
|
|
1124
1126
|
**kwargs,
|
|
1125
1127
|
) -> Dict:
|
|
1126
1128
|
if logging_tags is None:
|
|
@@ -1212,7 +1214,7 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
1212
1214
|
DX_PRINTER.critical(
|
|
1213
1215
|
block=self,
|
|
1214
1216
|
execution_partition=execution_partition,
|
|
1215
|
-
override_outputs=
|
|
1217
|
+
override_outputs=override_outputs,
|
|
1216
1218
|
dynamic_block_uuid=dynamic_block_uuid,
|
|
1217
1219
|
__uuid='store_variables',
|
|
1218
1220
|
)
|
|
@@ -1220,7 +1222,7 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
1220
1222
|
self.store_variables(
|
|
1221
1223
|
variable_mapping,
|
|
1222
1224
|
execution_partition=execution_partition,
|
|
1223
|
-
override_outputs=
|
|
1225
|
+
override_outputs=override_outputs,
|
|
1224
1226
|
spark=self.__get_spark_session_from_global_vars(
|
|
1225
1227
|
global_vars=global_vars,
|
|
1226
1228
|
),
|
|
@@ -1615,7 +1617,7 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
1615
1617
|
|
|
1616
1618
|
block_function = self._validate_execution(decorated_functions, input_vars)
|
|
1617
1619
|
if block_function is not None:
|
|
1618
|
-
if logger
|
|
1620
|
+
if logger:
|
|
1619
1621
|
global_vars['logger'] = logger
|
|
1620
1622
|
|
|
1621
1623
|
track_spark = from_notebook and self.should_track_spark()
|
|
@@ -1779,6 +1781,7 @@ class Block(DataIntegrationMixin, SparkBlock, ProjectPlatformAccessible):
|
|
|
1779
1781
|
global_vars=global_vars,
|
|
1780
1782
|
metadata=metadata,
|
|
1781
1783
|
upstream_block_uuids_override=upstream_block_uuids_override,
|
|
1784
|
+
current_block=self,
|
|
1782
1785
|
)
|
|
1783
1786
|
|
|
1784
1787
|
return variables
|
|
@@ -2385,8 +2388,17 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
2385
2388
|
|
|
2386
2389
|
def get_executor_type(self) -> str:
|
|
2387
2390
|
if self.executor_type:
|
|
2388
|
-
|
|
2389
|
-
|
|
2391
|
+
block_executor_type = Template(self.executor_type).render(**get_template_vars())
|
|
2392
|
+
else:
|
|
2393
|
+
block_executor_type = None
|
|
2394
|
+
if not block_executor_type or block_executor_type == ExecutorType.LOCAL_PYTHON:
|
|
2395
|
+
# If block executor_type is not set, fall back to pipeline level executor_type
|
|
2396
|
+
if self.pipeline:
|
|
2397
|
+
pipeline_executor_type = self.pipeline.get_executor_type()
|
|
2398
|
+
else:
|
|
2399
|
+
pipeline_executor_type = None
|
|
2400
|
+
block_executor_type = pipeline_executor_type or block_executor_type
|
|
2401
|
+
return block_executor_type
|
|
2390
2402
|
|
|
2391
2403
|
def get_pipelines_from_cache(self, block_cache: BlockCache = None) -> List[Dict]:
|
|
2392
2404
|
if block_cache is None:
|
|
@@ -2993,6 +3005,8 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
2993
3005
|
global_vars: Dict = None,
|
|
2994
3006
|
dynamic_block_index: int = None,
|
|
2995
3007
|
) -> Dict:
|
|
3008
|
+
from mage_ai.data_preparation.models.block.remote.models import RemoteBlock
|
|
3009
|
+
|
|
2996
3010
|
"""
|
|
2997
3011
|
Enriches the provided global variables dictionary with additional context, Spark session,
|
|
2998
3012
|
environment, configuration, and an empty context dictionary.
|
|
@@ -3039,6 +3053,12 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
3039
3053
|
if dynamic_block_index is not None:
|
|
3040
3054
|
global_vars['dynamic_block_index'] = dynamic_block_index
|
|
3041
3055
|
|
|
3056
|
+
# Remote blocks
|
|
3057
|
+
if global_vars.get('remote_blocks'):
|
|
3058
|
+
global_vars['remote_blocks'] = [RemoteBlock.load(
|
|
3059
|
+
**remote_block_dict,
|
|
3060
|
+
).get_outputs() for remote_block_dict in global_vars['remote_blocks']]
|
|
3061
|
+
|
|
3042
3062
|
self.global_vars = global_vars
|
|
3043
3063
|
|
|
3044
3064
|
return global_vars
|
|
@@ -3473,12 +3493,15 @@ df = get_variable('{self.pipeline.uuid}', '{self.uuid}', 'df')
|
|
|
3473
3493
|
|
|
3474
3494
|
cache = BlockCache()
|
|
3475
3495
|
if detach:
|
|
3496
|
+
from mage_ai.data_preparation.models.block.block_factory import (
|
|
3497
|
+
BlockFactory,
|
|
3498
|
+
)
|
|
3476
3499
|
""""
|
|
3477
3500
|
New block added to pipeline, so it must be added to the block cache.
|
|
3478
3501
|
Old block no longer in pipeline, so it must be removed from block cache.
|
|
3479
3502
|
"""
|
|
3480
3503
|
cache.add_pipeline(self, self.pipeline)
|
|
3481
|
-
old_block =
|
|
3504
|
+
old_block = BlockFactory.get_block(
|
|
3482
3505
|
old_uuid,
|
|
3483
3506
|
old_uuid,
|
|
3484
3507
|
self.type,
|
|
@@ -202,18 +202,29 @@ class DataIntegrationMixin:
|
|
|
202
202
|
with open(catalog_full_path, mode='w') as f:
|
|
203
203
|
f.write(json.dumps(catalog))
|
|
204
204
|
|
|
205
|
-
def is_data_integration(self) -> bool:
|
|
205
|
+
def is_data_integration(self, pipeline_project: Project = None) -> bool:
|
|
206
206
|
"""
|
|
207
207
|
Check if the block is a data integration block.
|
|
208
208
|
If the data_integration_in_batch_pipeline feature is not enabled, return False.
|
|
209
209
|
|
|
210
|
+
Args:
|
|
211
|
+
pipeline_project (Project, optional): A cached Project value to avoid
|
|
212
|
+
looking it up many times when called inside loops. Defaults to None.
|
|
213
|
+
|
|
210
214
|
Returns:
|
|
211
215
|
bool: True if it's a data integration block, False otherwise.
|
|
212
216
|
"""
|
|
213
|
-
if not self.pipeline
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
+
if not self.pipeline:
|
|
218
|
+
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
actual_project: Project = pipeline_project
|
|
222
|
+
if not actual_project:
|
|
223
|
+
actual_project = Project(self.pipeline.repo_config)
|
|
224
|
+
|
|
225
|
+
if not actual_project.is_feature_enabled(
|
|
226
|
+
FeatureUUID.DATA_INTEGRATION_IN_BATCH_PIPELINE,
|
|
227
|
+
):
|
|
217
228
|
|
|
218
229
|
return False
|
|
219
230
|
|
|
@@ -9,7 +9,10 @@ import pandas as pd
|
|
|
9
9
|
from mage_ai.data_preparation.models.block.dynamic.variables import (
|
|
10
10
|
get_outputs_for_dynamic_block,
|
|
11
11
|
)
|
|
12
|
-
from mage_ai.data_preparation.models.constants import
|
|
12
|
+
from mage_ai.data_preparation.models.constants import (
|
|
13
|
+
DATAFRAME_ANALYSIS_MAX_COLUMNS,
|
|
14
|
+
DATAFRAME_SAMPLE_COUNT_PREVIEW,
|
|
15
|
+
)
|
|
13
16
|
from mage_ai.server.kernel_output_parser import DataType
|
|
14
17
|
from mage_ai.shared.array import find
|
|
15
18
|
from mage_ai.shared.custom_logger import DX_PRINTER
|
|
@@ -245,7 +248,9 @@ def transform_dataframe_for_display(dataframe: pd.DataFrame) -> Dict:
|
|
|
245
248
|
data = dict(
|
|
246
249
|
columns=columns_to_display,
|
|
247
250
|
rows=json.loads(
|
|
248
|
-
dataframe[columns_to_display].to_json(
|
|
251
|
+
dataframe[columns_to_display][:DATAFRAME_SAMPLE_COUNT_PREVIEW].to_json(
|
|
252
|
+
orient='split',
|
|
253
|
+
)
|
|
249
254
|
)['data'],
|
|
250
255
|
index=list(dataframe.index),
|
|
251
256
|
shape=[row_count, column_count],
|
|
@@ -253,7 +258,7 @@ def transform_dataframe_for_display(dataframe: pd.DataFrame) -> Dict:
|
|
|
253
258
|
else:
|
|
254
259
|
data = dict(
|
|
255
260
|
columns=['col0'],
|
|
256
|
-
rows=[[dataframe]],
|
|
261
|
+
rows=[[dataframe[:DATAFRAME_SAMPLE_COUNT_PREVIEW]]],
|
|
257
262
|
index=[0],
|
|
258
263
|
shape=[1, 1],
|
|
259
264
|
)
|
|
@@ -413,7 +418,7 @@ def transform_output_for_display_dynamic_child(
|
|
|
413
418
|
df = pd.concat([df, df_inner], axis=1)
|
|
414
419
|
|
|
415
420
|
df = limit_output(df, sample_count)
|
|
416
|
-
if 1 == len(set(df.columns)):
|
|
421
|
+
if isinstance(df, pd.DataFrame) and 1 == len(set(df.columns)):
|
|
417
422
|
df.columns = [f'{col}_{idx}' for idx, col in enumerate(df.columns)]
|
|
418
423
|
|
|
419
424
|
return transform_dataframe_for_display(df)
|
|
@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Tuple, Union
|
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
|
|
9
|
-
from mage_ai.data_preparation.models.constants import BlockLanguage
|
|
9
|
+
from mage_ai.data_preparation.models.constants import BlockLanguage, BlockType
|
|
10
10
|
from mage_ai.data_preparation.models.variable import Variable
|
|
11
11
|
from mage_ai.shared.memory import get_memory_usage, get_memory_usage_async
|
|
12
12
|
from mage_ai.shared.strings import to_ordinal_integers
|
|
@@ -470,7 +470,7 @@ def fetch_input_variables_for_dynamic_upstream_blocks(
|
|
|
470
470
|
|
|
471
471
|
# If dynamic child should reduce its output (which means it passes the entire
|
|
472
472
|
# output to its downstream blocks):
|
|
473
|
-
if should_reduce_output(upstream_block):
|
|
473
|
+
if should_reduce_output(upstream_block) and block.type != BlockType.EXTENSION:
|
|
474
474
|
child_data = []
|
|
475
475
|
metadata = {}
|
|
476
476
|
for lazy_variable_set in lazy_variable_controller:
|