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
@@ -58,6 +58,7 @@ class K8sExecutorConfig(BaseConfig):
58
58
  service_account_name = DEFAULT_SERVICE_ACCOUNT_NAME
59
59
  affinity = None
60
60
  node_selector = None
61
+ scheduler_name = None
61
62
  tolerations = []
62
63
  volumes = []
63
64
  image_pull_secrets = {}
@@ -71,6 +72,8 @@ class K8sExecutorConfig(BaseConfig):
71
72
 
72
73
  if executor_config.pod.get('node_selector'):
73
74
  node_selector = executor_config.pod['node_selector']
75
+ if executor_config.pod.get('scheduler_name'):
76
+ scheduler_name = executor_config.pod['scheduler_name']
74
77
 
75
78
  if executor_config.pod.get('tolerations'):
76
79
  tolerations += [V1Toleration(**e) for e in executor_config.pod['tolerations']]
@@ -123,6 +126,7 @@ class K8sExecutorConfig(BaseConfig):
123
126
  containers=[container],
124
127
  image_pull_secrets=image_pull_secrets,
125
128
  node_selector=node_selector,
129
+ scheduler_name=scheduler_name,
126
130
  restart_policy='Never',
127
131
  service_account_name=service_account_name,
128
132
  tolerations=tolerations,
@@ -172,6 +172,8 @@ class JobManager():
172
172
  pod_spec.tolerations = mage_server_pod_spec.tolerations
173
173
  if not pod_spec.node_selector:
174
174
  pod_spec.node_selector = mage_server_pod_spec.node_selector
175
+ if not pod_spec.scheduler_name:
176
+ pod_spec.scheduler_name = mage_server_pod_spec.scheduler_name
175
177
  pod_spec.image_pull_secrets = pod_spec.image_pull_secrets if pod_spec.image_pull_secrets \
176
178
  else mage_server_pod_spec.image_pull_secrets
177
179
  return pod_spec
@@ -1,12 +1,12 @@
1
- from enum import Enum
1
+ from mage_ai.shared.enum import StrEnum
2
2
 
3
3
  SPARK_DIRECTORY_NAME = '.spark'
4
4
 
5
5
 
6
- class ComputeServiceUUID(str, Enum):
6
+ class ComputeServiceUUID(StrEnum):
7
7
  AWS_EMR = 'AWS_EMR'
8
8
  STANDALONE_CLUSTER = 'STANDALONE_CLUSTER'
9
9
 
10
10
 
11
- class SparkMaster(str, Enum):
11
+ class SparkMaster(StrEnum):
12
12
  LOCAL = 'local'
@@ -1,12 +1,12 @@
1
1
  from dataclasses import dataclass, field
2
- from enum import Enum
3
2
  from typing import Dict, List
4
3
 
5
4
  from mage_ai.services.spark.models.applications import Application
6
5
  from mage_ai.services.spark.models.base import BaseSparkModel
6
+ from mage_ai.shared.enum import StrEnum
7
7
 
8
8
 
9
- class JobStatus(str, Enum):
9
+ class JobStatus(StrEnum):
10
10
  FAILED = 'FAILED'
11
11
  RUNNING = 'RUNNING'
12
12
  SUCCEEDED = 'SUCCEEDED'
@@ -1,14 +1,14 @@
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.spark.models.applications import Application
6
5
  from mage_ai.services.spark.models.base import BaseSparkModel
7
6
  from mage_ai.services.spark.models.jobs import Job
8
7
  from mage_ai.services.spark.models.stages import StageAttempt
8
+ from mage_ai.shared.enum import StrEnum
9
9
 
10
10
 
11
- class SqlStatus(str, Enum):
11
+ class SqlStatus(StrEnum):
12
12
  COMPLETED = 'COMPLETED'
13
13
 
14
14
 
@@ -1,25 +1,25 @@
1
1
  from dataclasses import dataclass, field
2
- from enum import Enum
3
2
  from typing import Dict, List
4
3
 
5
4
  from mage_ai.services.spark.models.applications import Application
6
5
  from mage_ai.services.spark.models.base import BaseSparkModel
7
6
  from mage_ai.services.spark.models.metrics import Metrics
7
+ from mage_ai.shared.enum import StrEnum
8
8
 
9
9
 
10
- class Locality(str, Enum):
10
+ class Locality(StrEnum):
11
11
  NODE_LOCAL = 'NODE_LOCAL'
12
12
  PROCESS_LOCAL = 'PROCESS_LOCAL'
13
13
  RACK_LOCAL = 'RACK_LOCAL'
14
14
 
15
15
 
16
- class StageStatus(str, Enum):
16
+ class StageStatus(StrEnum):
17
17
  COMPLETE = 'COMPLETE'
18
18
  PENDING = 'PENDING'
19
19
  SKIPPED = 'SKIPPED'
20
20
 
21
21
 
22
- class TaskStatus(str, Enum):
22
+ class TaskStatus(StrEnum):
23
23
  SUCCESS = 'SUCCESS'
24
24
 
25
25
 
@@ -1,11 +1,11 @@
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.spark.models.base import BaseSparkModel
5
+ from mage_ai.shared.enum import StrEnum
6
6
 
7
7
 
8
- class ThreadState(str, Enum):
8
+ class ThreadState(StrEnum):
9
9
  RUNNABLE = 'RUNNABLE'
10
10
  TIMED_WAITING = 'TIMED_WAITING'
11
11
  WAITING = 'WAITING'
@@ -1,13 +1,14 @@
1
1
  import base64
2
2
  import logging
3
3
  import os
4
- from enum import Enum
5
4
  from typing import Optional
6
5
 
6
+ from mage_ai.shared.enum import StrEnum
7
+
7
8
  logger = logging.getLogger(__name__)
8
9
 
9
10
 
10
- class BackendType(str, Enum):
11
+ class BackendType(StrEnum):
11
12
  """
12
13
  Enum for the different types of settings backends.
13
14
  """
@@ -1,7 +1,6 @@
1
1
  import asyncio
2
2
  import os
3
3
  from dataclasses import dataclass
4
- from enum import Enum
5
4
  from pathlib import Path
6
5
  from typing import Dict, Union
7
6
 
@@ -15,6 +14,7 @@ from mage_ai.data_preparation.models.pipeline import Pipeline
15
14
  from mage_ai.data_preparation.shared.utils import get_template_vars
16
15
  from mage_ai.settings.platform 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.files import get_full_file_paths_containing_multi_items
19
19
  from mage_ai.shared.hash import merge_dict
20
20
  from mage_ai.shared.models import BaseDataClass
@@ -37,11 +37,11 @@ async def read_file(full_path: str) -> str:
37
37
  return config
38
38
 
39
39
 
40
- class ConfigurationType(str, Enum):
40
+ class ConfigurationType(StrEnum):
41
41
  DBT = 'dbt'
42
42
 
43
43
 
44
- class OptionType(str, Enum):
44
+ class OptionType(StrEnum):
45
45
  PROFILES = 'profiles'
46
46
  PROJECTS = 'projects'
47
47
  TARGETS = 'targets'
@@ -161,6 +161,11 @@ NEW_RELIC_CONFIG_PATH = os.getenv('NEW_RELIC_CONFIG_PATH', '')
161
161
  # If enabled, the /metrics route will expose Tornado server metrics
162
162
  ENABLE_PROMETHEUS = get_bool_value(os.getenv('ENABLE_PROMETHEUS', 'False'))
163
163
 
164
+ # API switch configuration
165
+ # If disabled, those AI APIs will not be used in backend.
166
+ ENABLE_OPEN_AI = get_bool_value(os.getenv('ENABLE_OPEN_AI') or 'True')
167
+ ENABLE_HUGGING_FACE = get_bool_value(os.getenv('ENABLE_HUGGING_FACE') or 'True')
168
+
164
169
  # OpenTelemetry Configuration
165
170
  OTEL_EXPORTER_OTLP_ENDPOINT = os.getenv('OTEL_EXPORTER_OTLP_ENDPOINT', None)
166
171
  OTEL_EXPORTER_OTLP_HTTP_ENDPOINT = os.getenv('OTEL_EXPORTER_HTTP_OTLP_ENDPOINT', None)
@@ -1,9 +1,9 @@
1
- from enum import Enum
1
+ from mage_ai.shared.enum import StrEnum
2
2
 
3
3
  ENV_DEV = 'dev'
4
4
  ENV_PROD = 'prod'
5
5
  ENV_STAGING = 'staging'
6
- ENV_TEST = 'test'
6
+ ENV_TEST = 'test_mage'
7
7
 
8
8
  VALID_ENVS = frozenset([
9
9
  ENV_DEV,
@@ -20,7 +20,7 @@ GCS_PREFIX = 'gs://'
20
20
  ENV_VAR_INSTANCE_TYPE = 'INSTANCE_TYPE'
21
21
 
22
22
 
23
- class InstanceType(str, Enum):
23
+ class InstanceType(StrEnum):
24
24
  SERVER_AND_SCHEDULER = 'server_and_scheduler'
25
25
  SCHEDULER = 'scheduler'
26
26
  WEB_SERVER = 'web_server'
@@ -1,15 +1,15 @@
1
1
  import inspect
2
2
  import logging
3
- from enum import Enum
4
3
 
5
4
  import simplejson
6
5
 
7
6
  from mage_ai.data_preparation.models.constants import BlockType
7
+ from mage_ai.shared.enum import StrEnum
8
8
  from mage_ai.shared.environments import is_deus_ex_machina
9
9
  from mage_ai.shared.parsers import encode_complex
10
10
 
11
11
 
12
- class Color(str, Enum):
12
+ class Color(StrEnum):
13
13
  BLUE = "\x1b[1;34m"
14
14
  BOLD_RED = "\x1b[31;1m"
15
15
  GREEN = "\x1b[1;32m"
@@ -64,19 +64,19 @@ class ColorPrinter:
64
64
  self.label = None
65
65
 
66
66
  def debug(self, *args, **kwargs):
67
- self.print(color=Color.PURPLE, *args, **kwargs)
67
+ self.print(*args, color=Color.PURPLE, **kwargs)
68
68
 
69
69
  def info(self, *args, **kwargs):
70
- self.print(color=Color.BLUE, *args, **kwargs)
70
+ self.print(*args, color=Color.BLUE, **kwargs)
71
71
 
72
72
  def warning(self, *args, **kwargs):
73
- self.print(color=Color.GREEN, *args, **kwargs)
73
+ self.print(*args, color=Color.GREEN, **kwargs)
74
74
 
75
75
  def error(self, *args, **kwargs):
76
- self.print(color=Color.RED, *args, **kwargs)
76
+ self.print(*args, color=Color.RED, **kwargs)
77
77
 
78
78
  def critical(self, *args, **kwargs):
79
- self.print(color=Color.BOLD_RED, *args, **kwargs)
79
+ self.print(*args, color=Color.BOLD_RED, **kwargs)
80
80
 
81
81
  def print(self, *args, **kwargs):
82
82
  if not is_deus_ex_machina():
@@ -183,39 +183,39 @@ class CustomFormatter(logging.Formatter):
183
183
  def debug(self, p: int = 0, *args, **kwargs):
184
184
  if is_deus_ex_machina():
185
185
  if p:
186
- self.print(color=Color.PURPLE, *args, **kwargs)
186
+ self.print(*args, color=Color.PURPLE, **kwargs)
187
187
  else:
188
188
  super().debug(*args, **kwargs)
189
189
 
190
190
  def info(self, p: int = 0, *args, **kwargs):
191
191
  if is_deus_ex_machina():
192
192
  if p:
193
- self.print(color=Color.BLUE, *args, **kwargs)
193
+ self.print(*args, color=Color.BLUE, **kwargs)
194
194
  else:
195
195
  super().info(*args, **kwargs)
196
196
 
197
197
  def warning(self, p: int = 0, *args, **kwargs):
198
198
  if is_deus_ex_machina():
199
199
  if p:
200
- self.print(color=Color.YELLOW, *args, **kwargs)
200
+ self.print(*args, color=Color.YELLOW, **kwargs)
201
201
  else:
202
202
  super().warning(*args, **kwargs)
203
203
 
204
204
  def error(self, p: int = 0, *args, **kwargs):
205
205
  if is_deus_ex_machina():
206
206
  if p:
207
- self.print(color=Color.RED, *args, **kwargs)
207
+ self.print(*args, color=Color.RED, **kwargs)
208
208
  else:
209
209
  super().error(*args, **kwargs)
210
210
 
211
211
  def critical(self, p: int = 0, *args, **kwargs):
212
212
  if is_deus_ex_machina():
213
213
  if p:
214
- self.print(color=Color.BOLD_RED, *args, **kwargs)
214
+ self.print(*args, color=Color.BOLD_RED, **kwargs)
215
215
  else:
216
216
  super().critical(*args, **kwargs)
217
217
 
218
- def print(self, color: Color, *args, **kwargs):
218
+ def print(self, *args, color: Color, **kwargs):
219
219
  more = None
220
220
  if kwargs:
221
221
  more = simplejson.dumps(
mage_ai/shared/enum.py ADDED
@@ -0,0 +1,11 @@
1
+ try:
2
+ # breaking change introduced in python 3.11
3
+ from enum import Enum, IntEnum, StrEnum
4
+ except ImportError: # pragma: no cover
5
+ from enum import Enum # pragma: no cover
6
+
7
+ class IntEnum(int, Enum): # pragma: no cover
8
+ pass # pragma: no cover
9
+
10
+ class StrEnum(str, Enum): # pragma: no cover
11
+ pass # pragma: no cover
@@ -17,7 +17,7 @@ def is_dev():
17
17
 
18
18
 
19
19
  def is_test():
20
- return os.getenv('ENV', None) == 'test' or any('unittest' in v for v in sys.argv)
20
+ return os.getenv('ENV', None) == 'test_mage' or any('unittest' in v for v in sys.argv)
21
21
 
22
22
 
23
23
  def is_production():
mage_ai/shared/logger.py CHANGED
@@ -2,10 +2,10 @@ import json
2
2
  import logging
3
3
  import time
4
4
  from contextlib import contextmanager, redirect_stdout
5
- from enum import Enum
6
5
  from typing import Callable, List
7
6
 
8
7
  from mage_ai.settings import SERVER_LOGGING_TEMPLATE
8
+ from mage_ai.shared.enum import StrEnum
9
9
  from mage_ai.shared.hash import merge_dict
10
10
 
11
11
  logger = logging.getLogger(__name__)
@@ -107,7 +107,7 @@ def set_logging_format(logging_format: str = None, level: str = None) -> None:
107
107
  root_logger.exception('Invalid logging level %s', level)
108
108
 
109
109
 
110
- class LoggingLevel(str, Enum):
110
+ class LoggingLevel(StrEnum):
111
111
  DEBUG = 'DEBUG'
112
112
  INFO = 'INFO'
113
113
  WARNING = 'WARNING'
mage_ai/shared/models.py CHANGED
@@ -7,12 +7,13 @@ from typing import Any, Dict, List, Optional, Type, Union
7
7
 
8
8
  import inflection
9
9
 
10
+ from mage_ai.shared.enum import StrEnum
10
11
  from mage_ai.shared.environments import is_debug
11
12
  from mage_ai.shared.hash import merge_dict
12
13
  from mage_ai.shared.parsers import encode_complex
13
14
 
14
15
 
15
- class BaseEnum(str, Enum):
16
+ class BaseEnum(StrEnum):
16
17
  @classmethod
17
18
  def has_value(cls, value: Union[Any, str]) -> bool:
18
19
  if isinstance(value, cls):
@@ -1,10 +1,10 @@
1
- from enum import Enum
1
+ from mage_ai.shared.enum import StrEnum
2
2
 
3
3
  DEFAULT_BATCH_SIZE = 100
4
4
  DEFAULT_TIMEOUT_MS = 500
5
5
 
6
6
 
7
- class SourceType(str, Enum):
7
+ class SourceType(StrEnum):
8
8
  ACTIVEMQ = 'activemq'
9
9
  AMAZON_SQS = 'amazon_sqs'
10
10
  AZURE_EVENT_HUB = 'azure_event_hub'
@@ -17,7 +17,7 @@ class SourceType(str, Enum):
17
17
  MONGODB = 'mongodb'
18
18
 
19
19
 
20
- class SinkType(str, Enum):
20
+ class SinkType(StrEnum):
21
21
  ACTIVEMQ = 'activemq'
22
22
  AMAZON_S3 = 'amazon_s3'
23
23
  AZURE_DATA_LAKE = 'azure_data_lake'
@@ -1,17 +1,17 @@
1
1
  import json
2
2
  import time
3
3
  from dataclasses import dataclass
4
- from enum import Enum
5
4
  from typing import Dict, List
6
5
 
7
6
  from kafka import KafkaProducer
8
7
 
9
8
  from mage_ai.shared.config import BaseConfig
9
+ from mage_ai.shared.enum import StrEnum
10
10
  from mage_ai.streaming.constants import DEFAULT_BATCH_SIZE, DEFAULT_TIMEOUT_MS
11
11
  from mage_ai.streaming.sinks.base import BaseSink
12
12
 
13
13
 
14
- class SecurityProtocol(str, Enum):
14
+ class SecurityProtocol(StrEnum):
15
15
  SASL_SSL = 'SASL_SSL'
16
16
  SSL = 'SSL'
17
17
 
@@ -23,6 +23,9 @@ class PostgresConfig(BaseConfig):
23
23
  port: int = 5432
24
24
  unique_conflict_method: str = UNIQUE_CONFLICT_METHOD_IGNORE
25
25
  unique_constraints: List = field(default_factory=list)
26
+ allow_reserved_words: bool = False
27
+ auto_clean_name: bool = True
28
+ case_sensitive: bool = False
26
29
 
27
30
 
28
31
  class PostgresSink(BaseSink):
@@ -57,6 +60,9 @@ class PostgresSink(BaseSink):
57
60
  if_exists=ExportWritePolicy.APPEND,
58
61
  unique_conflict_method=self.config.unique_conflict_method,
59
62
  unique_constraints=self.config.unique_constraints,
63
+ allow_reserved_words=self.config.allow_reserved_words,
64
+ auto_clean_name=self.config.auto_clean_name,
65
+ case_sensitive=self.config.case_sensitive,
60
66
  )
61
67
 
62
68
  def destroy(self):
@@ -2,12 +2,12 @@ import json
2
2
  import threading
3
3
  import time
4
4
  from dataclasses import dataclass
5
- from enum import Enum
6
5
  from typing import Callable, Dict
7
6
 
8
7
  import boto3
9
8
 
10
9
  from mage_ai.shared.config import BaseConfig
10
+ from mage_ai.shared.enum import StrEnum
11
11
  from mage_ai.streaming.constants import DEFAULT_BATCH_SIZE
12
12
  from mage_ai.streaming.sources.base import BaseSource
13
13
  from mage_ai.streaming.sources.shared import SerDeConfig, SerializationMethod
@@ -15,7 +15,7 @@ from mage_ai.streaming.sources.shared import SerDeConfig, SerializationMethod
15
15
  DEFAULT_WAIT_TIME_SECONDS = 1
16
16
 
17
17
 
18
- class MessageDeletionMethod(str, Enum):
18
+ class MessageDeletionMethod(StrEnum):
19
19
  AFTER_RECEIVED = 'AFTER_RECEIVED'
20
20
  MANUAL = 'MANUAL'
21
21
 
@@ -1,12 +1,12 @@
1
1
  import json
2
2
  from abc import ABC, abstractmethod
3
- from enum import Enum
4
3
  from typing import Callable, Dict
5
4
 
5
+ from mage_ai.shared.enum import StrEnum
6
6
  from mage_ai.shared.environments import is_test
7
7
 
8
8
 
9
- class SourceConsumeMethod(str, Enum):
9
+ class SourceConsumeMethod(StrEnum):
10
10
  BATCH_READ = 'BATCH_READ'
11
11
  READ = 'READ'
12
12
  READ_ASYNC = 'READ_ASYNC'
@@ -1,19 +1,25 @@
1
1
  import importlib
2
2
  import json
3
+ import sys
4
+
5
+ if sys.version_info >= (3, 12, 0):
6
+ import six
7
+ sys.modules['kafka.vendor.six.moves'] = six.moves
8
+
3
9
  import time
4
10
  from dataclasses import dataclass, field
5
- from enum import Enum
6
11
  from typing import Callable, Dict, List
7
12
 
8
13
  from kafka import KafkaConsumer, TopicPartition
9
14
 
10
15
  from mage_ai.shared.config import BaseConfig
16
+ from mage_ai.shared.enum import StrEnum
11
17
  from mage_ai.streaming.constants import DEFAULT_BATCH_SIZE, DEFAULT_TIMEOUT_MS
12
18
  from mage_ai.streaming.sources.base import BaseSource
13
19
  from mage_ai.streaming.sources.shared import SerDeConfig, SerializationMethod
14
20
 
15
21
 
16
- class SecurityProtocol(str, Enum):
22
+ class SecurityProtocol(StrEnum):
17
23
  SASL_PLAINTEXT = 'SASL_PLAINTEXT'
18
24
  SASL_SSL = 'SASL_SSL'
19
25
  SSL = 'SSL'
@@ -102,8 +108,18 @@ class KafkaSource(BaseSource):
102
108
  consumer_kwargs['sasl_plain_username'] = self.config.sasl_config.username
103
109
  consumer_kwargs['sasl_plain_password'] = self.config.sasl_config.password
104
110
 
105
- if self.config.ssl_config is not None and self.config.ssl_config.cafile:
106
- consumer_kwargs['ssl_cafile'] = self.config.ssl_config.cafile
111
+ if self.config.ssl_config:
112
+ consumer_kwargs[
113
+ 'ssl_check_hostname'] = self.config.ssl_config.check_hostname
114
+ if self.config.ssl_config.cafile:
115
+ consumer_kwargs['ssl_cafile'] = self.config.ssl_config.cafile
116
+ if self.config.ssl_config.certfile:
117
+ consumer_kwargs['ssl_certfile'] = self.config.ssl_config.certfile
118
+ if self.config.ssl_config.keyfile:
119
+ consumer_kwargs['ssl_keyfile'] = self.config.ssl_config.keyfile
120
+ if self.config.ssl_config.password:
121
+ consumer_kwargs['ssl_password'] = self.config.ssl_config.password
122
+
107
123
  elif self.config.security_protocol == SecurityProtocol.SASL_PLAINTEXT:
108
124
  consumer_kwargs['security_protocol'] = SecurityProtocol.SASL_PLAINTEXT
109
125
  consumer_kwargs['sasl_mechanism'] = self.config.sasl_config.mechanism
@@ -1,18 +1,20 @@
1
1
  import asyncio
2
- import enum
3
2
  import json
4
3
  import ssl
5
4
  import threading
6
5
  from dataclasses import dataclass
7
- from typing import Callable, Dict, Optional
6
+ from typing import Callable, Dict, Optional, Tuple, Union
8
7
 
9
8
  import nats
10
9
  from nats.errors import NoServersError, TimeoutError
11
10
 
12
11
  from mage_ai.shared.config import BaseConfig
12
+ from mage_ai.shared.enum import StrEnum
13
13
  from mage_ai.streaming.constants import DEFAULT_BATCH_SIZE, DEFAULT_TIMEOUT_MS
14
14
  from mage_ai.streaming.sources.base import BaseSource, SourceConsumeMethod
15
15
 
16
+ Credentials = Union[str, Tuple[str, str]]
17
+
16
18
 
17
19
  @dataclass
18
20
  class SSLConfig:
@@ -22,7 +24,7 @@ class SSLConfig:
22
24
  check_hostname: bool = False
23
25
 
24
26
 
25
- class ConsumerType(str, enum.Enum):
27
+ class ConsumerType(StrEnum):
26
28
  PULL = "PULL"
27
29
  PUSH = "PUSH"
28
30
 
@@ -33,6 +35,7 @@ class NATSConfig(BaseConfig):
33
35
  stream_name: str
34
36
  subject: str = None
35
37
  nkeys_seed_str: Optional[str] = None
38
+ user_credentials: Optional[Credentials] = None
36
39
  use_tls: bool = False
37
40
  ssl_config: Optional[SSLConfig] = None
38
41
  consumer_name: Optional[str] = None
@@ -99,6 +102,10 @@ class NATSSource(BaseSource):
99
102
  if self.config.nkeys_seed_str:
100
103
  connect_opts["nkeys_seed_str"] = self.config.nkeys_seed_str
101
104
 
105
+ # Use credentials if provided
106
+ if self.config.user_credentials:
107
+ connect_opts["user_credentials"] = self.config.user_credentials
108
+
102
109
  # Establish connection with the configured options
103
110
  self.nc = await nats.connect(**connect_opts)
104
111
  self.js = self.nc.jetstream()
@@ -1,8 +1,9 @@
1
1
  from dataclasses import dataclass
2
- from enum import Enum
3
2
 
3
+ from mage_ai.shared.enum import StrEnum
4
4
 
5
- class SerializationMethod(str, Enum):
5
+
6
+ class SerializationMethod(StrEnum):
6
7
  AVRO = 'AVRO'
7
8
  JSON = 'JSON'
8
9
  PROTOBUF = 'PROTOBUF'
@@ -1,7 +1,7 @@
1
- from enum import Enum
1
+ from mage_ai.shared.enum import StrEnum
2
2
 
3
3
 
4
- class LogType(str, Enum):
4
+ class LogType(StrEnum):
5
5
  END = 'END'
6
6
  GENERIC = 'GENERIC'
7
7
  MEMORY = 'MEMORY'
@@ -1,5 +1,4 @@
1
1
  import secrets
2
- from enum import Enum
3
2
  from typing import Any, Callable, Dict, List, Union
4
3
  from unittest.mock import patch
5
4
 
@@ -19,13 +18,14 @@ from mage_ai.authentication.permissions.constants import (
19
18
  )
20
19
  from mage_ai.orchestration.db.models.oauth import Permission, Role, User, UserRole
21
20
  from mage_ai.shared.array import find
21
+ from mage_ai.shared.enum import StrEnum
22
22
  from mage_ai.shared.hash import index_by, merge_dict
23
23
  from mage_ai.tests.api.mixins import BootstrapMixin
24
24
  from mage_ai.tests.api.operations.test_base import BaseApiTestCase
25
25
  from mage_ai.tests.api.policies.permissions.mixins import PermissionsMixin
26
26
 
27
27
 
28
- class TestSuite(str, Enum):
28
+ class TestSuite(StrEnum):
29
29
  AUTHORIZED = 'AUTHORIZED'
30
30
  DISABLED = 'DISABLED'
31
31
  INVERSE = 'INVERSE'