mage-ai 0.9.74__py3-none-any.whl → 0.9.79__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.
- mage_ai/ai/llm_pipeline_wizard.py +6 -4
- mage_ai/ai/openai_client.py +7 -5
- mage_ai/api/policies/PipelineSchedulePolicy.py +1 -0
- mage_ai/api/presenters/PipelineSchedulePresenter.py +11 -2
- mage_ai/api/resources/GitFileResource.py +8 -0
- mage_ai/api/resources/PipelineScheduleResource.py +20 -14
- mage_ai/api/resources/PipelineTriggerResource.py +3 -1
- mage_ai/api/resources/SessionResource.py +2 -2
- mage_ai/api/resources/SyncResource.py +1 -1
- mage_ai/api/resources/UserResource.py +1 -1
- mage_ai/cli/main.py +8 -1
- mage_ai/data_cleaner/analysis/charts.py +1 -1
- mage_ai/data_cleaner/cleaning_rules/reformat_values.py +1 -1
- mage_ai/data_integrations/destinations/constants.py +3 -0
- mage_ai/data_integrations/sources/constants.py +2 -0
- mage_ai/data_preparation/executors/block_executor.py +8 -3
- mage_ai/data_preparation/executors/pipeline_executor.py +35 -19
- mage_ai/data_preparation/git/utils.py +2 -2
- mage_ai/data_preparation/logging/logger_manager.py +31 -2
- mage_ai/data_preparation/models/block/__init__.py +33 -27
- mage_ai/data_preparation/models/block/dbt/dbt_adapter.py +20 -8
- mage_ai/data_preparation/models/block/dynamic/constants.py +0 -1
- mage_ai/data_preparation/models/block/dynamic/counter.py +1 -3
- mage_ai/data_preparation/models/block/outputs.py +7 -1
- mage_ai/data_preparation/models/block/r/__init__.py +16 -5
- mage_ai/data_preparation/models/block/sql/__init__.py +2 -0
- mage_ai/data_preparation/models/block/sql/mssql.py +8 -0
- mage_ai/data_preparation/models/block/sql/utils/shared.py +6 -2
- mage_ai/data_preparation/models/constants.py +4 -1
- mage_ai/data_preparation/models/pipeline.py +11 -2
- mage_ai/data_preparation/models/project/__init__.py +3 -1
- mage_ai/data_preparation/models/triggers/__init__.py +1 -1
- mage_ai/data_preparation/storage/local_storage.py +4 -1
- mage_ai/data_preparation/templates/constants.py +7 -0
- mage_ai/data_preparation/templates/data_exporters/streaming/elasticsearch.yaml +3 -0
- mage_ai/data_preparation/templates/data_loaders/airtable.py +28 -0
- mage_ai/data_preparation/templates/data_loaders/streaming/nats.yaml +6 -3
- mage_ai/data_preparation/templates/repo/io_config.yaml +2 -0
- mage_ai/io/airtable.py +104 -0
- mage_ai/io/base.py +30 -1
- mage_ai/io/bigquery.py +36 -0
- mage_ai/io/config.py +6 -0
- mage_ai/io/mssql.py +21 -9
- mage_ai/io/mysql.py +6 -1
- mage_ai/io/oracledb.py +2 -4
- mage_ai/io/postgres.py +41 -19
- mage_ai/io/qdrant.py +1 -1
- mage_ai/io/redshift.py +13 -0
- mage_ai/io/sql.py +1 -0
- mage_ai/io/utils.py +18 -0
- mage_ai/orchestration/db/__init__.py +23 -3
- mage_ai/orchestration/db/migrations/versions/39d36f1dab73_create_genericjob.py +47 -0
- mage_ai/orchestration/db/models/oauth.py +2 -1
- mage_ai/orchestration/db/models/schedules.py +108 -6
- mage_ai/orchestration/db/models/schedules_project_platform.py +1 -1
- mage_ai/orchestration/db/models/secrets.py +11 -1
- mage_ai/orchestration/job_manager.py +19 -0
- mage_ai/orchestration/metrics/pipeline_run.py +1 -1
- mage_ai/orchestration/notification/sender.py +2 -2
- mage_ai/orchestration/pipeline_scheduler_original.py +150 -6
- mage_ai/orchestration/pipeline_scheduler_project_platform.py +4 -5
- mage_ai/orchestration/queue/config.py +11 -1
- mage_ai/orchestration/queue/process_queue.py +4 -0
- mage_ai/orchestration/utils/distributed_lock.py +8 -1
- mage_ai/orchestration/utils/resources.py +56 -2
- mage_ai/sample_datasets/salary_survey.csv +52 -52
- mage_ai/server/api/base.py +41 -0
- mage_ai/server/api/constants.py +1 -0
- mage_ai/server/api/triggers.py +9 -0
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +3 -3
- mage_ai/server/frontend_dist/_next/static/TUo4RceCdMufBTBTq8CAq/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{1187-839336d276186105.js → 1187-4560c3895e1d7099.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{1598-0adca9dce3ba4c60.js → 1598-cbf3f5a6078fc3f5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2717-638a944d24d5abde.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3548-36f746b1824004f2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{3763-39a5174f6a3924db.js → 3763-aabe2703076636b0.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3782-3e2acb5ed45b582b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/449-5e2253c6aba42557.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/5627-d5e559859dd0e1e0.js → frontend_dist/_next/static/chunks/5627-10e76bafa5a26f5f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{5699-e49718dfc9eb2854.js → 5699-e99379e332bd0b41.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{7966-163da2621b8c987c.js → 7966-a5a7db345ce81263.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-b697b35dfc4e6e26.js +2 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/compute-ed67fa8e81662e8b.js → frontend_dist/_next/static/chunks/pages/compute-9e2dea78024e3bb4.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/files-e0ecd7ced09a63b2.js → frontend_dist/_next/static/chunks/pages/files-e08c7fe76f968f9c.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/{[...slug]-c7a729477ecda50e.js → [...slug]-30c3807057a4e65b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-data-products-fd6ae6a358a60a0c.js → global-data-products-8dcb3b31af9e0e39.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-8e50243797a7fe59.js → frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-85a64b64d27214b6.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{global-hooks-d0c003446332dc0d.js → global-hooks-4ff959d51b8a9502.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{files-a69ed8e9f814490c.js → files-d08a460641d0efaa.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{overview-1aad7093c6d39257.js → overview-aae747f487e08d51.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{pipeline-runs-528d30e0d13b0cc7.js → pipeline-runs-09a842d64a6ada62.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{settings-fb9201d9cf63031d.js → settings-2e98e57d9376a458.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/{[user]-000f5a980a07da39.js → [user]-7be6e41ad66089bb.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-e4e613f6e817a733.js → frontend_dist/_next/static/chunks/pages/manage/users/new-4c088833063bfa07.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-5db54821a3059c69.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/manage-34d718b8a4066c23.js → frontend_dist/_next/static/chunks/pages/manage-868fcd8cbeb265f0.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{oauth-3bfd1b8d7f036726.js → oauth-6ceceb62191dfe8a.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-f65416f6dbe30ad3.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{pipeline-runs-5f8c100e648efa8a.js → pipeline-runs-2d0136b51b57de93.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-688c652f3296bb9c.js → [...slug]-1ad5238742e25b4c.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-bd11e87d026bfbf9.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{dashboard-1236e36d39b1637d.js → dashboard-0f4f47f721b0723f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-5ae8efe9e0530212.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-fe91dfb0091f6bc6.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-0d68d4bf6290fefb.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-cf794b2d22a80f31.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-9254358d58f07714.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-a964caef91bed9e1.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{monitors-821001e690caebe2.js → monitors-80bebb4401eefe25.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-2eae7cb017027682.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-2d4b2a0800a66b33.js → frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-776b2e5b0b6ceba8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-03d9bca3bc5e6088.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-707ed8ca942ca802.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/{[...slug]-259143ed3cf59e31.js → [...slug]-8429f17d4146e1ec.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-193045d9836d8d80.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-d25d07db166cbb04.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/platform/global-hooks/{[...slug]-5eeec927e4202b63.js → [...slug]-6834ae87bd668cb2.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/platform/global-hooks-fbe9ad995d46d837.js → frontend_dist/_next/static/chunks/pages/platform/global-hooks-b3f7309a23e592b2.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/account/{profile-fc659962d4015cb3.js → profile-f8b7374385e1f1bf.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-8de68502a9afa299.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-a4f88c334414402b.js → frontend_dist/_next/static/chunks/pages/settings/platform/settings-50fb6a34f3913f1f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-4deb9579ef99a3c6.js → [...slug]-2e5c098c21ea32b7.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{permissions-e0cda2f2bfce8d61.js → permissions-54e4b15b9585bfc4.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-040f83d75d0f6537.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-910257d16c604ebd.js → [...slug]-95088f43034e3c95.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{roles-4f7a0756806cee34.js → roles-e9149e1fcf218f42.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{sync-data-208d6f955204d704.js → sync-data-75b67ae4a00818ef.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users/{[...slug]-c89dc67e5a1706a8.js → [...slug]-557dda05ca6c6124.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users-fa61dc6c1370e6a5.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{sign-in-054b33312d3193c3.js → sign-in-593c40985d63fcf7.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/templates/{[...slug]-b6ed6a5d818bfd20.js → [...slug]-252c4b6b818345d5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{templates-852357bc983af2ea.js → templates-ca528bc607753ab8.js} +1 -1
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/terminal-1f9c56d671bbc67d.js → frontend_dist/_next/static/chunks/pages/terminal-287362c1defcc96b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/test-2f83af8c9f1378fe.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-d9de73fb799efed8.js +1 -0
- mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/version-control-ae3469b992a341d6.js → frontend_dist/_next/static/chunks/pages/version-control-573f0225d7a703ed.js} +1 -1
- mage_ai/server/frontend_dist/block-layout.html +3 -3
- mage_ai/server/frontend_dist/compute.html +6 -6
- mage_ai/server/frontend_dist/files.html +6 -6
- mage_ai/server/frontend_dist/global-data-products/[...slug].html +6 -6
- mage_ai/server/frontend_dist/global-data-products.html +6 -6
- mage_ai/server/frontend_dist/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist/global-hooks.html +6 -6
- mage_ai/server/frontend_dist/index.html +3 -3
- mage_ai/server/frontend_dist/manage/files.html +6 -6
- mage_ai/server/frontend_dist/manage/overview.html +6 -6
- mage_ai/server/frontend_dist/manage/pipeline-runs.html +6 -6
- mage_ai/server/frontend_dist/manage/settings.html +6 -6
- mage_ai/server/frontend_dist/manage/users/[user].html +6 -6
- mage_ai/server/frontend_dist/manage/users/new.html +6 -6
- mage_ai/server/frontend_dist/manage/users.html +6 -6
- mage_ai/server/frontend_dist/manage.html +6 -6
- mage_ai/server/frontend_dist/oauth.html +5 -5
- mage_ai/server/frontend_dist/overview.html +6 -6
- mage_ai/server/frontend_dist/pipeline-runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +3 -3
- mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +6 -6
- mage_ai/server/frontend_dist/pipelines/[pipeline].html +3 -3
- mage_ai/server/frontend_dist/pipelines.html +6 -6
- mage_ai/server/frontend_dist/platform/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist/platform/global-hooks.html +6 -6
- mage_ai/server/frontend_dist/settings/account/profile.html +6 -6
- mage_ai/server/frontend_dist/settings/platform/preferences.html +6 -6
- mage_ai/server/frontend_dist/settings/platform/settings.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/permissions.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/roles.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +6 -6
- mage_ai/server/frontend_dist/settings/workspace/users.html +6 -6
- mage_ai/server/frontend_dist/settings.html +3 -3
- mage_ai/server/frontend_dist/sign-in.html +7 -7
- mage_ai/server/frontend_dist/templates/[...slug].html +6 -6
- mage_ai/server/frontend_dist/templates.html +6 -6
- mage_ai/server/frontend_dist/terminal.html +6 -6
- mage_ai/server/frontend_dist/test.html +3 -3
- mage_ai/server/frontend_dist/triggers.html +6 -6
- mage_ai/server/frontend_dist/v2/canvas.html +2 -2
- mage_ai/server/frontend_dist/v2.html +2 -2
- mage_ai/server/frontend_dist/version-control.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/404.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/_next/static/2QL-FT4lFR0a9bDZ7lNd9/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1187-839336d276186105.js → 1187-4560c3895e1d7099.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1598-0adca9dce3ba4c60.js → 1598-cbf3f5a6078fc3f5.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-638a944d24d5abde.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3548-36f746b1824004f2.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{3763-39a5174f6a3924db.js → 3763-aabe2703076636b0.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-3e2acb5ed45b582b.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/449-5e2253c6aba42557.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/5627-d5e559859dd0e1e0.js → frontend_dist_base_path_template/_next/static/chunks/5627-10e76bafa5a26f5f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{5699-e49718dfc9eb2854.js → 5699-e99379e332bd0b41.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{7966-163da2621b8c987c.js → 7966-a5a7db345ce81263.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-f205accb03b9ff43.js +2 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/compute-ed67fa8e81662e8b.js → frontend_dist_base_path_template/_next/static/chunks/pages/compute-9e2dea78024e3bb4.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/files-e0ecd7ced09a63b2.js → frontend_dist_base_path_template/_next/static/chunks/pages/files-e08c7fe76f968f9c.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/{[...slug]-c7a729477ecda50e.js → [...slug]-30c3807057a4e65b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-data-products-fd6ae6a358a60a0c.js → global-data-products-8dcb3b31af9e0e39.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/global-hooks/[...slug]-8e50243797a7fe59.js → frontend_dist_base_path_template/_next/static/chunks/pages/global-hooks/[...slug]-85a64b64d27214b6.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{global-hooks-d0c003446332dc0d.js → global-hooks-4ff959d51b8a9502.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{files-a69ed8e9f814490c.js → files-d08a460641d0efaa.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{overview-1aad7093c6d39257.js → overview-aae747f487e08d51.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{pipeline-runs-528d30e0d13b0cc7.js → pipeline-runs-09a842d64a6ada62.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/{settings-fb9201d9cf63031d.js → settings-2e98e57d9376a458.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/{[user]-000f5a980a07da39.js → [user]-7be6e41ad66089bb.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage/users/new-e4e613f6e817a733.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage/users/new-4c088833063bfa07.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-5db54821a3059c69.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/manage-34d718b8a4066c23.js → frontend_dist_base_path_template/_next/static/chunks/pages/manage-868fcd8cbeb265f0.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{oauth-3bfd1b8d7f036726.js → oauth-6ceceb62191dfe8a.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-f65416f6dbe30ad3.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{pipeline-runs-5f8c100e648efa8a.js → pipeline-runs-2d0136b51b57de93.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-688c652f3296bb9c.js → [...slug]-1ad5238742e25b4c.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-bd11e87d026bfbf9.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{dashboard-1236e36d39b1637d.js → dashboard-0f4f47f721b0723f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-5ae8efe9e0530212.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-fe91dfb0091f6bc6.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-0d68d4bf6290fefb.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-cf794b2d22a80f31.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-9254358d58f07714.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-a964caef91bed9e1.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{monitors-821001e690caebe2.js → monitors-80bebb4401eefe25.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-2eae7cb017027682.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-2d4b2a0800a66b33.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-776b2e5b0b6ceba8.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-03d9bca3bc5e6088.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-707ed8ca942ca802.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/{[...slug]-259143ed3cf59e31.js → [...slug]-8429f17d4146e1ec.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-193045d9836d8d80.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-d25d07db166cbb04.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/platform/global-hooks/{[...slug]-5eeec927e4202b63.js → [...slug]-6834ae87bd668cb2.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/platform/global-hooks-fbe9ad995d46d837.js → frontend_dist_base_path_template/_next/static/chunks/pages/platform/global-hooks-b3f7309a23e592b2.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/{profile-fc659962d4015cb3.js → profile-f8b7374385e1f1bf.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-8de68502a9afa299.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/platform/settings-a4f88c334414402b.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/settings-50fb6a34f3913f1f.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/permissions/{[...slug]-4deb9579ef99a3c6.js → [...slug]-2e5c098c21ea32b7.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{permissions-e0cda2f2bfce8d61.js → permissions-54e4b15b9585bfc4.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-040f83d75d0f6537.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/roles/{[...slug]-910257d16c604ebd.js → [...slug]-95088f43034e3c95.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{roles-4f7a0756806cee34.js → roles-e9149e1fcf218f42.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/{sync-data-208d6f955204d704.js → sync-data-75b67ae4a00818ef.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users/{[...slug]-c89dc67e5a1706a8.js → [...slug]-557dda05ca6c6124.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users-fa61dc6c1370e6a5.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{sign-in-054b33312d3193c3.js → sign-in-593c40985d63fcf7.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/templates/{[...slug]-b6ed6a5d818bfd20.js → [...slug]-252c4b6b818345d5.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{templates-852357bc983af2ea.js → templates-ca528bc607753ab8.js} +1 -1
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/terminal-1f9c56d671bbc67d.js → frontend_dist_base_path_template/_next/static/chunks/pages/terminal-287362c1defcc96b.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/test-2f83af8c9f1378fe.js +1 -0
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-d9de73fb799efed8.js +1 -0
- mage_ai/server/{frontend_dist/_next/static/chunks/pages/version-control-ae3469b992a341d6.js → frontend_dist_base_path_template/_next/static/chunks/pages/version-control-573f0225d7a703ed.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-12ad70eb5c31aa92.js → webpack-5f4be622608d9267.js} +1 -1
- mage_ai/server/frontend_dist_base_path_template/block-layout.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/compute.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/files.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-data-products.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/global-hooks.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/index.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/manage/files.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/overview.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/pipeline-runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage/users.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/manage.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/oauth.html +5 -5
- mage_ai/server/frontend_dist_base_path_template/overview.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +3 -3
- mage_ai/server/frontend_dist_base_path_template/pipelines.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/settings.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/sign-in.html +7 -7
- mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +6 -6
- mage_ai/server/frontend_dist_base_path_template/templates.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/terminal.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/test.html +3 -3
- mage_ai/server/frontend_dist_base_path_template/triggers.html +6 -6
- mage_ai/server/frontend_dist_base_path_template/v2/canvas.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/v2.html +2 -2
- mage_ai/server/frontend_dist_base_path_template/version-control.html +6 -6
- mage_ai/server/scheduler_manager.py +2 -0
- mage_ai/server/server.py +13 -0
- mage_ai/server/terminal_server.py +3 -0
- mage_ai/server/utils/output_display.py +5 -3
- mage_ai/services/aws/events/events.py +2 -2
- mage_ai/services/gcp/cloud_run/cloud_run.py +1 -1
- mage_ai/services/teams/config.py +13 -2
- mage_ai/services/teams/teams.py +13 -11
- mage_ai/settings/server.py +12 -1
- mage_ai/shared/constants.py +3 -1
- mage_ai/shared/croniter.py +1398 -0
- mage_ai/shared/enum.py +2 -5
- mage_ai/shared/environments.py +27 -3
- mage_ai/streaming/sinks/elasticsearch.py +15 -5
- mage_ai/streaming/sinks/kafka.py +21 -3
- mage_ai/streaming/sources/kafka.py +64 -7
- mage_ai/streaming/sources/kafka_oauth.py +182 -0
- mage_ai/tests/api/endpoints/test_blocks.py +1 -101
- mage_ai/tests/api/endpoints/test_configuration_options.py +1 -48
- mage_ai/tests/api/endpoints/test_configuration_options_project_platform.py +68 -0
- mage_ai/tests/api/endpoints/test_custom_designs.py +1 -106
- mage_ai/tests/api/endpoints/test_custom_designs_project_platform.py +132 -0
- mage_ai/tests/api/endpoints/test_dbt_blocks.py +111 -0
- mage_ai/tests/api/endpoints/test_file_contents.py +0 -48
- mage_ai/tests/api/endpoints/test_file_contents_with_project_platform.py +66 -0
- mage_ai/tests/api/endpoints/test_pipelines.py +0 -134
- mage_ai/tests/api/endpoints/test_pipelines_with_project_platform.py +143 -0
- mage_ai/tests/data_preparation/executors/test_block_executor.py +3 -3
- mage_ai/tests/data_preparation/logging/test_logger_manager.py +24 -5
- mage_ai/tests/data_preparation/models/block/dynamic/test_counter.py +1 -3
- mage_ai/tests/data_preparation/models/block/hook/test_hook_block.py +3 -3
- mage_ai/tests/data_preparation/models/test_block.py +7 -0
- mage_ai/tests/data_preparation/models/test_pipeline.py +55 -0
- mage_ai/tests/data_preparation/models/test_variable.py +2 -0
- mage_ai/tests/data_preparation/test_repo_manager.py +0 -63
- mage_ai/tests/data_preparation/test_repo_manager_project_platform.py +67 -0
- mage_ai/tests/data_preparation/test_variable_manager.py +0 -51
- mage_ai/tests/data_preparation/test_variable_manager_project_platform.py +41 -0
- mage_ai/tests/io/create_table/test_postgresql.py +28 -0
- mage_ai/tests/orchestration/db/models/test_schedules.py +1 -1
- mage_ai/tests/orchestration/notification/test_config.py +3 -3
- mage_ai/tests/orchestration/notification/test_sender.py +5 -1
- mage_ai/tests/orchestration/utils/__init__.py +0 -0
- mage_ai/tests/orchestration/utils/test_resources.py +235 -0
- mage_ai/tests/shared/test_croniter.py +2541 -0
- mage_ai/tests/streaming/sinks/test_kafka.py +130 -0
- mage_ai/tests/streaming/sources/test_kafka.py +125 -3
- mage_ai/tests/streaming/sources/test_kafka_oauth.py +208 -0
- mage_ai/tests/streaming/sources/test_kafka_raw_value.py +105 -0
- mage_ai/usage_statistics/logger.py +99 -15
- mage_ai-0.9.79.dist-info/METADATA +358 -0
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info}/RECORD +377 -359
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info}/WHEEL +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1557-1ad0c64c2d08e569.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2717-d65056b6b5e124eb.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3548-b2c5edfb710886a6.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3782-4b3091e550f809a2.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-5bdff745074fb350.js +0 -2
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-a5e9d77ed5b50205.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-69af3253ad0d0d89.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-fe112809feb25b05.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-e9ca358209cdf93d.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-a29f1615d2e7d330.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-6d382ae5bad9745c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-cd49372ae1702963.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-135be8974f7f5f2b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-3af13e89adff4d6c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-b578b075a8d857e3.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/platform/preferences-058d283ee178c038.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-7b02bb70462144cb.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/users-5212c01a9dc558da.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/test-86b12cc12d4a625f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-2481c40b18d5b6d4.js +0 -1
- mage_ai/server/frontend_dist/_next/static/pLWT6Sqd09xYpufCVIqnz/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/JQewSAObpbhO0wrdAM6Ng/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1557-1ad0c64c2d08e569.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2717-d65056b6b5e124eb.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3548-b2c5edfb710886a6.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3782-4b3091e550f809a2.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-90de19bc03f1484b.js +0 -2
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/users-a5e9d77ed5b50205.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-69af3253ad0d0d89.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-fe112809feb25b05.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-e9ca358209cdf93d.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-a29f1615d2e7d330.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-6d382ae5bad9745c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-cd49372ae1702963.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-135be8974f7f5f2b.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-3af13e89adff4d6c.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-b578b075a8d857e3.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/platform/preferences-058d283ee178c038.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-7b02bb70462144cb.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/users-5212c01a9dc558da.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/test-86b12cc12d4a625f.js +0 -1
- mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-2481c40b18d5b6d4.js +0 -1
- mage_ai-0.9.74.dist-info/METADATA +0 -544
- /mage_ai/server/frontend_dist/_next/static/{pLWT6Sqd09xYpufCVIqnz → TUo4RceCdMufBTBTq8CAq}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist/_next/static/chunks/pages/{_app-5bdff745074fb350.js.LICENSE.txt → _app-b697b35dfc4e6e26.js.LICENSE.txt} +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/{JQewSAObpbhO0wrdAM6Ng → 2QL-FT4lFR0a9bDZ7lNd9}/_ssgManifest.js +0 -0
- /mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{_app-90de19bc03f1484b.js.LICENSE.txt → _app-f205accb03b9ff43.js.LICENSE.txt} +0 -0
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info/licenses}/LICENSE +0 -0
- {mage_ai-0.9.74.dist-info → mage_ai-0.9.79.dist-info}/top_level.txt +0 -0
|
@@ -5,7 +5,9 @@ from typing import Any, Dict, Optional, Tuple, Union
|
|
|
5
5
|
|
|
6
6
|
import dbt.flags as flags
|
|
7
7
|
import pandas as pd
|
|
8
|
-
from dbt.adapters.base import BaseRelation
|
|
8
|
+
from dbt.adapters.base.relation import BaseRelation
|
|
9
|
+
from dbt.adapters.contracts.connection import AdapterResponse, Credentials
|
|
10
|
+
from dbt.adapters.contracts.relation import RelationType
|
|
9
11
|
from dbt.adapters.factory import (
|
|
10
12
|
Adapter,
|
|
11
13
|
cleanup_connections,
|
|
@@ -13,10 +15,10 @@ from dbt.adapters.factory import (
|
|
|
13
15
|
register_adapter,
|
|
14
16
|
reset_adapters,
|
|
15
17
|
)
|
|
16
|
-
from dbt.config.
|
|
18
|
+
from dbt.config.project import read_project_flags
|
|
17
19
|
from dbt.config.runtime import RuntimeConfig
|
|
18
|
-
from dbt.
|
|
19
|
-
from dbt.
|
|
20
|
+
from dbt.context.providers import generate_runtime_macro_context
|
|
21
|
+
from dbt.mp_context import get_mp_context
|
|
20
22
|
|
|
21
23
|
from mage_ai.data_preparation.models.block.dbt.profiles import Profiles
|
|
22
24
|
from mage_ai.shared.environments import is_debug
|
|
@@ -79,7 +81,11 @@ class DBTAdapter:
|
|
|
79
81
|
# remove interpolated profiles.yml
|
|
80
82
|
self.__profiles.clean()
|
|
81
83
|
|
|
82
|
-
def execute(
|
|
84
|
+
def execute(
|
|
85
|
+
self,
|
|
86
|
+
sql: str,
|
|
87
|
+
fetch: bool = False
|
|
88
|
+
) -> Tuple[AdapterResponse, pd.DataFrame]:
|
|
83
89
|
"""
|
|
84
90
|
Executes any sql statement using the dbt adapter.
|
|
85
91
|
|
|
@@ -135,6 +141,8 @@ class DBTAdapter:
|
|
|
135
141
|
package
|
|
136
142
|
)
|
|
137
143
|
|
|
144
|
+
self.__adapter.set_macro_resolver(manifest)
|
|
145
|
+
|
|
138
146
|
# create a context for the macro (e.g. downstream macros)
|
|
139
147
|
from dbt.context.providers import generate_runtime_macro_context
|
|
140
148
|
macro_context = generate_runtime_macro_context(
|
|
@@ -203,7 +211,7 @@ class DBTAdapter:
|
|
|
203
211
|
# set dbt flags
|
|
204
212
|
# Need to add profiles.yml file
|
|
205
213
|
try:
|
|
206
|
-
user_config =
|
|
214
|
+
user_config = read_project_flags(self.project_path, profiles_path)
|
|
207
215
|
except Exception as err:
|
|
208
216
|
print(f'[ERROR] DBTAdapter.open: {err}.')
|
|
209
217
|
|
|
@@ -211,7 +219,10 @@ class DBTAdapter:
|
|
|
211
219
|
not profiles_path.endswith('profiles.yml'):
|
|
212
220
|
|
|
213
221
|
try:
|
|
214
|
-
user_config =
|
|
222
|
+
user_config = read_project_flags(
|
|
223
|
+
self.project_path,
|
|
224
|
+
os.path.join(profiles_path, 'profiles.yml')
|
|
225
|
+
)
|
|
215
226
|
except Exception as err2:
|
|
216
227
|
print(f'[ERROR] DBTAdapter.open: {err2}.')
|
|
217
228
|
raise err
|
|
@@ -227,9 +238,10 @@ class DBTAdapter:
|
|
|
227
238
|
config = RuntimeConfig.from_args(adapter_config)
|
|
228
239
|
reset_adapters()
|
|
229
240
|
# register the correct adapter from config
|
|
230
|
-
register_adapter(config)
|
|
241
|
+
register_adapter(config, mp_context=get_mp_context())
|
|
231
242
|
# load the adapter
|
|
232
243
|
self.__adapter = get_adapter(config)
|
|
244
|
+
self.__adapter.set_macro_context_generator(generate_runtime_macro_context)
|
|
233
245
|
# connect
|
|
234
246
|
self.__adapter.acquire_connection('mage_dbt_adapter_' + uuid.uuid4().hex)
|
|
235
247
|
return self
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
CHILD_DATA_VARIABLE_UUID = 'output_0'
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
from typing import Any, Iterable, List, Optional, Sequence
|
|
2
2
|
|
|
3
3
|
from mage_ai.data.tabular.reader import read_metadata
|
|
4
|
-
from mage_ai.data_preparation.models.block.dynamic.constants import (
|
|
5
|
-
CHILD_DATA_VARIABLE_UUID,
|
|
6
|
-
)
|
|
7
4
|
from mage_ai.data_preparation.models.block.dynamic.utils import (
|
|
8
5
|
is_dynamic_block,
|
|
9
6
|
is_dynamic_block_child,
|
|
10
7
|
should_reduce_output,
|
|
11
8
|
)
|
|
9
|
+
from mage_ai.data_preparation.models.constants import CHILD_DATA_VARIABLE_UUID
|
|
12
10
|
from mage_ai.data_preparation.models.variables.cache import VariableAggregateCache
|
|
13
11
|
from mage_ai.data_preparation.models.variables.constants import (
|
|
14
12
|
VariableAggregateDataType,
|
|
@@ -343,7 +343,13 @@ def format_output_data(
|
|
|
343
343
|
columns=columns_to_display,
|
|
344
344
|
rows=[
|
|
345
345
|
list(row.values())
|
|
346
|
-
for row in json.loads(
|
|
346
|
+
for row in json.loads(
|
|
347
|
+
simplejson.dumps(
|
|
348
|
+
data[columns_to_display].to_dicts(),
|
|
349
|
+
default=encode_complex,
|
|
350
|
+
ignore_nan=True,
|
|
351
|
+
)
|
|
352
|
+
)
|
|
347
353
|
],
|
|
348
354
|
),
|
|
349
355
|
resource_usage=resource_usage,
|
|
@@ -8,7 +8,10 @@ import pandas as pd
|
|
|
8
8
|
import simplejson
|
|
9
9
|
|
|
10
10
|
from mage_ai.data_preparation.models.block import Block
|
|
11
|
-
from mage_ai.data_preparation.models.constants import
|
|
11
|
+
from mage_ai.data_preparation.models.constants import (
|
|
12
|
+
CHILD_DATA_VARIABLE_UUID,
|
|
13
|
+
BlockType,
|
|
14
|
+
)
|
|
12
15
|
from mage_ai.data_preparation.models.variables.constants import (
|
|
13
16
|
DATAFRAME_CSV_FILE,
|
|
14
17
|
VariableType,
|
|
@@ -81,7 +84,10 @@ def execute_r_code(
|
|
|
81
84
|
|
|
82
85
|
if len(output_variable_objects) > 0:
|
|
83
86
|
df = pd.read_csv(
|
|
84
|
-
os.path.join(
|
|
87
|
+
os.path.join(
|
|
88
|
+
output_variable_objects[0].variable_path,
|
|
89
|
+
DATAFRAME_CSV_FILE
|
|
90
|
+
)
|
|
85
91
|
)
|
|
86
92
|
else:
|
|
87
93
|
df = None
|
|
@@ -129,14 +135,19 @@ def __render_r_script(
|
|
|
129
135
|
raise Exception(
|
|
130
136
|
f"Block execution for {block.type} with R language is not supported.",
|
|
131
137
|
)
|
|
132
|
-
template = template_env.get_template(
|
|
138
|
+
template = template_env.get_template(
|
|
139
|
+
BLOCK_TYPE_TO_EXECUTION_TEMPLATE[block.type]
|
|
140
|
+
)
|
|
133
141
|
|
|
134
142
|
output_variable_object = block.variable_object(
|
|
135
|
-
|
|
143
|
+
CHILD_DATA_VARIABLE_UUID,
|
|
136
144
|
execution_partition=execution_partition,
|
|
137
145
|
)
|
|
138
146
|
os.makedirs(output_variable_object.variable_path, exist_ok=True)
|
|
139
|
-
output_path = os.path.join(
|
|
147
|
+
output_path = os.path.join(
|
|
148
|
+
output_variable_object.variable_path,
|
|
149
|
+
DATAFRAME_CSV_FILE
|
|
150
|
+
)
|
|
140
151
|
|
|
141
152
|
global_vars_str = __render_global_vars(global_vars=global_vars)
|
|
142
153
|
|
|
@@ -150,6 +150,7 @@ def execute_sql_code(
|
|
|
150
150
|
interpolate_vars_options = dict(
|
|
151
151
|
block=block,
|
|
152
152
|
dynamic_block_index=dynamic_block_index,
|
|
153
|
+
execution_partition=execution_partition,
|
|
153
154
|
global_vars=global_vars,
|
|
154
155
|
)
|
|
155
156
|
|
|
@@ -368,6 +369,7 @@ def execute_sql_code(
|
|
|
368
369
|
loader,
|
|
369
370
|
block,
|
|
370
371
|
query_string,
|
|
372
|
+
disable_query_preprocessing=disable_query_preprocessing,
|
|
371
373
|
configuration=configuration,
|
|
372
374
|
should_query=should_query,
|
|
373
375
|
)
|
|
@@ -67,9 +67,17 @@ def execute_raw_sql(
|
|
|
67
67
|
query_string: str,
|
|
68
68
|
configuration: Dict = None,
|
|
69
69
|
should_query: bool = False,
|
|
70
|
+
disable_query_preprocessing: bool = False,
|
|
70
71
|
) -> List[Any]:
|
|
71
72
|
if configuration is None:
|
|
72
73
|
configuration = {}
|
|
74
|
+
|
|
75
|
+
if disable_query_preprocessing:
|
|
76
|
+
return loader.execute_query_raw(
|
|
77
|
+
query_string,
|
|
78
|
+
configuration=configuration,
|
|
79
|
+
)
|
|
80
|
+
|
|
73
81
|
queries = []
|
|
74
82
|
fetch_query_at_indexes = []
|
|
75
83
|
|
|
@@ -232,7 +232,8 @@ def interpolate_vars(
|
|
|
232
232
|
content: str,
|
|
233
233
|
global_vars: Dict = None,
|
|
234
234
|
block=None,
|
|
235
|
-
dynamic_block_index: int = None
|
|
235
|
+
dynamic_block_index: int = None,
|
|
236
|
+
execution_partition: str = None,
|
|
236
237
|
) -> str :
|
|
237
238
|
if not content:
|
|
238
239
|
return content
|
|
@@ -241,7 +242,10 @@ def interpolate_vars(
|
|
|
241
242
|
|
|
242
243
|
if block:
|
|
243
244
|
content = block.interpolate_content(
|
|
244
|
-
content,
|
|
245
|
+
content,
|
|
246
|
+
variables=global_vars,
|
|
247
|
+
dynamic_block_index=dynamic_block_index,
|
|
248
|
+
execution_partition=execution_partition,
|
|
245
249
|
)
|
|
246
250
|
|
|
247
251
|
return Template(
|
|
@@ -15,7 +15,7 @@ DATA_INTEGRATION_CATALOG_FILE = 'data_integration_catalog.json'
|
|
|
15
15
|
DATAFRAME_ANALYSIS_MAX_COLUMNS = 100
|
|
16
16
|
DATAFRAME_ANALYSIS_MAX_ROWS = 100_000
|
|
17
17
|
DATAFRAME_SAMPLE_COUNT = 1000
|
|
18
|
-
DATAFRAME_SAMPLE_COUNT_PREVIEW = 10
|
|
18
|
+
DATAFRAME_SAMPLE_COUNT_PREVIEW = int(os.getenv('DATAFRAME_SAMPLE_COUNT_PREVIEW', 10) or 10)
|
|
19
19
|
DATAFRAME_SAMPLE_MAX_COLUMNS = 1000
|
|
20
20
|
DYNAMIC_CHILD_BLOCK_SAMPLE_COUNT_PREVIEW = 10
|
|
21
21
|
LOGS_SUBDIR = '.logs'
|
|
@@ -27,6 +27,7 @@ PIPELINES_FOLDER = 'pipelines'
|
|
|
27
27
|
PREFERENCES_FILE = '.preferences.yaml'
|
|
28
28
|
REPO_CONFIG_FILE = 'metadata.yaml'
|
|
29
29
|
VARIABLE_DIR = '.variables'
|
|
30
|
+
CHILD_DATA_VARIABLE_UUID = 'output_0'
|
|
30
31
|
|
|
31
32
|
PIPELINE_RUN_STATUS_LAST_RUN_FAILED = 'last_run_failed'
|
|
32
33
|
|
|
@@ -81,6 +82,7 @@ class BlockColor(StrEnum):
|
|
|
81
82
|
|
|
82
83
|
|
|
83
84
|
class CallbackStatus(StrEnum):
|
|
85
|
+
CANCELLED = 'cancelled'
|
|
84
86
|
FAILURE = 'failure'
|
|
85
87
|
SUCCESS = 'success'
|
|
86
88
|
|
|
@@ -125,6 +127,7 @@ BLOCK_LANGUAGE_TO_FILE_EXTENSION = {
|
|
|
125
127
|
|
|
126
128
|
|
|
127
129
|
CALLBACK_STATUSES = [
|
|
130
|
+
CallbackStatus.CANCELLED,
|
|
128
131
|
CallbackStatus.FAILURE,
|
|
129
132
|
CallbackStatus.SUCCESS,
|
|
130
133
|
]
|
|
@@ -4,6 +4,7 @@ import json
|
|
|
4
4
|
import os
|
|
5
5
|
import shutil
|
|
6
6
|
import tempfile
|
|
7
|
+
import time
|
|
7
8
|
import zipfile
|
|
8
9
|
from datetime import datetime, timezone
|
|
9
10
|
from io import BytesIO
|
|
@@ -77,6 +78,7 @@ from mage_ai.orchestration.notification.sender import NotificationSender
|
|
|
77
78
|
from mage_ai.settings.platform import build_repo_path_for_all_projects
|
|
78
79
|
from mage_ai.settings.platform.constants import project_platform_activated
|
|
79
80
|
from mage_ai.settings.repo import get_repo_path
|
|
81
|
+
from mage_ai.settings.server import RUN_PIPELINE_IN_ONE_PROCESS
|
|
80
82
|
from mage_ai.shared.array import find
|
|
81
83
|
from mage_ai.shared.hash import extract, ignore_keys, index_by, merge_dict
|
|
82
84
|
from mage_ai.shared.io import safe_write, safe_write_async
|
|
@@ -127,7 +129,7 @@ class Pipeline:
|
|
|
127
129
|
|
|
128
130
|
self.repo_path = repo_path or get_repo_path()
|
|
129
131
|
self.retry_config = {}
|
|
130
|
-
self.run_pipeline_in_one_process =
|
|
132
|
+
self.run_pipeline_in_one_process = RUN_PIPELINE_IN_ONE_PROCESS
|
|
131
133
|
self.schedules = []
|
|
132
134
|
self.settings = {}
|
|
133
135
|
self.tags = tags or []
|
|
@@ -884,7 +886,10 @@ class Pipeline:
|
|
|
884
886
|
self.executor_type = config.get('executor_type')
|
|
885
887
|
self.notification_config = config.get('notification_config') or {}
|
|
886
888
|
self.retry_config = config.get('retry_config') or {}
|
|
887
|
-
self.run_pipeline_in_one_process = config.get(
|
|
889
|
+
self.run_pipeline_in_one_process = config.get(
|
|
890
|
+
'run_pipeline_in_one_process',
|
|
891
|
+
RUN_PIPELINE_IN_ONE_PROCESS,
|
|
892
|
+
)
|
|
888
893
|
self.settings = PipelineSettings.load(**config.get('settings') or {})
|
|
889
894
|
self.spark_config = config.get('spark_config') or {}
|
|
890
895
|
self.tags = config.get('tags') or []
|
|
@@ -2328,6 +2333,10 @@ class Pipeline:
|
|
|
2328
2333
|
extension_uuid: str = None,
|
|
2329
2334
|
widget: bool = False,
|
|
2330
2335
|
):
|
|
2336
|
+
# Introduce a small delay to prevent multiple changes from generating
|
|
2337
|
+
# identical timestamps for the pipeline YAML file
|
|
2338
|
+
time.sleep(0.0005)
|
|
2339
|
+
|
|
2331
2340
|
blocks_current = sorted([b.uuid for b in self.blocks_by_uuid.values()])
|
|
2332
2341
|
|
|
2333
2342
|
if block_uuid is not None:
|
|
@@ -214,10 +214,12 @@ class Project:
|
|
|
214
214
|
return [self.repo_path]
|
|
215
215
|
|
|
216
216
|
def projects(self) -> Dict:
|
|
217
|
-
|
|
217
|
+
projects = project_platform_settings(
|
|
218
218
|
context_data=self.context_data,
|
|
219
219
|
mage_projects_only=True
|
|
220
220
|
)
|
|
221
|
+
sorted_projects = {k: projects[k] for k in sorted(projects)}
|
|
222
|
+
return sorted_projects
|
|
221
223
|
|
|
222
224
|
def is_feature_enabled(self, feature_name: FeatureUUID) -> bool:
|
|
223
225
|
feature_enabled = self.features.get(feature_name.value, False)
|
|
@@ -5,12 +5,12 @@ from datetime import datetime, timezone
|
|
|
5
5
|
from typing import Dict, List, Optional
|
|
6
6
|
|
|
7
7
|
import yaml
|
|
8
|
-
from croniter import croniter
|
|
9
8
|
|
|
10
9
|
from mage_ai.data_preparation.models.constants import PIPELINES_FOLDER
|
|
11
10
|
from mage_ai.settings.repo import get_repo_path
|
|
12
11
|
from mage_ai.shared.config import BaseConfig
|
|
13
12
|
from mage_ai.shared.constants import VALID_ENVS
|
|
13
|
+
from mage_ai.shared.croniter import croniter
|
|
14
14
|
from mage_ai.shared.enum import StrEnum
|
|
15
15
|
from mage_ai.shared.hash import index_by
|
|
16
16
|
from mage_ai.shared.io import safe_write
|
|
@@ -121,7 +121,10 @@ class LocalStorage(BaseStorage):
|
|
|
121
121
|
return pd.read_parquet(file_path, engine='pyarrow')
|
|
122
122
|
|
|
123
123
|
def read_polars_parquet(self, file_path: str, **kwargs) -> pl.DataFrame:
|
|
124
|
-
|
|
124
|
+
try:
|
|
125
|
+
return pl.read_parquet(file_path, use_pyarrow=True)
|
|
126
|
+
except Exception:
|
|
127
|
+
return pl.read_parquet(file_path)
|
|
125
128
|
|
|
126
129
|
def write_csv(self, df: pd.DataFrame, file_path: str) -> None:
|
|
127
130
|
File.create_parent_directories(file_path)
|
|
@@ -19,6 +19,13 @@ GROUP_ROW_ACTIONS = 'Row actions'
|
|
|
19
19
|
GROUP_SHIFT = 'Shift'
|
|
20
20
|
|
|
21
21
|
TEMPLATES = [
|
|
22
|
+
dict(
|
|
23
|
+
block_type=BlockType.DATA_LOADER,
|
|
24
|
+
description='Load a Table from Airtable App.',
|
|
25
|
+
language=BlockLanguage.PYTHON,
|
|
26
|
+
name='Airtable',
|
|
27
|
+
path='data_loaders/airtable.py',
|
|
28
|
+
),
|
|
22
29
|
dict(
|
|
23
30
|
block_type=BlockType.DATA_LOADER,
|
|
24
31
|
description='Load a Delta Table from Amazon S3.',
|
|
@@ -2,6 +2,9 @@ connector_type: elasticsearch
|
|
|
2
2
|
host: http://localhost
|
|
3
3
|
index_name: elastic_index
|
|
4
4
|
api_key: api_key_for_elastic_search
|
|
5
|
+
# # When using Data streams this must be set to create as they are Append-only indexes
|
|
6
|
+
# _op_type: None / index, create or update
|
|
7
|
+
# _source: None (Default '_doc') / Specify the source field
|
|
5
8
|
# # Whether to verify SSL certificates to authenticate.
|
|
6
9
|
# verify_certs: true
|
|
7
10
|
# ca_cert: "certificate.cert"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{% extends "data_loaders/default.jinja" %}
|
|
2
|
+
{% block imports %}
|
|
3
|
+
from mage_ai.settings.repo import get_repo_path
|
|
4
|
+
from mage_ai.io.config import ConfigFileLoader
|
|
5
|
+
from mage_ai.io.airtable import Airtable
|
|
6
|
+
from os import path
|
|
7
|
+
{{ super() -}}
|
|
8
|
+
{% endblock %}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
{% block content %}
|
|
12
|
+
@data_loader
|
|
13
|
+
def load_data_from_airtable(*args, **kwargs):
|
|
14
|
+
"""
|
|
15
|
+
Template for loading data from Airtable.
|
|
16
|
+
Specify your configuration settings in 'io_config.yaml'.
|
|
17
|
+
"""
|
|
18
|
+
config_path = path.join(get_repo_path(), 'io_config.yaml')
|
|
19
|
+
config_profile = 'default'
|
|
20
|
+
|
|
21
|
+
base_id = 'your_base_id'
|
|
22
|
+
table_name = 'your_table_name'
|
|
23
|
+
|
|
24
|
+
return Airtable.with_config(ConfigFileLoader(config_path, config_profile)).load(
|
|
25
|
+
base_id=base_id,
|
|
26
|
+
table_name=table_name
|
|
27
|
+
)
|
|
28
|
+
{% endblock %}
|
|
@@ -17,9 +17,12 @@ timeout: 5
|
|
|
17
17
|
|
|
18
18
|
# Optional: TLS configuration
|
|
19
19
|
use_tls: false
|
|
20
|
-
|
|
21
|
-
#
|
|
22
|
-
#
|
|
20
|
+
|
|
21
|
+
# Optional: SSL configuration
|
|
22
|
+
# ssl_config:
|
|
23
|
+
# cafile: "path/to/ca.pem"
|
|
24
|
+
# certfile: "path/to/client-cert.pem"
|
|
25
|
+
# keyfile: "path/to/client-key.pem"
|
|
23
26
|
|
|
24
27
|
# Optional: NKEY seed string
|
|
25
28
|
# nkeys_seed_str: "SUAPAEYJQOQHJ4"
|
|
@@ -11,6 +11,8 @@ default:
|
|
|
11
11
|
ALGOLIA_APP_ID: app_id
|
|
12
12
|
ALGOLIA_API_KEY: api_key
|
|
13
13
|
ALGOLIA_INDEX_NAME: index_name
|
|
14
|
+
# Airtable
|
|
15
|
+
AIRTABLE_ACCESS_TOKEN: token
|
|
14
16
|
# Azure
|
|
15
17
|
AZURE_CLIENT_ID: "{{ env_var('AZURE_CLIENT_ID') }}"
|
|
16
18
|
AZURE_CLIENT_SECRET: "{{ env_var('AZURE_CLIENT_SECRET') }}"
|
mage_ai/io/airtable.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import polars as pl
|
|
5
|
+
from pyairtable.api import Api
|
|
6
|
+
|
|
7
|
+
from mage_ai.io.base import BaseIO
|
|
8
|
+
from mage_ai.io.config import BaseConfigLoader, ConfigKey
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Airtable(BaseIO):
|
|
12
|
+
"""
|
|
13
|
+
Handles data transfer between Airtable tables and the Mage app.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
token: str,
|
|
19
|
+
verbose: bool = True,
|
|
20
|
+
**kwargs) -> None:
|
|
21
|
+
"""
|
|
22
|
+
Initializes a connection to Airtable.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
token (str): Airtable API token.
|
|
26
|
+
verbose (bool, optional): Whether to print verbose output. Defaults to True.
|
|
27
|
+
**kwargs: Additional keyword arguments to pass to the pyairtable Api constructor.
|
|
28
|
+
"""
|
|
29
|
+
super().__init__(verbose=verbose)
|
|
30
|
+
self.client = Api(token, **kwargs) # Create the Airtable API client
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def with_config(
|
|
34
|
+
cls,
|
|
35
|
+
config: BaseConfigLoader
|
|
36
|
+
) -> 'Airtable':
|
|
37
|
+
"""
|
|
38
|
+
Initializes an Airtable client from a configuration loader.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
config (BaseConfigLoader): Configuration loader object.
|
|
42
|
+
|
|
43
|
+
Raises:
|
|
44
|
+
ValueError: If no valid Airtable API token is found in the configuration.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Airtable: An instance of the Airtable class.
|
|
48
|
+
"""
|
|
49
|
+
if ConfigKey.AIRTABLE_ACCESS_TOKEN not in config:
|
|
50
|
+
raise ValueError(
|
|
51
|
+
'No valid API token found for Airtable.'
|
|
52
|
+
'You must specify your access token in your config.'
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return cls(
|
|
56
|
+
token=config[ConfigKey.AIRTABLE_ACCESS_TOKEN]
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def load(
|
|
60
|
+
self,
|
|
61
|
+
base_id: str,
|
|
62
|
+
table_name: str,
|
|
63
|
+
**kwargs,
|
|
64
|
+
) -> pd.DataFrame:
|
|
65
|
+
"""
|
|
66
|
+
Loads data from an Airtable table into a Pandas DataFrame.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
base_id (str): The ID of the Airtable base (e.g., 'app*****').
|
|
70
|
+
table_name (str): The name or ID of the Airtable table (e.g., 'tbl*****').
|
|
71
|
+
**kwargs: Additional keyword arguments to pass to the pyairtable table.all() method.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
DataFrame: A Pandas DataFrame containing the data from the Airtable table.
|
|
75
|
+
"""
|
|
76
|
+
with self.printer.print_msg(
|
|
77
|
+
f'Loading data frame from table \'{table_name}\' at airtable app \'{base_id}\''
|
|
78
|
+
):
|
|
79
|
+
table = self.client.table(base_id, table_name) # Get the Airtable table
|
|
80
|
+
data = table.all(**kwargs) # Fetch all records from the table
|
|
81
|
+
|
|
82
|
+
# Flatten the Airtable data structure into a list of dictionaries
|
|
83
|
+
flattened_data = []
|
|
84
|
+
for record in data:
|
|
85
|
+
flattened_record = {
|
|
86
|
+
'id': record['id'],
|
|
87
|
+
'createdTime': record['createdTime']
|
|
88
|
+
}
|
|
89
|
+
fields = record['fields']
|
|
90
|
+
flattened_record.update(fields)
|
|
91
|
+
flattened_data.append(flattened_record)
|
|
92
|
+
|
|
93
|
+
return pd.DataFrame(flattened_data) # Create and return a DataFrame
|
|
94
|
+
|
|
95
|
+
def export(
|
|
96
|
+
self,
|
|
97
|
+
df: Union[pd.DataFrame, pl.DataFrame],
|
|
98
|
+
*args,
|
|
99
|
+
**kwargs
|
|
100
|
+
) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Not implemented yet. This method is intended to export data to Airtable.
|
|
103
|
+
"""
|
|
104
|
+
pass
|
mage_ai/io/base.py
CHANGED
|
@@ -16,6 +16,7 @@ QUERY_ROW_LIMIT = 10_000_000
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class DataSource(StrEnum):
|
|
19
|
+
AIRTABLE = 'airtable'
|
|
19
20
|
ALGOLIA = 'algolia'
|
|
20
21
|
API = 'api'
|
|
21
22
|
BIGQUERY = 'bigquery'
|
|
@@ -47,6 +48,26 @@ class FileFormat(StrEnum):
|
|
|
47
48
|
PARQUET = 'parquet'
|
|
48
49
|
HDF5 = 'hdf5'
|
|
49
50
|
XML = 'xml'
|
|
51
|
+
EXCEL = 'excel'
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def from_extension(cls, ext: str):
|
|
55
|
+
if ext == 'csv':
|
|
56
|
+
return cls.CSV
|
|
57
|
+
elif ext == 'json':
|
|
58
|
+
return cls.JSON
|
|
59
|
+
elif ext == 'parquet':
|
|
60
|
+
return cls.PARQUET
|
|
61
|
+
elif ext == 'hdf5':
|
|
62
|
+
return cls.HDF5
|
|
63
|
+
elif ext == 'xml':
|
|
64
|
+
return cls.XML
|
|
65
|
+
elif ext in ('xls', 'xlsx'):
|
|
66
|
+
return cls.EXCEL
|
|
67
|
+
else:
|
|
68
|
+
raise ValueError(
|
|
69
|
+
f'None file format found for this file extension: {ext}'
|
|
70
|
+
)
|
|
50
71
|
|
|
51
72
|
|
|
52
73
|
class ExportWritePolicy(BaseEnum):
|
|
@@ -126,7 +147,9 @@ class BaseFile(BaseIO):
|
|
|
126
147
|
pass
|
|
127
148
|
|
|
128
149
|
def _get_file_format(self, filepath: Union[os.PathLike, str]) -> str:
|
|
129
|
-
return
|
|
150
|
+
return FileFormat.from_extension(
|
|
151
|
+
os.path.splitext(os.path.basename(filepath))[-1][1:]
|
|
152
|
+
)
|
|
130
153
|
|
|
131
154
|
def __get_reader(self, format: Union[FileFormat, str, None]) -> Callable:
|
|
132
155
|
"""
|
|
@@ -151,6 +174,8 @@ class BaseFile(BaseIO):
|
|
|
151
174
|
return pd.read_hdf
|
|
152
175
|
elif format == FileFormat.XML:
|
|
153
176
|
return pd.read_xml
|
|
177
|
+
elif format == FileFormat.EXCEL:
|
|
178
|
+
return pd.read_excel
|
|
154
179
|
else:
|
|
155
180
|
raise ValueError(f"Invalid format '{format}' specified.")
|
|
156
181
|
|
|
@@ -249,6 +274,8 @@ class BaseFile(BaseIO):
|
|
|
249
274
|
return df.write_hdf5
|
|
250
275
|
elif format == FileFormat.XML:
|
|
251
276
|
return df.write_xml
|
|
277
|
+
elif format == FileFormat.EXCEL:
|
|
278
|
+
return df.write_excel
|
|
252
279
|
return df.write_parquet
|
|
253
280
|
|
|
254
281
|
elif isinstance(df, DataFrame): # pandas DataFrame
|
|
@@ -260,6 +287,8 @@ class BaseFile(BaseIO):
|
|
|
260
287
|
return df.to_hdf
|
|
261
288
|
elif format == FileFormat.XML:
|
|
262
289
|
return df.to_xml
|
|
290
|
+
elif format == FileFormat.EXCEL:
|
|
291
|
+
return df.to_excel
|
|
263
292
|
return df.to_parquet
|
|
264
293
|
|
|
265
294
|
def __del__(self):
|
mage_ai/io/bigquery.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import traceback
|
|
1
2
|
import uuid
|
|
2
3
|
from typing import Dict, List, Mapping, Union
|
|
3
4
|
|
|
4
5
|
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
5
7
|
from google.cloud.bigquery import (
|
|
6
8
|
Client,
|
|
7
9
|
LoadJobConfig,
|
|
@@ -399,7 +401,41 @@ WHERE table_id = '{table_name}'
|
|
|
399
401
|
# Clean column names
|
|
400
402
|
if type(df) is DataFrame:
|
|
401
403
|
df.columns = df.columns.str.replace(' ', '_')
|
|
404
|
+
table = None
|
|
405
|
+
try:
|
|
406
|
+
# Cast column types
|
|
407
|
+
table = self.client.get_table(table_id)
|
|
408
|
+
except Exception:
|
|
409
|
+
print(f'Table {table_id} does not exist.')
|
|
410
|
+
pass
|
|
402
411
|
|
|
412
|
+
if table is not None:
|
|
413
|
+
try:
|
|
414
|
+
timestamp_columns = [field.name for field in table.schema
|
|
415
|
+
if field.field_type == 'TIMESTAMP']
|
|
416
|
+
|
|
417
|
+
# Convert TIMESTAMP columns in DataFrame
|
|
418
|
+
for col in timestamp_columns:
|
|
419
|
+
if col in df.columns:
|
|
420
|
+
df[col] = pd.to_datetime(df[col])
|
|
421
|
+
except Exception:
|
|
422
|
+
print('Fail to cast column types in dataframe.')
|
|
423
|
+
traceback.print_exc()
|
|
424
|
+
if (
|
|
425
|
+
not config.schema and
|
|
426
|
+
config.write_disposition == WriteDisposition.WRITE_TRUNCATE
|
|
427
|
+
):
|
|
428
|
+
df_columns = df.columns.tolist()
|
|
429
|
+
config.schema = [
|
|
430
|
+
SchemaField(
|
|
431
|
+
field.name,
|
|
432
|
+
field.field_type,
|
|
433
|
+
mode=field.mode,
|
|
434
|
+
fields=field.fields,
|
|
435
|
+
)
|
|
436
|
+
for field in table.schema
|
|
437
|
+
if field.name in df_columns
|
|
438
|
+
]
|
|
403
439
|
return self.client.load_table_from_dataframe(df, table_id, job_config=config).result()
|
|
404
440
|
|
|
405
441
|
def execute(self, query_string: str, **kwargs) -> None:
|