mage-ai 0.9.73__py3-none-any.whl → 0.9.74__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.
Files changed (247) hide show
  1. mage_ai/ai/constants.py +2 -2
  2. mage_ai/ai/llm_pipeline_wizard.py +5 -3
  3. mage_ai/ai/openai_client.py +11 -0
  4. mage_ai/api/constants.py +4 -5
  5. mage_ai/api/oauth_scope.py +2 -2
  6. mage_ai/api/operations/constants.py +2 -2
  7. mage_ai/api/presenters/SyncPresenter.py +4 -1
  8. mage_ai/authentication/oauth/constants.py +2 -2
  9. mage_ai/authentication/operation_history/constants.py +2 -2
  10. mage_ai/authentication/permissions/constants.py +5 -6
  11. mage_ai/cache/constants.py +2 -2
  12. mage_ai/cache/dbt/constants.py +2 -3
  13. mage_ai/cluster_manager/constants.py +2 -2
  14. mage_ai/cluster_manager/kubernetes/workload_manager.py +3 -2
  15. mage_ai/command_center/constants.py +13 -13
  16. mage_ai/data_cleaner/column_types/constants.py +2 -2
  17. mage_ai/data_cleaner/transformer_actions/column.py +19 -7
  18. mage_ai/data_cleaner/transformer_actions/constants.py +10 -9
  19. mage_ai/data_integrations/sources/constants.py +2 -0
  20. mage_ai/data_preparation/git/utils.py +4 -1
  21. mage_ai/data_preparation/logging/__init__.py +2 -2
  22. mage_ai/data_preparation/logging/logger.py +3 -3
  23. mage_ai/data_preparation/models/block/__init__.py +9 -3
  24. mage_ai/data_preparation/models/block/data_integration/constants.py +2 -2
  25. mage_ai/data_preparation/models/block/dbt/constants.py +3 -3
  26. mage_ai/data_preparation/models/block/dynamic/factory.py +40 -3
  27. mage_ai/data_preparation/models/block/dynamic/utils.py +31 -33
  28. mage_ai/data_preparation/models/block/dynamic/variables.py +1 -1
  29. mage_ai/data_preparation/models/block/settings/dynamic/constants.py +3 -3
  30. mage_ai/data_preparation/models/block/settings/dynamic/mixins.py +63 -4
  31. mage_ai/data_preparation/models/block/settings/global_data_products/models.py +2 -2
  32. mage_ai/data_preparation/models/constants.py +10 -10
  33. mage_ai/data_preparation/models/global_hooks/constants.py +7 -8
  34. mage_ai/data_preparation/models/global_hooks/models.py +5 -5
  35. mage_ai/data_preparation/models/project/constants.py +2 -2
  36. mage_ai/data_preparation/models/triggers/__init__.py +6 -4
  37. mage_ai/data_preparation/models/variables/constants.py +5 -5
  38. mage_ai/data_preparation/models/widget/constants.py +5 -5
  39. mage_ai/data_preparation/preferences.py +9 -16
  40. mage_ai/data_preparation/repo_manager.py +2 -2
  41. mage_ai/data_preparation/sync/__init__.py +2 -2
  42. mage_ai/data_preparation/templates/data_exporters/streaming/generic_python.py +1 -1
  43. mage_ai/data_preparation/templates/data_loaders/streaming/nats.yaml +3 -0
  44. mage_ai/errors/constants.py +2 -2
  45. mage_ai/io/base.py +28 -15
  46. mage_ai/io/config.py +3 -3
  47. mage_ai/io/export_utils.py +2 -2
  48. mage_ai/io/google_cloud_storage.py +3 -2
  49. mage_ai/io/io_config.py +3 -2
  50. mage_ai/io/postgres.py +2 -1
  51. mage_ai/kernels/magic/constants.py +4 -4
  52. mage_ai/orchestration/constants.py +2 -2
  53. mage_ai/orchestration/db/constants.py +2 -2
  54. mage_ai/orchestration/db/models/oauth.py +5 -5
  55. mage_ai/orchestration/db/models/schedules.py +28 -8
  56. mage_ai/orchestration/db/models/schedules_project_platform.py +10 -8
  57. mage_ai/orchestration/job_manager.py +2 -2
  58. mage_ai/orchestration/monitor/monitor_stats.py +2 -2
  59. mage_ai/orchestration/notification/config.py +2 -2
  60. mage_ai/orchestration/pipeline_scheduler_original.py +4 -12
  61. mage_ai/orchestration/queue/config.py +2 -2
  62. mage_ai/orchestration/queue/process_queue.py +3 -3
  63. mage_ai/presenters/charts/data_sources/constants.py +2 -2
  64. mage_ai/presenters/interactions/constants.py +4 -4
  65. mage_ai/presenters/pages/models/constants.py +4 -4
  66. mage_ai/server/constants.py +1 -1
  67. mage_ai/server/frontend_dist/404.html +2 -2
  68. mage_ai/server/frontend_dist/_next/static/chunks/pages/{_app-663c909dcda4c23a.js → _app-5bdff745074fb350.js} +2 -2
  69. mage_ai/server/frontend_dist/_next/static/chunks/{webpack-43534cc51fce8644.js → webpack-b9a067f3bd0a3a05.js} +1 -1
  70. mage_ai/server/frontend_dist/block-layout.html +2 -2
  71. mage_ai/server/frontend_dist/compute.html +2 -2
  72. mage_ai/server/frontend_dist/files.html +2 -2
  73. mage_ai/server/frontend_dist/global-data-products/[...slug].html +2 -2
  74. mage_ai/server/frontend_dist/global-data-products.html +2 -2
  75. mage_ai/server/frontend_dist/global-hooks/[...slug].html +2 -2
  76. mage_ai/server/frontend_dist/global-hooks.html +2 -2
  77. mage_ai/server/frontend_dist/index.html +2 -2
  78. mage_ai/server/frontend_dist/manage/files.html +2 -2
  79. mage_ai/server/frontend_dist/manage/overview.html +2 -2
  80. mage_ai/server/frontend_dist/manage/pipeline-runs.html +2 -2
  81. mage_ai/server/frontend_dist/manage/settings.html +2 -2
  82. mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
  83. mage_ai/server/frontend_dist/manage/users/new.html +2 -2
  84. mage_ai/server/frontend_dist/manage/users.html +2 -2
  85. mage_ai/server/frontend_dist/manage.html +2 -2
  86. mage_ai/server/frontend_dist/oauth.html +3 -3
  87. mage_ai/server/frontend_dist/overview.html +2 -2
  88. mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
  89. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  90. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
  91. mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +2 -2
  92. mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
  93. mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
  94. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  95. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  96. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
  97. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
  98. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
  99. mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
  100. mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
  101. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  102. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
  103. mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
  104. mage_ai/server/frontend_dist/pipelines.html +2 -2
  105. mage_ai/server/frontend_dist/platform/global-hooks/[...slug].html +2 -2
  106. mage_ai/server/frontend_dist/platform/global-hooks.html +2 -2
  107. mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
  108. mage_ai/server/frontend_dist/settings/platform/preferences.html +2 -2
  109. mage_ai/server/frontend_dist/settings/platform/settings.html +2 -2
  110. mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +2 -2
  111. mage_ai/server/frontend_dist/settings/workspace/permissions.html +2 -2
  112. mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
  113. mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +2 -2
  114. mage_ai/server/frontend_dist/settings/workspace/roles.html +2 -2
  115. mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
  116. mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +2 -2
  117. mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
  118. mage_ai/server/frontend_dist/settings.html +2 -2
  119. mage_ai/server/frontend_dist/sign-in.html +5 -5
  120. mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
  121. mage_ai/server/frontend_dist/templates.html +2 -2
  122. mage_ai/server/frontend_dist/terminal.html +2 -2
  123. mage_ai/server/frontend_dist/test.html +2 -2
  124. mage_ai/server/frontend_dist/triggers.html +2 -2
  125. mage_ai/server/frontend_dist/v2/canvas.html +2 -2
  126. mage_ai/server/frontend_dist/v2.html +2 -2
  127. mage_ai/server/frontend_dist/version-control.html +2 -2
  128. mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
  129. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{_app-bb4a0e0d783622a8.js → _app-90de19bc03f1484b.js} +2 -2
  130. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-9eb1dd2ee735aaac.js → webpack-12ad70eb5c31aa92.js} +1 -1
  131. mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
  132. mage_ai/server/frontend_dist_base_path_template/compute.html +2 -2
  133. mage_ai/server/frontend_dist_base_path_template/files.html +2 -2
  134. mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +2 -2
  135. mage_ai/server/frontend_dist_base_path_template/global-data-products.html +2 -2
  136. mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +2 -2
  137. mage_ai/server/frontend_dist_base_path_template/global-hooks.html +2 -2
  138. mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
  139. mage_ai/server/frontend_dist_base_path_template/manage/files.html +2 -2
  140. mage_ai/server/frontend_dist_base_path_template/manage/overview.html +2 -2
  141. mage_ai/server/frontend_dist_base_path_template/manage/pipeline-runs.html +2 -2
  142. mage_ai/server/frontend_dist_base_path_template/manage/settings.html +2 -2
  143. mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +2 -2
  144. mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +2 -2
  145. mage_ai/server/frontend_dist_base_path_template/manage/users.html +2 -2
  146. mage_ai/server/frontend_dist_base_path_template/manage.html +2 -2
  147. mage_ai/server/frontend_dist_base_path_template/oauth.html +3 -3
  148. mage_ai/server/frontend_dist_base_path_template/overview.html +2 -2
  149. mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +2 -2
  150. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  151. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +2 -2
  152. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +2 -2
  153. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
  154. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +2 -2
  155. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  156. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  157. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +2 -2
  158. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +2 -2
  159. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +2 -2
  160. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +2 -2
  161. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +2 -2
  162. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  163. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +2 -2
  164. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
  165. mage_ai/server/frontend_dist_base_path_template/pipelines.html +2 -2
  166. mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +2 -2
  167. mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +2 -2
  168. mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +2 -2
  169. mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +2 -2
  170. mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +2 -2
  171. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +2 -2
  172. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +2 -2
  173. mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +2 -2
  174. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +2 -2
  175. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +2 -2
  176. mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +2 -2
  177. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +2 -2
  178. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +2 -2
  179. mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
  180. mage_ai/server/frontend_dist_base_path_template/sign-in.html +5 -5
  181. mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +2 -2
  182. mage_ai/server/frontend_dist_base_path_template/templates.html +2 -2
  183. mage_ai/server/frontend_dist_base_path_template/terminal.html +2 -2
  184. mage_ai/server/frontend_dist_base_path_template/test.html +2 -2
  185. mage_ai/server/frontend_dist_base_path_template/triggers.html +2 -2
  186. mage_ai/server/frontend_dist_base_path_template/v2/canvas.html +2 -2
  187. mage_ai/server/frontend_dist_base_path_template/v2.html +2 -2
  188. mage_ai/server/frontend_dist_base_path_template/version-control.html +2 -2
  189. mage_ai/server/kernel_output_parser.py +2 -3
  190. mage_ai/server/kernels.py +2 -3
  191. mage_ai/server/scheduler_manager.py +2 -2
  192. mage_ai/server/server.py +12 -0
  193. mage_ai/server/websockets/constants.py +4 -4
  194. mage_ai/services/compute/aws/constants.py +2 -2
  195. mage_ai/services/compute/aws/steps.py +16 -10
  196. mage_ai/services/compute/constants.py +4 -4
  197. mage_ai/services/compute/models.py +4 -4
  198. mage_ai/services/k8s/config.py +4 -0
  199. mage_ai/services/k8s/job_manager.py +2 -0
  200. mage_ai/services/spark/constants.py +3 -3
  201. mage_ai/services/spark/models/jobs.py +2 -2
  202. mage_ai/services/spark/models/sqls.py +2 -2
  203. mage_ai/services/spark/models/stages.py +4 -4
  204. mage_ai/services/spark/models/threads.py +2 -2
  205. mage_ai/settings/backends.py +3 -2
  206. mage_ai/settings/models/configuration_option.py +3 -3
  207. mage_ai/settings/server.py +5 -0
  208. mage_ai/shared/constants.py +3 -3
  209. mage_ai/shared/custom_logger.py +13 -13
  210. mage_ai/shared/enum.py +11 -0
  211. mage_ai/shared/environments.py +1 -1
  212. mage_ai/shared/logger.py +2 -2
  213. mage_ai/shared/models.py +2 -1
  214. mage_ai/streaming/constants.py +3 -3
  215. mage_ai/streaming/sinks/kafka.py +2 -2
  216. mage_ai/streaming/sinks/postgres.py +6 -0
  217. mage_ai/streaming/sources/amazon_sqs.py +2 -2
  218. mage_ai/streaming/sources/base.py +2 -2
  219. mage_ai/streaming/sources/kafka.py +20 -4
  220. mage_ai/streaming/sources/nats_js.py +10 -3
  221. mage_ai/streaming/sources/shared.py +3 -2
  222. mage_ai/system/constants.py +2 -2
  223. mage_ai/tests/api/policies/permissions/test_base_policy_with_permissions.py +2 -2
  224. mage_ai/tests/data_cleaner/transformer_actions/test_trim_transformer.py +161 -0
  225. mage_ai/tests/data_preparation/models/block/dbt/test_profiles.py +1 -1
  226. mage_ai/tests/data_preparation/models/block/dynamic/test_combos.py +1 -1
  227. mage_ai/tests/data_preparation/models/block/hook/test_hook_block.py +3 -2
  228. mage_ai/tests/data_preparation/models/test_blocks_helper.py +1 -1
  229. mage_ai/tests/data_preparation/models/variables/test_summarizer.py +1 -1
  230. mage_ai/tests/data_preparation/sync/test_git_sync.py +6 -6
  231. mage_ai/tests/orchestration/queue/test_process_queue.py +3 -2
  232. mage_ai/tests/orchestration/test_pipeline_scheduler.py +1 -0
  233. mage_ai/tests/settings/test_platform.py +2 -2
  234. mage_ai/tests/streaming/sinks/test_generic_io.py +25 -21
  235. mage_ai/usage_statistics/constants.py +4 -4
  236. {mage_ai-0.9.73.dist-info → mage_ai-0.9.74.dist-info}/METADATA +172 -171
  237. {mage_ai-0.9.73.dist-info → mage_ai-0.9.74.dist-info}/RECORD +247 -245
  238. {mage_ai-0.9.73.dist-info → mage_ai-0.9.74.dist-info}/WHEEL +1 -1
  239. /mage_ai/server/frontend_dist/_next/static/chunks/pages/{_app-663c909dcda4c23a.js.LICENSE.txt → _app-5bdff745074fb350.js.LICENSE.txt} +0 -0
  240. /mage_ai/server/frontend_dist/_next/static/{kxGpiudO3f9aX6FAiqydf → pLWT6Sqd09xYpufCVIqnz}/_buildManifest.js +0 -0
  241. /mage_ai/server/frontend_dist/_next/static/{kxGpiudO3f9aX6FAiqydf → pLWT6Sqd09xYpufCVIqnz}/_ssgManifest.js +0 -0
  242. /mage_ai/server/frontend_dist_base_path_template/_next/static/{H5pcGxWf1BkhXDRs2BqiI → JQewSAObpbhO0wrdAM6Ng}/_buildManifest.js +0 -0
  243. /mage_ai/server/frontend_dist_base_path_template/_next/static/{H5pcGxWf1BkhXDRs2BqiI → JQewSAObpbhO0wrdAM6Ng}/_ssgManifest.js +0 -0
  244. /mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{_app-bb4a0e0d783622a8.js.LICENSE.txt → _app-90de19bc03f1484b.js.LICENSE.txt} +0 -0
  245. {mage_ai-0.9.73.dist-info → mage_ai-0.9.74.dist-info}/LICENSE +0 -0
  246. {mage_ai-0.9.73.dist-info → mage_ai-0.9.74.dist-info}/entry_points.txt +0 -0
  247. {mage_ai-0.9.73.dist-info → mage_ai-0.9.74.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,6 @@ import logging
3
3
  import os
4
4
  import traceback
5
5
  import uuid
6
- from enum import Enum
7
6
  from typing import Dict, Optional
8
7
  from warnings import warn
9
8
 
@@ -25,6 +24,7 @@ from mage_ai.settings.repo import get_repo_path as get_repo_path_new
25
24
  from mage_ai.settings.repo import get_variables_dir
26
25
  from mage_ai.settings.repo import set_repo_path as set_repo_path_new
27
26
  from mage_ai.settings.utils import base_repo_path
27
+ from mage_ai.shared.enum import StrEnum
28
28
  from mage_ai.shared.environments import is_debug
29
29
  from mage_ai.shared.yaml import load_yaml, trim_strings
30
30
 
@@ -36,7 +36,7 @@ yml.indent(mapping=2, sequence=2, offset=0)
36
36
  logger = logging.getLogger(__name__)
37
37
 
38
38
 
39
- class ProjectType(str, Enum):
39
+ class ProjectType(StrEnum):
40
40
  MAIN = 'main'
41
41
  SUB = 'sub'
42
42
  STANDALONE = 'standalone'
@@ -1,16 +1,16 @@
1
1
  import inspect
2
2
  import os
3
3
  from dataclasses import dataclass
4
- from enum import Enum
5
4
 
6
5
  from mage_ai.shared.config import BaseConfig
6
+ from mage_ai.shared.enum import StrEnum
7
7
 
8
8
  GIT_ACCESS_TOKEN_SECRET_NAME = 'mage_git_access_token'
9
9
  GIT_SSH_PRIVATE_KEY_SECRET_NAME = 'mage_git_ssh_private_key_b64'
10
10
  GIT_SSH_PUBLIC_KEY_SECRET_NAME = 'mage_git_ssh_public_key_b64'
11
11
 
12
12
 
13
- class AuthType(str, Enum):
13
+ class AuthType(StrEnum):
14
14
  SSH = 'ssh'
15
15
  HTTPS = 'https'
16
16
  OAUTH = 'oauth'
@@ -1,5 +1,5 @@
1
1
  from mage_ai.streaming.sinks.base_python import BasePythonSink
2
- from typing import Callable
2
+ from typing import Callable, Dict, List
3
3
 
4
4
  if 'streaming_sink' not in globals():
5
5
  from mage_ai.data_preparation.decorators import streaming_sink
@@ -24,5 +24,8 @@ use_tls: false
24
24
  # Optional: NKEY seed string
25
25
  # nkeys_seed_str: "SUAPAEYJQOQHJ4"
26
26
 
27
+ # Optional: user credentials
28
+ # user_credentials: "path/to/credentials.creds"
29
+
27
30
  # Optional: Consumer name for a durable consumer identifier, will use stream name if not provided
28
31
  consumer_name: "my_consumer"
@@ -1,4 +1,4 @@
1
- from enum import Enum
1
+ from mage_ai.shared.enum import IntEnum
2
2
 
3
3
  """
4
4
  - **400 Bad Request**: The server could not understand the request due to invalid syntax.
@@ -13,7 +13,7 @@ from enum import Enum
13
13
  """
14
14
 
15
15
 
16
- class ErrorCode(int, Enum):
16
+ class ErrorCode(IntEnum):
17
17
  CODE_400 = 400
18
18
  CODE_401 = 401
19
19
  CODE_402 = 402
mage_ai/io/base.py CHANGED
@@ -1,12 +1,13 @@
1
1
  import os
2
2
  from abc import ABC, abstractmethod
3
- from enum import Enum
4
3
  from typing import IO, Any, Callable, Dict, Union
5
4
 
6
5
  import pandas as pd
6
+ import polars as pl
7
7
  from pandas import DataFrame
8
8
 
9
9
  from mage_ai.io.constants import SQL_RESERVED_WORDS
10
+ from mage_ai.shared.enum import StrEnum
10
11
  from mage_ai.shared.logger import VerbosePrintHandler
11
12
  from mage_ai.shared.models import BaseEnum
12
13
  from mage_ai.shared.utils import clean_name
@@ -14,7 +15,7 @@ from mage_ai.shared.utils import clean_name
14
15
  QUERY_ROW_LIMIT = 10_000_000
15
16
 
16
17
 
17
- class DataSource(str, Enum):
18
+ class DataSource(StrEnum):
18
19
  ALGOLIA = 'algolia'
19
20
  API = 'api'
20
21
  BIGQUERY = 'bigquery'
@@ -40,7 +41,7 @@ class DataSource(str, Enum):
40
41
  WEAVIATE = 'weaviate'
41
42
 
42
43
 
43
- class FileFormat(str, Enum):
44
+ class FileFormat(StrEnum):
44
45
  CSV = 'csv'
45
46
  JSON = 'json'
46
47
  PARQUET = 'parquet'
@@ -190,7 +191,7 @@ class BaseFile(BaseIO):
190
191
 
191
192
  def _write(
192
193
  self,
193
- df: DataFrame,
194
+ df,
194
195
  format: Union[FileFormat, str, None],
195
196
  output: Union[IO, os.PathLike, str],
196
197
  **kwargs,
@@ -218,7 +219,7 @@ class BaseFile(BaseIO):
218
219
  raise ValueError('Cannot write HDF5 file to buffer of any type.')
219
220
  name = os.path.splitext(os.path.basename(output))[0]
220
221
  kwargs.setdefault('key', name)
221
- elif format == FileFormat.PARQUET:
222
+ elif format == FileFormat.PARQUET and isinstance(df, DataFrame):
222
223
  if 'coerce_timestamps' not in kwargs:
223
224
  kwargs['coerce_timestamps'] = 'ms'
224
225
  kwargs['allow_truncated_timestamps'] = True
@@ -226,7 +227,7 @@ class BaseFile(BaseIO):
226
227
 
227
228
  def __get_writer(
228
229
  self,
229
- df: DataFrame,
230
+ df,
230
231
  format: Union[FileFormat, str, None],
231
232
  ) -> Callable:
232
233
  """
@@ -239,15 +240,27 @@ class BaseFile(BaseIO):
239
240
  Returns:
240
241
  Callable: File writer method
241
242
  """
242
- if format == FileFormat.CSV:
243
- return df.to_csv
244
- elif format == FileFormat.JSON:
245
- return df.to_json
246
- elif format == FileFormat.HDF5:
247
- return df.to_hdf
248
- elif format == FileFormat.XML:
249
- return df.to_xml
250
- return df.to_parquet
243
+ if isinstance(df, pl.DataFrame): # polars DataFrame
244
+ if format == FileFormat.CSV:
245
+ return df.write_csv
246
+ elif format == FileFormat.JSON:
247
+ return df.write_json
248
+ elif format == FileFormat.HDF5:
249
+ return df.write_hdf5
250
+ elif format == FileFormat.XML:
251
+ return df.write_xml
252
+ return df.write_parquet
253
+
254
+ elif isinstance(df, DataFrame): # pandas DataFrame
255
+ if format == FileFormat.CSV:
256
+ return df.to_csv
257
+ elif format == FileFormat.JSON:
258
+ return df.to_json
259
+ elif format == FileFormat.HDF5:
260
+ return df.to_hdf
261
+ elif format == FileFormat.XML:
262
+ return df.to_xml
263
+ return df.to_parquet
251
264
 
252
265
  def __del__(self):
253
266
  if self.verbose and self.printer.exists_previous_message:
mage_ai/io/config.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import os
2
2
  from abc import ABC, abstractmethod
3
- from enum import Enum
4
3
  from pathlib import Path
5
4
  from typing import Any, Dict, Union
6
5
 
@@ -9,9 +8,10 @@ from jinja2 import Template
9
8
 
10
9
  from mage_ai.data_preparation.shared.utils import get_template_vars
11
10
  from mage_ai.settings.repo import get_repo_path
11
+ from mage_ai.shared.enum import StrEnum
12
12
 
13
13
 
14
- class ConfigKey(str, Enum):
14
+ class ConfigKey(StrEnum):
15
15
  """
16
16
  List of configuration settings for use with data IO clients.
17
17
  """
@@ -333,7 +333,7 @@ class EnvironmentVariableLoader(BaseConfigLoader):
333
333
  return os.getenv(env_var)
334
334
 
335
335
 
336
- class VerboseConfigKey(str, Enum):
336
+ class VerboseConfigKey(StrEnum):
337
337
  """
338
338
  Config key headers for the verbose configuration file format.
339
339
  """
@@ -1,9 +1,9 @@
1
- from enum import Enum
2
1
  from typing import Callable, Dict, List, Mapping
3
2
 
4
3
  from pandas import DataFrame, Series
5
4
  from pandas.api.types import infer_dtype
6
5
 
6
+ from mage_ai.shared.enum import StrEnum
7
7
  from mage_ai.shared.utils import clean_name
8
8
 
9
9
  """
@@ -19,7 +19,7 @@ class BadConversionError(Exception):
19
19
  pass
20
20
 
21
21
 
22
- class PandasTypes(str, Enum):
22
+ class PandasTypes(StrEnum):
23
23
  """
24
24
  Internal datatypes defined by the pandas Public API
25
25
  """
@@ -1,6 +1,7 @@
1
1
  from io import BytesIO
2
2
  from typing import Union
3
3
 
4
+ import polars as pl
4
5
  from google.cloud import storage
5
6
  from google.oauth2 import service_account
6
7
  from pandas import DataFrame
@@ -103,7 +104,7 @@ class GoogleCloudStorage(BaseFile):
103
104
 
104
105
  def export(
105
106
  self,
106
- data: Union[DataFrame, str],
107
+ data: Union[DataFrame, pl.DataFrame, str],
107
108
  bucket_name: str,
108
109
  object_key: str,
109
110
  format: Union[FileFormat, str, None] = None,
@@ -127,7 +128,7 @@ class GoogleCloudStorage(BaseFile):
127
128
  ):
128
129
  bucket = self.client.get_bucket(bucket_name)
129
130
  blob = bucket.blob(object_key)
130
- if isinstance(data, DataFrame):
131
+ if isinstance(data, DataFrame) or isinstance(data, pl.DataFrame):
131
132
  buffer = BytesIO()
132
133
  self._write(data, format, buffer, **kwargs)
133
134
  buffer.seek(0)
mage_ai/io/io_config.py CHANGED
@@ -1,12 +1,13 @@
1
1
  import os
2
- from enum import Enum
3
2
  from pathlib import Path
4
3
  from typing import Any, Mapping, Optional, Union
5
4
 
6
5
  import yaml
7
6
 
7
+ from mage_ai.shared.enum import StrEnum
8
8
 
9
- class IOConfigKeys(str, Enum):
9
+
10
+ class IOConfigKeys(StrEnum):
10
11
  AWS = 'AWS'
11
12
  BIGQUERY = 'BigQuery'
12
13
  CLICKHOUSE = 'ClickHouse'
mage_ai/io/postgres.py CHANGED
@@ -166,13 +166,14 @@ class Postgres(BaseSQL):
166
166
  self,
167
167
  schema_name: str
168
168
  ) -> str:
169
+ clean_schema_name = schema_name.strip('"')
169
170
  return f"""
170
171
  DO $$
171
172
  BEGIN
172
173
  IF NOT EXISTS (
173
174
  SELECT schema_name
174
175
  FROM information_schema.schemata
175
- WHERE schema_name = '{schema_name}'
176
+ WHERE schema_name = '{clean_schema_name}'
176
177
  ) THEN
177
178
  EXECUTE 'CREATE SCHEMA {schema_name}';
178
179
  END IF;
@@ -1,7 +1,7 @@
1
- from enum import Enum
1
+ from mage_ai.shared.enum import StrEnum
2
2
 
3
3
 
4
- class ExecutionStatus(str, Enum):
4
+ class ExecutionStatus(StrEnum):
5
5
  CANCELLED = 'cancelled'
6
6
  ERROR = 'error'
7
7
  FAILURE = 'failure'
@@ -10,12 +10,12 @@ class ExecutionStatus(str, Enum):
10
10
  SUCCESS = 'success'
11
11
 
12
12
 
13
- class EventStreamType(str, Enum):
13
+ class EventStreamType(StrEnum):
14
14
  EXECUTION = 'execution'
15
15
  TASK = 'task'
16
16
 
17
17
 
18
- class ResultType(str, Enum):
18
+ class ResultType(StrEnum):
19
19
  DATA = 'data'
20
20
  STATUS = 'status'
21
21
  STDOUT = 'stdout'
@@ -1,4 +1,4 @@
1
- import enum
1
+ from mage_ai.shared.enum import StrEnum
2
2
 
3
3
  DATABASE_CONNECTION_URL_ENV_VAR = 'MAGE_DATABASE_CONNECTION_URL'
4
4
 
@@ -18,7 +18,7 @@ PG_DB_NAME = 'DB_NAME'
18
18
  PIPELINE_RUN_MAGE_VARIABLES_KEY = '__mage_variables'
19
19
 
20
20
 
21
- class Entity(str, enum.Enum):
21
+ class Entity(StrEnum):
22
22
  # Permissions saved to the DB should not have the "ANY" entity. It should only be used
23
23
  # when evaluating permissions.
24
24
  ANY = 'any'
@@ -1,6 +1,6 @@
1
- from enum import Enum
1
+ from mage_ai.shared.enum import StrEnum
2
2
 
3
3
 
4
- class DatabaseType(str, Enum):
4
+ class DatabaseType(StrEnum):
5
5
  POSTGRESQL = 'postgresql'
6
6
  SQLITE = 'sqlite'
@@ -1,4 +1,3 @@
1
- import enum
2
1
  import re
3
2
  from datetime import datetime
4
3
  from typing import Callable, List, Union
@@ -31,6 +30,7 @@ from mage_ai.orchestration.db import db_connection, safe_db_query
31
30
  from mage_ai.orchestration.db.errors import ValidationError
32
31
  from mage_ai.orchestration.db.models.base import BaseModel
33
32
  from mage_ai.shared.array import find
33
+ from mage_ai.shared.enum import IntEnum, StrEnum
34
34
  from mage_ai.shared.environments import is_test
35
35
  from mage_ai.shared.hash import group_by, merge_dict
36
36
 
@@ -299,7 +299,7 @@ class Role(BaseModel):
299
299
  user = relationship(User, back_populates='created_roles')
300
300
 
301
301
  # Default global roles created by Mage
302
- class DefaultRole(str, enum.Enum):
302
+ class DefaultRole(StrEnum):
303
303
  OWNER = 'Owner'
304
304
  ADMIN = 'Admin'
305
305
  EDITOR = 'Editor'
@@ -561,7 +561,7 @@ class UserRole(BaseModel):
561
561
 
562
562
 
563
563
  class Permission(BaseModel):
564
- class Access(int, enum.Enum):
564
+ class Access(IntEnum):
565
565
  OWNER = PermissionAccess.OWNER.value
566
566
  ADMIN = PermissionAccess.ADMIN.value
567
567
  EDITOR = PermissionAccess.EDITOR.value
@@ -841,11 +841,11 @@ class RolePermission(BaseModel):
841
841
 
842
842
 
843
843
  class Oauth2Application(BaseModel):
844
- class AuthorizationGrantType(str, enum.Enum):
844
+ class AuthorizationGrantType(StrEnum):
845
845
  AUTHORIZATION_CODE = 'authorization-code'
846
846
  CLIENT_CREDENTIALS = 'client-credentials'
847
847
 
848
- class ClientType(str, enum.Enum):
848
+ class ClientType(StrEnum):
849
849
  PRIVATE = 'private'
850
850
  PUBLIC = 'public'
851
851
 
@@ -1,6 +1,5 @@
1
1
  import asyncio
2
2
  import collections
3
- import enum
4
3
  import traceback
5
4
  import uuid
6
5
  from datetime import datetime, timedelta, timezone
@@ -73,6 +72,7 @@ from mage_ai.settings.platform import project_platform_activated
73
72
  from mage_ai.settings.repo import get_repo_path
74
73
  from mage_ai.shared.constants import ENV_PROD
75
74
  from mage_ai.shared.dates import compare
75
+ from mage_ai.shared.enum import StrEnum
76
76
  from mage_ai.shared.hash import ignore_keys, index_by, merge_dict
77
77
  from mage_ai.shared.utils import clean_name
78
78
 
@@ -201,13 +201,32 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
201
201
 
202
202
  @property
203
203
  def pipeline_runs_count(self) -> int:
204
- if project_platform_activated():
205
- return self.pipeline_runs_count_project_platform
204
+ return (
205
+ PipelineRun.select(func.count(PipelineRun.id))
206
+ .filter(
207
+ PipelineRun.pipeline_schedule_id == self.id,
208
+ )
209
+ .scalar()
210
+ )
206
211
 
212
+ @property
213
+ def initial_pipeline_runs(self) -> List:
214
+ return (
215
+ PipelineRun.query
216
+ .filter(
217
+ PipelineRun.pipeline_schedule_id == self.id,
218
+ PipelineRun.status == PipelineRun.PipelineRunStatus.INITIAL,
219
+ )
220
+ .all()
221
+ )
222
+
223
+ @property
224
+ def running_pipeline_run_count(self) -> int:
207
225
  return (
208
226
  PipelineRun.select(func.count(PipelineRun.id))
209
227
  .filter(
210
228
  PipelineRun.pipeline_schedule_id == self.id,
229
+ PipelineRun.status == PipelineRun.PipelineRunStatus.RUNNING,
211
230
  )
212
231
  .scalar()
213
232
  )
@@ -736,7 +755,7 @@ class PipelineSchedule(PipelineScheduleProjectPlatformMixin, BaseModel):
736
755
 
737
756
 
738
757
  class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
739
- class PipelineRunStatus(str, enum.Enum):
758
+ class PipelineRunStatus(StrEnum):
740
759
  INITIAL = 'initial'
741
760
  RUNNING = 'running'
742
761
  COMPLETED = 'completed'
@@ -1538,6 +1557,7 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1538
1557
  variables['execution_date'] = self.execution_date
1539
1558
  variables['execution_partition'] = self.execution_partition
1540
1559
  variables['pipeline_run_id'] = self.id
1560
+ variables['trigger_name'] = self.pipeline_schedule.name
1541
1561
 
1542
1562
  interval_end_datetime = variables.get('interval_end_datetime')
1543
1563
  interval_seconds = variables.get('interval_seconds')
@@ -1632,7 +1652,7 @@ class PipelineRun(PipelineRunProjectPlatformMixin, BaseModel):
1632
1652
 
1633
1653
 
1634
1654
  class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
1635
- class BlockRunStatus(str, enum.Enum):
1655
+ class BlockRunStatus(StrEnum):
1636
1656
  INITIAL = 'initial'
1637
1657
  QUEUED = 'queued'
1638
1658
  RUNNING = 'running'
@@ -1788,7 +1808,7 @@ class BlockRun(BlockRunProjectPlatformMixin, BaseModel):
1788
1808
 
1789
1809
 
1790
1810
  class EventMatcher(BaseModel):
1791
- class EventType(str, enum.Enum):
1811
+ class EventType(StrEnum):
1792
1812
  AWS_EVENT = 'aws_event'
1793
1813
 
1794
1814
  event_type = Column(Enum(EventType), default=EventType.AWS_EVENT)
@@ -1889,7 +1909,7 @@ class EventMatcher(BaseModel):
1889
1909
 
1890
1910
 
1891
1911
  class Backfill(BaseModel):
1892
- class IntervalType(str, enum.Enum):
1912
+ class IntervalType(StrEnum):
1893
1913
  SECOND = 'second'
1894
1914
  MINUTE = 'minute'
1895
1915
  HOUR = 'hour'
@@ -1899,7 +1919,7 @@ class Backfill(BaseModel):
1899
1919
  YEAR = 'year'
1900
1920
  CUSTOM = 'custom'
1901
1921
 
1902
- class Status(str, enum.Enum):
1922
+ class Status(StrEnum):
1903
1923
  INITIAL = 'initial'
1904
1924
  RUNNING = 'running'
1905
1925
  COMPLETED = 'completed'
@@ -27,7 +27,6 @@ from mage_ai.settings.platform.utils import (
27
27
  get_pipeline_from_platform,
28
28
  get_pipeline_from_platform_async,
29
29
  )
30
- from mage_ai.shared.array import find
31
30
  from mage_ai.shared.constants import ENV_PROD
32
31
  from mage_ai.shared.dates import compare
33
32
  from mage_ai.shared.hash import merge_dict
@@ -192,15 +191,18 @@ class PipelineScheduleProjectPlatformMixin:
192
191
  compare(current_execution_date, self.start_time.replace(tzinfo=pytz.UTC)) == -1:
193
192
  return False
194
193
 
194
+ from mage_ai.orchestration.db.models.schedules import PipelineRun
195
+
195
196
  # If there is a pipeline_run with an execution_date the same as the
196
197
  # current_execution_date, then don’t schedule
197
- if not find(
198
- lambda x: compare(
199
- x.execution_date.replace(tzinfo=pytz.UTC),
200
- current_execution_date,
201
- ) == 0,
202
- self.fetch_pipeline_runs([self.id])
203
- ):
198
+ run_exists = PipelineRun.select(
199
+ PipelineRun.query.filter(
200
+ PipelineRun.pipeline_schedule_id == self.id,
201
+ PipelineRun.execution_date == current_execution_date,
202
+ ).exists()
203
+ ).scalar()
204
+
205
+ if not run_exists:
204
206
  if self.landing_time_enabled():
205
207
  if not previous_runtimes or len(previous_runtimes) == 0:
206
208
  return True
@@ -1,10 +1,10 @@
1
- from enum import Enum
2
1
  from typing import Callable, Dict, Union
3
2
 
4
3
  from mage_ai.orchestration.queue.queue_factory import QueueFactory
4
+ from mage_ai.shared.enum import StrEnum
5
5
 
6
6
 
7
- class JobType(str, Enum):
7
+ class JobType(StrEnum):
8
8
  BLOCK_RUN = 'block_run'
9
9
  PIPELINE_RUN = 'pipeline_run'
10
10
  INTEGRATION_STREAM = 'integration_stream'
@@ -1,4 +1,3 @@
1
- import enum
2
1
  from datetime import datetime, timedelta
3
2
  from functools import reduce
4
3
  from typing import Callable, Dict, List, Union
@@ -15,13 +14,14 @@ from mage_ai.orchestration.db.models.schedules import (
15
14
  )
16
15
  from mage_ai.settings.platform.constants import project_platform_activated
17
16
  from mage_ai.settings.repo import get_repo_path
17
+ from mage_ai.shared.enum import StrEnum
18
18
  from mage_ai.shared.hash import group_by, merge_dict
19
19
 
20
20
  NO_PIPELINE_SCHEDULE_ID = 'no_pipeline_schedule_id'
21
21
  NO_PIPELINE_SCHEDULE_NAME = 'no_pipeline_schedule_name'
22
22
 
23
23
 
24
- class MonitorStatsType(str, enum.Enum):
24
+ class MonitorStatsType(StrEnum):
25
25
  PIPELINE_RUN_COUNT = 'pipeline_run_count'
26
26
  PIPELINE_RUN_TIME = 'pipeline_run_time'
27
27
  BLOCK_RUN_COUNT = 'block_run_count'
@@ -1,5 +1,4 @@
1
1
  from dataclasses import dataclass, field
2
- from enum import Enum
3
2
  from typing import List
4
3
 
5
4
  from mage_ai.services.discord.config import DiscordConfig
@@ -10,9 +9,10 @@ from mage_ai.services.slack.config import SlackConfig
10
9
  from mage_ai.services.teams.config import TeamsConfig
11
10
  from mage_ai.services.telegram.config import TelegramConfig
12
11
  from mage_ai.shared.config import BaseConfig
12
+ from mage_ai.shared.enum import StrEnum
13
13
 
14
14
 
15
- class AlertOn(str, Enum):
15
+ class AlertOn(StrEnum):
16
16
  PIPELINE_RUN_FAILURE = 'trigger_failure'
17
17
  PIPELINE_RUN_SUCCESS = 'trigger_success'
18
18
  PIPELINE_RUN_PASSED_SLA = 'trigger_passed_sla'
@@ -1610,21 +1610,13 @@ def schedule_all():
1610
1610
  pipeline=pipeline,
1611
1611
  repo_config=repo_config,
1612
1612
  )
1613
- initial_pipeline_runs = [
1614
- r
1615
- for r in pipeline_schedule.pipeline_runs
1616
- if r.status == PipelineRun.PipelineRunStatus.INITIAL
1617
- ]
1613
+ initial_pipeline_runs = pipeline_schedule.initial_pipeline_runs
1618
1614
 
1619
1615
  if not should_schedule and not initial_pipeline_runs:
1620
1616
  lock.release_lock(lock_key)
1621
1617
  continue
1622
1618
 
1623
- running_pipeline_runs = [
1624
- r
1625
- for r in pipeline_schedule.pipeline_runs
1626
- if r.status == PipelineRun.PipelineRunStatus.RUNNING
1627
- ]
1619
+ running_pipeline_run_count = pipeline_schedule.running_pipeline_run_count
1628
1620
 
1629
1621
  if (
1630
1622
  should_schedule
@@ -1646,7 +1638,7 @@ def schedule_all():
1646
1638
  payload['metrics'] = dict(previous_runtimes=previous_runtimes)
1647
1639
 
1648
1640
  if pipeline_schedule.get_settings().skip_if_previous_running and (
1649
- initial_pipeline_runs or running_pipeline_runs
1641
+ initial_pipeline_runs or running_pipeline_run_count > 0
1650
1642
  ):
1651
1643
  # Cancel the pipeline run if previous pipeline runs haven't completed and
1652
1644
  # skip_if_previous_running is enabled
@@ -1677,7 +1669,7 @@ def schedule_all():
1677
1669
  # Enforce pipeline concurrency limit
1678
1670
  pipeline_run_quota = None
1679
1671
  if trigger_pipeline_run_limit is not None:
1680
- pipeline_run_quota = trigger_pipeline_run_limit - len(running_pipeline_runs)
1672
+ pipeline_run_quota = trigger_pipeline_run_limit - running_pipeline_run_count
1681
1673
 
1682
1674
  if pipeline_run_quota is None:
1683
1675
  pipeline_run_quota = len(initial_pipeline_runs)
@@ -1,10 +1,10 @@
1
1
  from dataclasses import dataclass
2
- from enum import Enum
3
2
 
4
3
  from mage_ai.shared.config import BaseConfig
4
+ from mage_ai.shared.enum import StrEnum
5
5
 
6
6
 
7
- class QueueType(str, Enum):
7
+ class QueueType(StrEnum):
8
8
  CELERY = 'celery'
9
9
  PROCESS = 'process'
10
10
 
@@ -2,7 +2,6 @@ import multiprocessing as mp
2
2
  import os
3
3
  import signal
4
4
  import time
5
- from enum import Enum
6
5
  from multiprocessing import Manager
7
6
  from typing import Callable, Dict
8
7
 
@@ -24,19 +23,20 @@ from mage_ai.settings import (
24
23
  SERVER_LOGGING_FORMAT,
25
24
  SERVER_VERBOSITY,
26
25
  )
26
+ from mage_ai.shared.enum import StrEnum
27
27
  from mage_ai.shared.logger import set_logging_format
28
28
 
29
29
  LIVENESS_TIMEOUT_SECONDS = 300
30
30
 
31
31
 
32
- class JobStatus(str, Enum):
32
+ class JobStatus(StrEnum):
33
33
  QUEUED = 'queued'
34
34
  RUNNING = 'running' # Not used. The value for RUNNING job is process id.
35
35
  COMPLETED = 'completed'
36
36
  CANCELLED = 'cancelled'
37
37
 
38
38
 
39
- class QueueStatus(str, Enum):
39
+ class QueueStatus(StrEnum):
40
40
  ACTIVE = 'active'
41
41
  INACTIVE = 'inactive'
42
42
 
@@ -1,9 +1,9 @@
1
- from enum import Enum
1
+ from mage_ai.shared.enum import StrEnum
2
2
 
3
3
  DEFAULT_LIMIT = 10000
4
4
 
5
5
 
6
- class ChartDataSourceType(str, Enum):
6
+ class ChartDataSourceType(StrEnum):
7
7
  BLOCK = 'block'
8
8
  BLOCK_RUNS = 'block_runs'
9
9
  CHART_CODE = 'chart_code'