mage-ai 0.9.12__py3-none-any.whl → 0.9.14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mage-ai might be problematic. Click here for more details.

Files changed (325) hide show
  1. mage_ai/ai/generator.py +1 -1
  2. mage_ai/ai/generator_cmds.py +1 -1
  3. mage_ai/ai/llm_pipeline_wizard.py +31 -17
  4. mage_ai/api/policies/BlockPolicy.py +1 -0
  5. mage_ai/api/policies/PipelineRunPolicy.py +1 -0
  6. mage_ai/api/policies/PipelineSchedulePolicy.py +12 -0
  7. mage_ai/api/policies/TagPolicy.py +18 -0
  8. mage_ai/api/presenters/BlockRunPresenter.py +4 -1
  9. mage_ai/api/presenters/PipelineRunPresenter.py +2 -0
  10. mage_ai/api/presenters/PipelineSchedulePresenter.py +9 -2
  11. mage_ai/api/presenters/TagPresenter.py +3 -0
  12. mage_ai/api/resources/BackfillResource.py +6 -3
  13. mage_ai/api/resources/BlockResource.py +2 -0
  14. mage_ai/api/resources/BlockRunResource.py +18 -12
  15. mage_ai/api/resources/DatabaseResource.py +23 -0
  16. mage_ai/api/resources/GitBranchResource.py +8 -1
  17. mage_ai/api/resources/GlobalDataProductResource.py +5 -2
  18. mage_ai/api/resources/PipelineResource.py +30 -14
  19. mage_ai/api/resources/PipelineScheduleResource.py +157 -1
  20. mage_ai/api/resources/SearchResultResource.py +1 -0
  21. mage_ai/api/resources/TagResource.py +16 -3
  22. mage_ai/data_integrations/sources/constants.py +1 -0
  23. mage_ai/data_preparation/git/__init__.py +18 -0
  24. mage_ai/data_preparation/models/block/__init__.py +34 -11
  25. mage_ai/data_preparation/models/block/dbt/utils/__init__.py +37 -10
  26. mage_ai/data_preparation/models/block/integration/__init__.py +1 -1
  27. mage_ai/data_preparation/models/block/sql/__init__.py +44 -2
  28. mage_ai/data_preparation/models/custom_templates/utils.py +14 -4
  29. mage_ai/data_preparation/models/global_data_product/__init__.py +8 -0
  30. mage_ai/data_preparation/models/pipeline.py +4 -0
  31. mage_ai/data_preparation/models/variable.py +5 -2
  32. mage_ai/data_preparation/repo_manager.py +28 -16
  33. mage_ai/io/clickhouse.py +9 -6
  34. mage_ai/io/redshift.py +9 -10
  35. mage_ai/io/utils.py +3 -1
  36. mage_ai/orchestration/db/migrations/README.md +39 -2
  37. mage_ai/orchestration/db/migrations/env.py +1 -0
  38. mage_ai/orchestration/db/migrations/versions/386bcfebd48d_create_tag_and_tagassociation_tables.py +59 -0
  39. mage_ai/orchestration/db/models/schedules.py +29 -2
  40. mage_ai/orchestration/db/models/tags.py +57 -0
  41. mage_ai/orchestration/pipeline_scheduler.py +7 -7
  42. mage_ai/orchestration/triggers/global_data_product.py +41 -40
  43. mage_ai/orchestration/triggers/utils.py +11 -1
  44. mage_ai/server/constants.py +1 -1
  45. mage_ai/server/frontend_dist/404.html +2 -2
  46. mage_ai/server/frontend_dist/404.html.html +2 -2
  47. mage_ai/server/frontend_dist/_next/static/CNjkRIWPaAu1yJUmIaX_q/_buildManifest.js +1 -0
  48. mage_ai/server/frontend_dist/_next/static/chunks/1005-a2f0e3ee378ef02b.js +1 -0
  49. mage_ai/server/frontend_dist/_next/static/chunks/1424-fca78f21a81a7183.js +1 -0
  50. mage_ai/server/frontend_dist/_next/static/chunks/1484-87d4d4a698ac63dc.js +1 -0
  51. mage_ai/server/frontend_dist/_next/static/chunks/2485-39885e5335888821.js +1 -0
  52. mage_ai/server/frontend_dist/_next/static/chunks/2786-f71862671f66d948.js +1 -0
  53. mage_ai/server/frontend_dist/_next/static/chunks/3391-6f0a0a5c254cd7f2.js +1 -0
  54. mage_ai/server/frontend_dist/_next/static/chunks/3881-131cf690e54c23a3.js +1 -0
  55. mage_ai/server/frontend_dist/_next/static/chunks/437-331193bd9b2fe777.js +1 -0
  56. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/4822-045cc7cdd7c95163.js → frontend_dist/_next/static/chunks/4822-ee62acb1927c8150.js} +1 -1
  57. mage_ai/server/frontend_dist/_next/static/chunks/547-bd961ea93f3eb98b.js +1 -0
  58. mage_ai/server/frontend_dist/_next/static/chunks/6299-fcb702d0f3d3291b.js +1 -0
  59. mage_ai/server/frontend_dist/_next/static/chunks/6422-0cdd6e596dcd43b6.js +1 -0
  60. mage_ai/server/frontend_dist/_next/static/chunks/{6786-77c7e36678abb2c6.js → 6786-55e1bca3c897d5ee.js} +1 -1
  61. mage_ai/server/frontend_dist/_next/static/chunks/7496-7e4dd11e3f3b8e79.js +1 -0
  62. mage_ai/server/frontend_dist/_next/static/chunks/7722-76c724a66240561b.js +1 -0
  63. mage_ai/server/frontend_dist/_next/static/chunks/7815-8b68b0eb665fcd2d.js +1 -0
  64. mage_ai/server/frontend_dist/_next/static/chunks/8190-d38ed1133030797d.js +1 -0
  65. mage_ai/server/frontend_dist/_next/static/chunks/8952-9d6fa18fa9378989.js +1 -0
  66. mage_ai/server/frontend_dist/_next/static/chunks/9605-9332e1686c46da7d.js +1 -0
  67. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-9dae6fa5126cf001.js +1 -0
  68. mage_ai/server/frontend_dist/_next/static/chunks/pages/files-2dc2a0dfc0ff620d.js +1 -0
  69. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-6d3d53624debede6.js +1 -0
  70. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-2756fe6d9decae4a.js +1 -0
  71. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/settings-6577159a0af52a78.js +1 -0
  72. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-6815a3ece7dc1678.js +1 -0
  73. mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-7f790238fe70d9ab.js +1 -0
  74. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-33c7f2550add0719.js +1 -0
  75. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-07e4a3a674e83578.js +1 -0
  76. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-b8b4bed1e8e50068.js +1 -0
  77. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-54cb4936accdd2d9.js +1 -0
  78. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-d331e98ad103b13e.js +1 -0
  79. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-d87d0c21758a2d7c.js +1 -0
  80. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-68e1b861ef4fc0d7.js +1 -0
  81. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-9fa0c4ce1c921a41.js +1 -0
  82. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-d5ef19ca1f9931de.js +1 -0
  83. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-4a2671811a153411.js +1 -0
  84. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-8872a6e00280f58c.js +1 -0
  85. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-484581ae34a1c596.js +1 -0
  86. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-ce11db27e4af7869.js +1 -0
  87. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-624a2d7cbe6303b4.js +1 -0
  88. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-1169f4eecf752033.js +1 -0
  89. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-d2224a447987fa69.js → frontend_dist/_next/static/chunks/pages/settings/account/profile-c3ff06a12baa40a2.js} +1 -1
  90. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-60b4398d7ae00206.js +1 -0
  91. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-dd827816bf4a7908.js → frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-05b53444f0e7449b.js} +1 -1
  92. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-097aa0bef1e34cdb.js → frontend_dist/_next/static/chunks/pages/sign-in-a5e9561a6c0d2e38.js} +1 -1
  93. mage_ai/server/frontend_dist/_next/static/chunks/pages/templates/{[...slug]-78a07e7fe8973811.js → [...slug]-c21b269750441494.js} +1 -1
  94. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/templates-19df643f52679d5a.js → frontend_dist/_next/static/chunks/pages/templates-ce2a29d477a6ce94.js} +1 -1
  95. mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-71bbb30dd9b57f80.js +1 -0
  96. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-1dc780d52fbd1573.js +1 -0
  97. mage_ai/server/frontend_dist/files.html +2 -2
  98. mage_ai/server/frontend_dist/global-data-products/[...slug].html +2 -2
  99. mage_ai/server/frontend_dist/global-data-products.html +2 -2
  100. mage_ai/server/frontend_dist/index.html +2 -2
  101. mage_ai/server/frontend_dist/manage/settings.html +2 -2
  102. mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
  103. mage_ai/server/frontend_dist/manage/users/new.html +2 -2
  104. mage_ai/server/frontend_dist/manage/users.html +2 -2
  105. mage_ai/server/frontend_dist/manage.html +2 -2
  106. mage_ai/server/frontend_dist/overview.html +2 -2
  107. mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
  108. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  109. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
  110. mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
  111. mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
  112. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  113. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  114. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
  115. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
  116. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
  117. mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
  118. mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
  119. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  120. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
  121. mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
  122. mage_ai/server/frontend_dist/pipelines.html +2 -2
  123. mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
  124. mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
  125. mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
  126. mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
  127. mage_ai/server/frontend_dist/settings.html +2 -2
  128. mage_ai/server/frontend_dist/sign-in.html +11 -11
  129. mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
  130. mage_ai/server/frontend_dist/templates.html +2 -2
  131. mage_ai/server/frontend_dist/terminal.html +2 -2
  132. mage_ai/server/frontend_dist/test.html +3 -3
  133. mage_ai/server/frontend_dist/triggers.html +2 -2
  134. mage_ai/server/frontend_dist/version-control.html +2 -2
  135. mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
  136. mage_ai/server/frontend_dist_base_path_template/404.html.html +2 -2
  137. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1005-a2f0e3ee378ef02b.js +1 -0
  138. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1424-fca78f21a81a7183.js +1 -0
  139. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1484-87d4d4a698ac63dc.js +1 -0
  140. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2485-39885e5335888821.js +1 -0
  141. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2786-f71862671f66d948.js +1 -0
  142. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3391-6f0a0a5c254cd7f2.js +1 -0
  143. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3881-131cf690e54c23a3.js +1 -0
  144. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/437-331193bd9b2fe777.js +1 -0
  145. mage_ai/server/{frontend_dist/_next/static/chunks/4822-045cc7cdd7c95163.js → frontend_dist_base_path_template/_next/static/chunks/4822-ee62acb1927c8150.js} +1 -1
  146. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/547-bd961ea93f3eb98b.js +1 -0
  147. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6299-fcb702d0f3d3291b.js +1 -0
  148. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6422-0cdd6e596dcd43b6.js +1 -0
  149. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{6786-77c7e36678abb2c6.js → 6786-55e1bca3c897d5ee.js} +1 -1
  150. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7496-7e4dd11e3f3b8e79.js +1 -0
  151. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7722-76c724a66240561b.js +1 -0
  152. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7815-8b68b0eb665fcd2d.js +1 -0
  153. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8190-d38ed1133030797d.js +1 -0
  154. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8952-9d6fa18fa9378989.js +1 -0
  155. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9605-9332e1686c46da7d.js +1 -0
  156. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-9dae6fa5126cf001.js +1 -0
  157. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-2dc2a0dfc0ff620d.js +1 -0
  158. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-6d3d53624debede6.js +1 -0
  159. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-2756fe6d9decae4a.js +1 -0
  160. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/settings-6577159a0af52a78.js +1 -0
  161. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-6815a3ece7dc1678.js +1 -0
  162. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-7f790238fe70d9ab.js +1 -0
  163. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-33c7f2550add0719.js +1 -0
  164. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-07e4a3a674e83578.js +1 -0
  165. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-b8b4bed1e8e50068.js +1 -0
  166. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-54cb4936accdd2d9.js +1 -0
  167. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-d331e98ad103b13e.js +1 -0
  168. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-d87d0c21758a2d7c.js +1 -0
  169. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-68e1b861ef4fc0d7.js +1 -0
  170. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-9fa0c4ce1c921a41.js +1 -0
  171. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-d5ef19ca1f9931de.js +1 -0
  172. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-4a2671811a153411.js +1 -0
  173. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-8872a6e00280f58c.js +1 -0
  174. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-484581ae34a1c596.js +1 -0
  175. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-ce11db27e4af7869.js +1 -0
  176. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-624a2d7cbe6303b4.js +1 -0
  177. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-1169f4eecf752033.js +1 -0
  178. mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/account/profile-d2224a447987fa69.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/account/profile-c3ff06a12baa40a2.js} +1 -1
  179. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-60b4398d7ae00206.js +1 -0
  180. mage_ai/server/{frontend_dist/_next/static/chunks/pages/settings/workspace/sync-data-dd827816bf4a7908.js → frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/sync-data-05b53444f0e7449b.js} +1 -1
  181. mage_ai/server/{frontend_dist/_next/static/chunks/pages/sign-in-097aa0bef1e34cdb.js → frontend_dist_base_path_template/_next/static/chunks/pages/sign-in-a5e9561a6c0d2e38.js} +1 -1
  182. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/templates/{[...slug]-78a07e7fe8973811.js → [...slug]-c21b269750441494.js} +1 -1
  183. mage_ai/server/{frontend_dist/_next/static/chunks/pages/templates-19df643f52679d5a.js → frontend_dist_base_path_template/_next/static/chunks/pages/templates-ce2a29d477a6ce94.js} +1 -1
  184. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-71bbb30dd9b57f80.js +1 -0
  185. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-1dc780d52fbd1573.js +1 -0
  186. mage_ai/server/frontend_dist_base_path_template/_next/static/yJvL-3bfsNF3WCStZ10Dm/_buildManifest.js +1 -0
  187. mage_ai/server/frontend_dist_base_path_template/files.html +2 -2
  188. mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +2 -2
  189. mage_ai/server/frontend_dist_base_path_template/global-data-products.html +2 -2
  190. mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
  191. mage_ai/server/frontend_dist_base_path_template/manage/settings.html +2 -2
  192. mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +2 -2
  193. mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +2 -2
  194. mage_ai/server/frontend_dist_base_path_template/manage/users.html +2 -2
  195. mage_ai/server/frontend_dist_base_path_template/manage.html +2 -2
  196. mage_ai/server/frontend_dist_base_path_template/overview.html +2 -2
  197. mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +2 -2
  198. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  199. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +2 -2
  200. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
  201. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +2 -2
  202. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  203. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  204. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +2 -2
  205. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +2 -2
  206. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +2 -2
  207. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +2 -2
  208. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +2 -2
  209. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  210. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +2 -2
  211. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
  212. mage_ai/server/frontend_dist_base_path_template/pipelines.html +2 -2
  213. mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +2 -2
  214. mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +2 -2
  215. mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +2 -2
  216. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +2 -2
  217. mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
  218. mage_ai/server/frontend_dist_base_path_template/sign-in.html +11 -11
  219. mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +2 -2
  220. mage_ai/server/frontend_dist_base_path_template/templates.html +2 -2
  221. mage_ai/server/frontend_dist_base_path_template/terminal.html +2 -2
  222. mage_ai/server/frontend_dist_base_path_template/test.html +3 -3
  223. mage_ai/server/frontend_dist_base_path_template/triggers.html +2 -2
  224. mage_ai/server/frontend_dist_base_path_template/version-control.html +2 -2
  225. mage_ai/server/server.py +53 -27
  226. mage_ai/services/spark/spark.py +75 -2
  227. mage_ai/streaming/constants.py +1 -0
  228. mage_ai/streaming/sources/kafka.py +17 -9
  229. mage_ai/tests/data_preparation/models/custom_templates/__init__.py +0 -0
  230. mage_ai/tests/data_preparation/models/custom_templates/test_utils.py +36 -0
  231. mage_ai/tests/data_preparation/models/test_block.py +48 -0
  232. mage_ai/tests/data_preparation/test_repo_manager.py +19 -1
  233. mage_ai/tests/server/test_server.py +20 -2
  234. mage_ai/tests/services/spark/__init__.py +0 -0
  235. mage_ai/tests/services/spark/test_spark.py +52 -0
  236. {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/METADATA +1 -1
  237. {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/RECORD +245 -233
  238. mage_ai/server/frontend_dist/_next/static/RdDEYzOW6lfmOEilKsz4V/_buildManifest.js +0 -1
  239. mage_ai/server/frontend_dist/_next/static/chunks/1005-2f8ef0e28c917767.js +0 -1
  240. mage_ai/server/frontend_dist/_next/static/chunks/1424-a2cd1bfc708a323b.js +0 -1
  241. mage_ai/server/frontend_dist/_next/static/chunks/1484-a07f74ae5c40141c.js +0 -1
  242. mage_ai/server/frontend_dist/_next/static/chunks/2485-b569baad92049d6b.js +0 -1
  243. mage_ai/server/frontend_dist/_next/static/chunks/2786-acce6ea0d9b4898e.js +0 -1
  244. mage_ai/server/frontend_dist/_next/static/chunks/3654-14ee3eacc42b118a.js +0 -1
  245. mage_ai/server/frontend_dist/_next/static/chunks/3881-0eb04f7f7a244347.js +0 -1
  246. mage_ai/server/frontend_dist/_next/static/chunks/437-d43ccff3a064a528.js +0 -1
  247. mage_ai/server/frontend_dist/_next/static/chunks/547-4ad2cdae967055b6.js +0 -1
  248. mage_ai/server/frontend_dist/_next/static/chunks/6299-cf188c1b7a1bc33c.js +0 -1
  249. mage_ai/server/frontend_dist/_next/static/chunks/7496-ab1be388ae09d362.js +0 -1
  250. mage_ai/server/frontend_dist/_next/static/chunks/7722-a74e6f977993e75e.js +0 -1
  251. mage_ai/server/frontend_dist/_next/static/chunks/7815-fbd99c8f259d9e8b.js +0 -1
  252. mage_ai/server/frontend_dist/_next/static/chunks/8952-98e54b14c1af492f.js +0 -1
  253. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-74805cf1296fd50f.js +0 -1
  254. mage_ai/server/frontend_dist/_next/static/chunks/pages/files-bcdaa82adcca891d.js +0 -1
  255. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products/[...slug]-abdbda772d94c386.js +0 -1
  256. mage_ai/server/frontend_dist/_next/static/chunks/pages/global-data-products-01f8ef10e87ec236.js +0 -1
  257. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/settings-950fbcb72961eb3c.js +0 -1
  258. mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-c6fd44191c812edf.js +0 -1
  259. mage_ai/server/frontend_dist/_next/static/chunks/pages/overview-6e46ed84cf3f4e9d.js +0 -1
  260. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipeline-runs-1d52bba72442c53f.js +0 -1
  261. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-8c33956a28fb4fa8.js +0 -1
  262. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-b28d151c32c2a469.js +0 -1
  263. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-e1708e5576cd26d1.js +0 -1
  264. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-0f3468d52020dcbf.js +0 -1
  265. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-489d02937d5f4695.js +0 -1
  266. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-544475d8e841638f.js +0 -1
  267. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e117a99f334b6022.js +0 -1
  268. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-f1ef481c7beb8aef.js +0 -1
  269. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-ab52e3174c3dcf64.js +0 -1
  270. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-3e290f7d76c68b3f.js +0 -1
  271. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/syncs-1ac4dc91ec394c6d.js +0 -1
  272. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-4753de69f7e366c5.js +0 -1
  273. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers-cf285c43759e9b2a.js +0 -1
  274. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-3f86e7f1c8d63beb.js +0 -1
  275. mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-b2354688508b0755.js +0 -1
  276. mage_ai/server/frontend_dist/_next/static/chunks/pages/triggers-cacb24e3632cfdfc.js +0 -1
  277. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-5a6e3a62fef551f1.js +0 -1
  278. mage_ai/server/frontend_dist_base_path_template/_next/static/4dbzHNz2XwS_s6Z0qsIGO/_buildManifest.js +0 -1
  279. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1005-2f8ef0e28c917767.js +0 -1
  280. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1424-a2cd1bfc708a323b.js +0 -1
  281. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1484-a07f74ae5c40141c.js +0 -1
  282. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2485-b569baad92049d6b.js +0 -1
  283. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2786-acce6ea0d9b4898e.js +0 -1
  284. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3654-14ee3eacc42b118a.js +0 -1
  285. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/3881-0eb04f7f7a244347.js +0 -1
  286. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/437-d43ccff3a064a528.js +0 -1
  287. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/547-4ad2cdae967055b6.js +0 -1
  288. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/6299-cf188c1b7a1bc33c.js +0 -1
  289. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7496-ab1be388ae09d362.js +0 -1
  290. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7722-a74e6f977993e75e.js +0 -1
  291. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7815-fbd99c8f259d9e8b.js +0 -1
  292. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/8952-98e54b14c1af492f.js +0 -1
  293. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-74805cf1296fd50f.js +0 -1
  294. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/files-bcdaa82adcca891d.js +0 -1
  295. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products/[...slug]-abdbda772d94c386.js +0 -1
  296. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/global-data-products-01f8ef10e87ec236.js +0 -1
  297. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage/settings-950fbcb72961eb3c.js +0 -1
  298. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/manage-c6fd44191c812edf.js +0 -1
  299. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/overview-6e46ed84cf3f4e9d.js +0 -1
  300. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipeline-runs-1d52bba72442c53f.js +0 -1
  301. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-8c33956a28fb4fa8.js +0 -1
  302. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-b28d151c32c2a469.js +0 -1
  303. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-e1708e5576cd26d1.js +0 -1
  304. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-0f3468d52020dcbf.js +0 -1
  305. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runs-489d02937d5f4695.js +0 -1
  306. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors/block-runtime-544475d8e841638f.js +0 -1
  307. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/monitors-e117a99f334b6022.js +0 -1
  308. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs/[run]-f1ef481c7beb8aef.js +0 -1
  309. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-ab52e3174c3dcf64.js +0 -1
  310. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/settings-3e290f7d76c68b3f.js +0 -1
  311. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/syncs-1ac4dc91ec394c6d.js +0 -1
  312. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers/[...slug]-4753de69f7e366c5.js +0 -1
  313. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/triggers-cf285c43759e9b2a.js +0 -1
  314. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-3f86e7f1c8d63beb.js +0 -1
  315. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/settings/workspace/preferences-b2354688508b0755.js +0 -1
  316. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/triggers-cacb24e3632cfdfc.js +0 -1
  317. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-5a6e3a62fef551f1.js +0 -1
  318. /mage_ai/server/frontend_dist/_next/static/{RdDEYzOW6lfmOEilKsz4V → CNjkRIWPaAu1yJUmIaX_q}/_middlewareManifest.js +0 -0
  319. /mage_ai/server/frontend_dist/_next/static/{RdDEYzOW6lfmOEilKsz4V → CNjkRIWPaAu1yJUmIaX_q}/_ssgManifest.js +0 -0
  320. /mage_ai/server/frontend_dist_base_path_template/_next/static/{4dbzHNz2XwS_s6Z0qsIGO → yJvL-3bfsNF3WCStZ10Dm}/_middlewareManifest.js +0 -0
  321. /mage_ai/server/frontend_dist_base_path_template/_next/static/{4dbzHNz2XwS_s6Z0qsIGO → yJvL-3bfsNF3WCStZ10Dm}/_ssgManifest.js +0 -0
  322. {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/LICENSE +0 -0
  323. {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/WHEEL +0 -0
  324. {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/entry_points.txt +0 -0
  325. {mage_ai-0.9.12.dist-info → mage_ai-0.9.14.dist-info}/top_level.txt +0 -0
@@ -81,9 +81,11 @@ class RepoConfig:
81
81
  # from the config_dict. Otherwise, we will set the variables_dir with
82
82
  # `get_variables_dir`.
83
83
  if config_dict and config_dict.get('variables_dir'):
84
- self.variables_dir = os.path.abspath(
85
- os.path.join(self.repo_path, config_dict.get('variables_dir'))
86
- )
84
+ self.variables_dir = config_dict.get('variables_dir')
85
+ if not self.variables_dir.startswith('s3'):
86
+ self.variables_dir = os.path.abspath(
87
+ os.path.join(self.repo_path, self.variables_dir)
88
+ )
87
89
  else:
88
90
  self.variables_dir = get_variables_dir(
89
91
  repo_path=self.repo_path,
@@ -164,7 +166,7 @@ class RepoConfig:
164
166
  def save(self, **kwargs) -> None:
165
167
  if os.path.exists(self.metadata_path):
166
168
  with open(self.metadata_path) as f:
167
- data = yml.load(f)
169
+ data = yml.load(f) or {}
168
170
  else:
169
171
  data = {}
170
172
 
@@ -284,25 +286,35 @@ def get_variables_dir(
284
286
  variables_dir = os.path.abspath(
285
287
  os.path.join(repo_path, variables_dir),
286
288
  )
287
- os.makedirs(variables_dir, exist_ok=True)
289
+ try:
290
+ os.makedirs(variables_dir, exist_ok=True)
291
+ except Exception:
292
+ traceback.print_exc()
288
293
  return variables_dir
289
294
 
290
295
 
291
- project_uuid = None
292
- try:
293
- with get_metadata_path() as f:
294
- config = yml.load(f) or {}
295
- project_uuid = config.get('project_uuid')
296
- except Exception:
297
- pass
296
+ def set_project_uuid_from_metadata():
297
+ global project_uuid
298
+ if os.path.exists(get_metadata_path()):
299
+ with open(get_metadata_path(), 'r', encoding='utf-8') as f:
300
+ config = yml.load(f) or {}
301
+ project_uuid = config.get('project_uuid')
298
302
 
299
303
 
300
- def update_project_uuid():
304
+ def init_project_uuid():
301
305
  global project_uuid
302
306
  if not project_uuid:
303
- puuid = uuid.uuid4().hex
304
- get_repo_config().save(project_uuid=puuid)
305
- project_uuid = puuid
307
+ repo_config = get_repo_config()
308
+ if repo_config.project_uuid:
309
+ project_uuid = repo_config.project_uuid
310
+ else:
311
+ puuid = uuid.uuid4().hex
312
+ repo_config.save(project_uuid=puuid)
313
+ project_uuid = puuid
314
+
315
+
316
+ project_uuid = None
317
+ set_project_uuid_from_metadata()
306
318
 
307
319
 
308
320
  def get_project_uuid() -> str:
mage_ai/io/clickhouse.py CHANGED
@@ -236,12 +236,14 @@ EXISTS TABLE {database}.{table_name}
236
236
  self.client.command(f'USE {database}')
237
237
 
238
238
  if should_create_table:
239
- self.client.command(f"""
240
- CREATE TABLE IF NOT EXISTS {database}.{table_name} ENGINE = Memory AS
239
+ with self.printer.print_msg(
240
+ f'Creating a new table: {database}.{table_name}'):
241
+ self.client.command(f"""
242
+ CREATE TABLE IF NOT EXISTS {database}.{table_name} ENGINE = Memory EMPTY AS
241
243
  {query_string}
242
244
  """)
243
- else:
244
- self.client.command(f"""
245
+
246
+ self.client.command(f"""
245
247
  INSERT INTO {database}.{table_name}
246
248
  {query_string}
247
249
  """)
@@ -254,8 +256,9 @@ INSERT INTO {database}.{table_name}
254
256
  table_name=table_name,
255
257
  database=database,
256
258
  )
257
- self.printer.print_msg(f'Creating a new table: {create_table_stmt}')
258
- self.client.command(create_table_stmt)
259
+ with self.printer.print_msg(
260
+ f'Creating a new table: {create_table_stmt}'):
261
+ self.client.command(create_table_stmt)
259
262
 
260
263
  self.client.insert_df(f'{database}.{table_name}', df)
261
264
 
mage_ai/io/redshift.py CHANGED
@@ -1,20 +1,19 @@
1
- from mage_ai.io.base import ExportWritePolicy, QUERY_ROW_LIMIT
1
+ import json
2
+ import warnings
3
+ from typing import Union
4
+
5
+ from pandas import DataFrame
6
+ from redshift_connector import connect
7
+
8
+ from mage_ai.io.base import QUERY_ROW_LIMIT, ExportWritePolicy
2
9
  from mage_ai.io.config import BaseConfigLoader, ConfigKey
3
- from mage_ai.io.export_utils import (
4
- clean_df_for_export,
5
- infer_dtypes,
6
- )
10
+ from mage_ai.io.export_utils import clean_df_for_export, infer_dtypes
7
11
  from mage_ai.io.sql import BaseSQL
8
12
  from mage_ai.io.utils import format_value
9
13
  from mage_ai.shared.utils import (
10
14
  convert_pandas_dtype_to_python_type,
11
15
  convert_python_type_to_redshift_type,
12
16
  )
13
- from pandas import DataFrame
14
- from redshift_connector import connect
15
- from typing import Union
16
- import json
17
- import warnings
18
17
 
19
18
 
20
19
  class Redshift(BaseSQL):
mage_ai/io/utils.py CHANGED
@@ -2,7 +2,7 @@ import pandas as pd
2
2
 
3
3
 
4
4
  def format_value(value):
5
- if value is None or pd.isnull(value):
5
+ if type(value) is not list and (value is None or pd.isnull(value)):
6
6
  return 'NULL'
7
7
 
8
8
  if type(value) is bool:
@@ -16,6 +16,8 @@ def format_value(value):
16
16
 
17
17
  if type(value) is str:
18
18
  value = escape_quotes(value)
19
+ else:
20
+ value = escape_quotes(str(value))
19
21
 
20
22
  return f"'{value}'"
21
23
 
@@ -2,9 +2,46 @@
2
2
 
3
3
  We use alembic to perform DB migrations. alembic tutorial: https://alembic.sqlalchemy.org/en/latest/tutorial.html
4
4
 
5
+ ## Before running commands
6
+
7
+ 1. Open the file `mage-ai/mage_ai/orchestration/db/alembic.ini`
8
+ 1. Change the value `sqlalchemy.url` to the URL of your database.
9
+ - e.g. `sqlalchemy.url = postgresql+psycopg2://postgres:postgres@host.docker.internal:5432/demo`
10
+
5
11
  ## Create migration scripts
6
- `alembic revision --autogenerate -m "Migration message"`
7
12
 
13
+ Change directory into:
14
+
15
+ ```
16
+ cd mage_ai/orchestration/db
17
+ ```
18
+
19
+
20
+ ```
21
+ alembic revision --autogenerate -m "Migration message"
22
+ ```
23
+
24
+ If you don’t see your changes in the migration file, add your new models module in this
25
+ file: `mage-ai/mage_ai/orchestration/db/migrations/env.py`
26
+
27
+ For example:
28
+
29
+ ```python
30
+ import mage_ai.orchestration.db.models.tags # noqa: E402, F401
31
+ ```
8
32
 
9
33
  ## Run migration
10
- `alembic upgrade head`
34
+
35
+ ```
36
+ alembic upgrade head
37
+ ```
38
+
39
+ ## Rollback migration
40
+
41
+ ```
42
+ alembic downgrade -1
43
+ ```
44
+
45
+ ## Clean up
46
+
47
+ 1. Change the `sqlalchemy.url` back to the original value.
@@ -34,6 +34,7 @@ sys.path.insert(0, os.path.dirname(
34
34
  import mage_ai.orchestration.db.models.oauth # noqa: E402, F401
35
35
  import mage_ai.orchestration.db.models.schedules # noqa: E402, F401
36
36
  import mage_ai.orchestration.db.models.secrets # noqa: E402, F401
37
+ import mage_ai.orchestration.db.models.tags # noqa: E402, F401
37
38
  from mage_ai.orchestration.db.models.base import Base # noqa: E402
38
39
 
39
40
  target_metadata = Base.metadata
@@ -0,0 +1,59 @@
1
+ """Create Tag and TagAssociation tables
2
+
3
+ Revision ID: 386bcfebd48d
4
+ Revises: 66928ca5b0d7
5
+ Create Date: 2023-08-08 08:35:27.099117
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '386bcfebd48d'
14
+ down_revision = '66928ca5b0d7'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade() -> None:
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ op.create_table('tag',
22
+ sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
23
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
24
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
25
+ sa.Column('description', sa.Text(), nullable=True),
26
+ sa.Column('name', sa.String(length=255), nullable=True),
27
+ sa.PrimaryKeyConstraint('id')
28
+ )
29
+ with op.batch_alter_table('tag', schema=None) as batch_op:
30
+ batch_op.create_index(batch_op.f('ix_tag_name'), ['name'], unique=True)
31
+
32
+ op.create_table('tag_association',
33
+ sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
34
+ sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
35
+ sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
36
+ sa.Column('tag_id', sa.Integer(), nullable=True),
37
+ sa.Column('taggable_id', sa.Integer(), nullable=True),
38
+ sa.Column('taggable_type', sa.String(length=255), nullable=True),
39
+ sa.ForeignKeyConstraint(['tag_id'], ['tag.id'], ),
40
+ sa.PrimaryKeyConstraint('id'),
41
+ sa.UniqueConstraint('tag_id', 'taggable_id', 'taggable_type', name='tag_id_taggable_id_taggable_type_uc')
42
+ )
43
+ with op.batch_alter_table('tag_association', schema=None) as batch_op:
44
+ batch_op.create_index(batch_op.f('ix_tag_association_taggable_id'), ['taggable_id', 'taggable_type'], unique=False)
45
+
46
+ # ### end Alembic commands ###
47
+
48
+
49
+ def downgrade() -> None:
50
+ # ### commands auto generated by Alembic - please adjust! ###
51
+ with op.batch_alter_table('tag_association', schema=None) as batch_op:
52
+ batch_op.drop_index(batch_op.f('ix_tag_association_taggable_id'))
53
+
54
+ op.drop_table('tag_association')
55
+ with op.batch_alter_table('tag', schema=None) as batch_op:
56
+ batch_op.drop_index(batch_op.f('ix_tag_name'))
57
+
58
+ op.drop_table('tag')
59
+ # ### end Alembic commands ###
@@ -45,6 +45,7 @@ from mage_ai.data_preparation.models.triggers import (
45
45
  from mage_ai.data_preparation.variable_manager import get_global_variables
46
46
  from mage_ai.orchestration.db import db_connection, safe_db_query
47
47
  from mage_ai.orchestration.db.models.base import Base, BaseModel, classproperty
48
+ from mage_ai.orchestration.db.models.tags import Tag, TagAssociation
48
49
  from mage_ai.settings.repo import get_repo_path
49
50
  from mage_ai.shared.array import find
50
51
  from mage_ai.shared.constants import ENV_PROD
@@ -120,6 +121,28 @@ class PipelineSchedule(BaseModel):
120
121
  return None
121
122
  return sorted(self.pipeline_runs, key=lambda x: x.created_at)[-1].status
122
123
 
124
+ @property
125
+ def tag_associations(self):
126
+ return (
127
+ TagAssociation.
128
+ select(
129
+ TagAssociation.id,
130
+ TagAssociation.tag_id,
131
+ TagAssociation.taggable_id,
132
+ TagAssociation.taggable_type,
133
+ Tag.name,
134
+ ).
135
+ join(
136
+ Tag,
137
+ Tag.id == TagAssociation.tag_id,
138
+ ).
139
+ filter(
140
+ TagAssociation.taggable_id == self.id,
141
+ TagAssociation.taggable_type == self.__class__.__name__,
142
+ ).
143
+ all()
144
+ )
145
+
123
146
  @classmethod
124
147
  @safe_db_query
125
148
  def active_schedules(self, pipeline_uuids: List[str] = None) -> List['PipelineSchedule']:
@@ -223,7 +246,7 @@ class PipelineSchedule(BaseModel):
223
246
 
224
247
  @safe_db_query
225
248
  def should_schedule(self, previous_runtimes: List[int] = None) -> bool:
226
- now = datetime.now()
249
+ now = datetime.now(tz=pytz.UTC)
227
250
 
228
251
  if self.status != ScheduleStatus.ACTIVE:
229
252
  return False
@@ -411,6 +434,10 @@ class PipelineRun(BaseModel):
411
434
  def block_runs_count(self) -> int:
412
435
  return len(self.block_runs)
413
436
 
437
+ @property
438
+ def completed_block_runs_count(self) -> int:
439
+ return len(self.completed_block_runs)
440
+
414
441
  @property
415
442
  def execution_partition(self) -> str:
416
443
  if self.variables and self.variables.get('execution_partition'):
@@ -533,7 +560,7 @@ class PipelineRun(BaseModel):
533
560
  @safe_db_query
534
561
  def complete(self):
535
562
  self.update(
536
- completed_at=datetime.now(),
563
+ completed_at=datetime.now(tz=pytz.UTC),
537
564
  status=self.PipelineRunStatus.COMPLETED,
538
565
  )
539
566
 
@@ -0,0 +1,57 @@
1
+ from sqlalchemy import (
2
+ Column,
3
+ ForeignKey,
4
+ Integer,
5
+ String,
6
+ Text,
7
+ UniqueConstraint,
8
+ )
9
+ from sqlalchemy.orm import relationship
10
+ from sqlalchemy.schema import Index
11
+
12
+ from mage_ai.orchestration.db.models.base import BaseModel
13
+
14
+
15
+ class Tag(BaseModel):
16
+ description = Column(Text)
17
+ name = Column(String(255), index=True, unique=True)
18
+
19
+ tag_associations = relationship('TagAssociation', back_populates='tag')
20
+
21
+ @property
22
+ def uuid(self) -> str:
23
+ return self.name
24
+
25
+
26
+ class TagAssociation(BaseModel):
27
+ tag_id = Column(Integer, ForeignKey('tag.id'))
28
+ taggable_id = Column(Integer)
29
+ taggable_type = Column(String(255))
30
+
31
+ tag = relationship(Tag, back_populates='tag_associations')
32
+
33
+ __table_args__ = (
34
+ UniqueConstraint(
35
+ 'tag_id',
36
+ 'taggable_id',
37
+ 'taggable_type',
38
+ name='tag_id_taggable_id_taggable_type_uc',
39
+ ),
40
+ Index(None, 'taggable_id', 'taggable_type'),
41
+ )
42
+
43
+
44
+ class TagAssociationWithTag:
45
+ def __init__(
46
+ self,
47
+ id: int = None,
48
+ name: str = None,
49
+ tag_id: int = None,
50
+ taggable_id: int = None,
51
+ taggable_type: str = None,
52
+ ):
53
+ self.id = id
54
+ self.name = name
55
+ self.tag_id = tag_id
56
+ self.taggable_id = taggable_id
57
+ self.taggable_type = taggable_type
@@ -186,7 +186,7 @@ class PipelineScheduler:
186
186
  if self.pipeline_run.any_blocks_failed():
187
187
  self.pipeline_run.update(
188
188
  status=PipelineRun.PipelineRunStatus.FAILED,
189
- completed_at=datetime.now(),
189
+ completed_at=datetime.now(tz=pytz.UTC),
190
190
  )
191
191
  self.notification_sender.send_pipeline_run_failure_message(
192
192
  pipeline=self.pipeline,
@@ -213,7 +213,7 @@ class PipelineScheduler:
213
213
  if all([PipelineRun.PipelineRunStatus.COMPLETED == pr.status
214
214
  for pr in backfill.pipeline_runs]):
215
215
  backfill.update(
216
- completed_at=datetime.now(),
216
+ completed_at=datetime.now(tz=pytz.UTC),
217
217
  status=Backfill.Status.COMPLETED,
218
218
  )
219
219
  schedule.update(
@@ -247,7 +247,7 @@ class PipelineScheduler:
247
247
  def update_status():
248
248
  block_run.update(
249
249
  status=BlockRun.BlockRunStatus.COMPLETED,
250
- completed_at=datetime.now(),
250
+ completed_at=datetime.now(tz=pytz.UTC),
251
251
  )
252
252
 
253
253
  update_status()
@@ -281,7 +281,7 @@ class PipelineScheduler:
281
281
  def update_status():
282
282
  block_run.update(
283
283
  status=BlockRun.BlockRunStatus.COMPLETED,
284
- completed_at=datetime.now(),
284
+ completed_at=datetime.now(tz=pytz.UTC),
285
285
  )
286
286
 
287
287
  update_status()
@@ -924,7 +924,7 @@ def run_integration_stream(
924
924
  return
925
925
 
926
926
  block_run.update(
927
- started_at=datetime.now(),
927
+ started_at=datetime.now(tz=pytz.UTC),
928
928
  status=BlockRun.BlockRunStatus.RUNNING,
929
929
  )
930
930
  pipeline_scheduler.logger.info(
@@ -1015,7 +1015,7 @@ def run_block(
1015
1015
  return {}
1016
1016
 
1017
1017
  block_run.update(
1018
- started_at=datetime.now(),
1018
+ started_at=datetime.now(tz=pytz.UTC),
1019
1019
  status=BlockRun.BlockRunStatus.RUNNING,
1020
1020
  )
1021
1021
 
@@ -1464,7 +1464,7 @@ def schedule_with_event(event: Dict = None):
1464
1464
 
1465
1465
  for p in matched_pipeline_schedules:
1466
1466
  payload = dict(
1467
- execution_date=datetime.now(),
1467
+ execution_date=datetime.now(tz=pytz.UTC),
1468
1468
  pipeline_schedule_id=p.id,
1469
1469
  pipeline_uuid=p.pipeline_uuid,
1470
1470
  variables=merge_dict(p.variables or dict(), dict(event=event)),
@@ -82,29 +82,40 @@ def trigger_and_check_status(
82
82
  if not is_outdated or not is_outdated_after:
83
83
  if verbose:
84
84
  next_run_at = global_data_product.next_run_at(pipeline_run)
85
- execution_date = pipeline_run.execution_date
86
- seconds = next_run_at.timestamp() - now.timestamp()
87
85
 
88
- if not is_outdated:
89
- print(
90
- f'Global data product {global_data_product.uuid} is up-to-date: '
91
- f'most recent pipeline run {pipeline_run.id} '
92
- f'executed at {execution_date.isoformat()}. '
93
- f'Will be outdated after {next_run_at.isoformat()} '
94
- f'in {round(seconds)} seconds.'
95
- )
96
- elif not is_outdated_after:
97
- arr = []
98
- for k, d in global_data_product.is_outdated_after(
99
- return_values=True,
100
- ).items():
101
- current = d.get('current')
102
- value = d.get('value')
103
- arr.append(f'{k.replace("_", " ")}: {value} (currently {current})')
86
+ if next_run_at:
87
+ execution_date = pipeline_run.execution_date
88
+ seconds = next_run_at.timestamp() - now.timestamp()
89
+
90
+ if not is_outdated:
91
+ print(
92
+ f'Global data product {global_data_product.uuid} is up-to-date: '
93
+ f'most recent pipeline run {pipeline_run.id} '
94
+ f'executed at {execution_date.isoformat()}. '
95
+ f'Will be outdated after {next_run_at.isoformat()} '
96
+ f'in {round(seconds)} seconds.'
97
+ )
98
+ elif not is_outdated_after:
99
+ arr = []
100
+ for k, d in global_data_product.is_outdated_after(
101
+ return_values=True,
102
+ ).items():
103
+ current = d.get('current')
104
+ value = d.get('value')
105
+ arr.append(f'{k.replace("_", " ")}: {value} (currently {current})')
104
106
 
107
+ print(
108
+ f'Global data product {global_data_product.uuid} '
109
+ 'is not yet outdated. '
110
+ 'It’ll be outdated after a specific moment in time - '
111
+ f'{", ".join(arr)}'
112
+ )
113
+ else:
105
114
  print(
106
- f'Global data product {global_data_product.uuid} is not yet outdated. '
107
- f'It’ll be outdated after a specific moment in time - {", ".join(arr)}'
115
+ f'Global data product {global_data_product.uuid} has no outdated at '
116
+ 'configured. '
117
+ 'You must configure when the global data product is outdated at '
118
+ 'in order for it to run.'
108
119
  )
109
120
 
110
121
  break
@@ -132,28 +143,18 @@ def trigger_and_check_status(
132
143
  timeout=10,
133
144
  ):
134
145
  pipeline_schedule = fetch_or_create_pipeline_schedule(global_data_product)
135
- try:
136
- pipeline_run_created = create_and_start_pipeline_run(
137
- global_data_product.pipeline,
138
- pipeline_schedule,
139
- dict(variables=variables),
140
- should_schedule=should_schedule,
141
- )
142
- if pipeline_run_created:
143
- if verbose:
144
- print(
145
- f'Created pipeline run {pipeline_run_created.id} for '
146
- f'global data product {global_data_product.uuid}.'
147
- )
148
- except AssertionError as err:
149
- if 'can only test a child process' in str(err):
146
+ pipeline_run_created = create_and_start_pipeline_run(
147
+ global_data_product.pipeline,
148
+ pipeline_schedule,
149
+ dict(variables=variables),
150
+ should_schedule=should_schedule,
151
+ )
152
+ if pipeline_run_created:
153
+ if verbose:
150
154
  print(
151
- '[WARNING] triggers.global_data_product.trigger_and_check_status '
152
- f'({global_data_product.uuid}): '
153
- f'{err}'
155
+ f'Created pipeline run {pipeline_run_created.id} for '
156
+ f'global data product {global_data_product.uuid}.'
154
157
  )
155
- else:
156
- raise err
157
158
 
158
159
  lock.release_lock(__lock_key_for_creating_pipeline_run(global_data_product))
159
160
 
@@ -82,6 +82,16 @@ def create_and_start_pipeline_run(
82
82
  # pipeline_run.get_variables(),
83
83
  # )
84
84
 
85
- pipeline_scheduler.start(should_schedule=should_schedule)
85
+ try:
86
+ pipeline_scheduler.start(should_schedule=should_schedule)
87
+ except AssertionError as err:
88
+ if 'can only test a child process' in str(err):
89
+ print(
90
+ '[WARNING] triggers.utils.create_and_start_pipeline_run '
91
+ f'({pipeline.uuid} {pipeline_schedule.id}): '
92
+ f'{err}'
93
+ )
94
+ else:
95
+ raise err
86
96
 
87
97
  return pipeline_run
@@ -12,4 +12,4 @@ DATAFRAME_OUTPUT_SAMPLE_COUNT = 10
12
12
  # Dockerfile depends on it because it runs ./scripts/install_mage.sh and uses
13
13
  # the last line to determine the version to install.
14
14
  VERSION = \
15
- '0.9.12'
15
+ '0.9.14'
@@ -1,4 +1,4 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=0" name="viewport"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><link href="/favicon.ico" rel="icon"/><link rel="preload" href="/_next/static/css/d1e8e64d0b07af2f.css" as="style"/><link rel="stylesheet" href="/_next/static/css/d1e8e64d0b07af2f.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-5cd94c89d3acac5f.js"></script><script src="/_next/static/chunks/webpack-8f51011a10b384a1.js" defer=""></script><script src="/_next/static/chunks/framework-7c365855dab1bf41.js" defer=""></script><script src="/_next/static/chunks/main-714e8aae7672e1fc.js" defer=""></script><script src="/_next/static/chunks/pages/_app-74805cf1296fd50f.js" defer=""></script><script src="/_next/static/chunks/pages/_error-235304e5badb19eb.js" defer=""></script><script src="/_next/static/RdDEYzOW6lfmOEilKsz4V/_buildManifest.js" defer=""></script><script src="/_next/static/RdDEYzOW6lfmOEilKsz4V/_ssgManifest.js" defer=""></script><script src="/_next/static/RdDEYzOW6lfmOEilKsz4V/_middlewareManifest.js" defer=""></script><style data-styled="" data-styled-version="5.3.6">html{-webkit-box-sizing:border-box;box-sizing:border-box;-ms-overflow-style:scrollbar;}/*!sc*/
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=0" name="viewport"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><link href="/favicon.ico" rel="icon"/><link rel="preload" href="/_next/static/css/d1e8e64d0b07af2f.css" as="style"/><link rel="stylesheet" href="/_next/static/css/d1e8e64d0b07af2f.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-5cd94c89d3acac5f.js"></script><script src="/_next/static/chunks/webpack-8f51011a10b384a1.js" defer=""></script><script src="/_next/static/chunks/framework-7c365855dab1bf41.js" defer=""></script><script src="/_next/static/chunks/main-714e8aae7672e1fc.js" defer=""></script><script src="/_next/static/chunks/pages/_app-9dae6fa5126cf001.js" defer=""></script><script src="/_next/static/chunks/pages/_error-235304e5badb19eb.js" defer=""></script><script src="/_next/static/CNjkRIWPaAu1yJUmIaX_q/_buildManifest.js" defer=""></script><script src="/_next/static/CNjkRIWPaAu1yJUmIaX_q/_ssgManifest.js" defer=""></script><script src="/_next/static/CNjkRIWPaAu1yJUmIaX_q/_middlewareManifest.js" defer=""></script><style data-styled="" data-styled-version="5.3.6">html{-webkit-box-sizing:border-box;box-sizing:border-box;-ms-overflow-style:scrollbar;}/*!sc*/
2
2
  *,*::before,*::after{-webkit-box-sizing:inherit;box-sizing:inherit;}/*!sc*/
3
3
  data-styled.g4[id="sc-global-czSCUT1"]{content:"sc-global-czSCUT1,"}/*!sc*/
4
4
  .kOVcuR .Toastify__toast-container{margin-top:24px;padding:0 !important;width:500px !important;}/*!sc*/
@@ -19,4 +19,4 @@ data-styled.g5[id="ToastWrapper-sc-1a33ph1-0"]{content:"kOVcuR,"}/*!sc*/
19
19
  .next-error-h1 {
20
20
  border-right: 1px solid rgba(255, 255, 255, .3);
21
21
  }
22
- }</style><h1 class="next-error-h1" style="display:inline-block;margin:0;margin-right:20px;padding:10px 23px 10px 0;font-size:24px;font-weight:500;vertical-align:top">404<!-- --></h1><div style="display:inline-block;text-align:left;line-height:49px;height:49px;vertical-align:middle"><h2 style="font-size:14px;font-weight:normal;line-height:inherit;margin:0;padding:0">This page could not be found<!-- -->.<!-- --></h2></div></div></div><div></div><div></div><div></div><div class="ToastWrapper-sc-1a33ph1-0 kOVcuR"><div class="Toastify"></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404},"currentTheme":{"accent":{"alert":"#F6540B","blue":"#4877FF","blueLight":"rgba(72, 119, 255, 0.5)","contentDefaultTransparent":"rgba(174, 174, 174, 0.5)","cyan":"#65E3FF","cyanLight":"rgba(101, 227, 255, 0.3)","cyanTransparent":"rgba(101, 227, 255, 0.12)","dbt":"#fc6949","dbtLight":"rgba(252, 105, 73, 0.5)","info":"#00ABFF","infoTransparent":"rgba(0, 171, 255, 0.5)","negative":"#FF1E59","negativeTransparent":"rgba(255, 30, 89, 0.3)","pink":"#FF4FF8","pinkLight":"rgb(255, 79, 248, 0.5)","positive":"#00A81A","primaryTransparent":"rgba(155, 108, 167, 0.5)","purple":"#7D55EC","purpleLight":"rgba(125, 85, 236, 0.5)","rose":"#D1A2AB","roseLight":"rgba(209, 162, 171, 0.5)","sky":"#6AA1E0","skyLight":"rgba(106, 161, 224, 0.05)","teal":"#00B4CC","tealLight":"rgba(0, 180, 204, 0.5)","warning":"#DD9900","warningTransparent":"rgba(221, 153, 0, 0.5)","yellow":"#FFCC19","yellowLight":"rgba(255, 204, 25, 0.5)"},"background":{"chartBlock":"#2E3036","codeArea":"#1E1F24","codeTextarea":"#000000","content":"#1B1C20","danger":"#FFD0DB","dark":"#B1B8C3","dashboard":"#18181C","header":"#1B1B1B","menu":"#0F4CFF","muted":"#F9FAFC","navigation":"#EDEDED","output":"#2E3036","page":"#1E1F24","panel":"#232429","popup":"#27292E","row":"#2C2C2C","row2":"#51535C","scrollbarThumb":"rgba(100, 100, 100, 0.5)","scrollbarThumbHover":"rgba(255, 255, 255, 0.3)","scrollbarTrack":"#2E3036","success":"#8ADE00","successLight":"rgb(138, 222, 0, 0.3)","table":"#292A2F","tag":"#3A4550"},"borders":{"button":"#454850","contrast":"#FFFFFF","danger":"#FF144D","dark":"#000000","info":"#FFCC19","light":"#2F3034","medium":"#1C1C1C","medium2":"#141414","success":"#2FCB52"},"brand":{"earth100":"#C6EEDB","earth200":"#9DDFBF","earth300":"#6BBF96","earth400":"#37A46F","earth400Transparent":"rgba(55, 164, 111, 0.4)","earth500":"#00954C","energy100":"#FFF4BA","energy200":"#FFED92","energy300":"#FFE662","energy400":"#FFDA19","energy400Transparent":"rgba(255, 218, 25, 0.04)","energy500":"#F6C000","fire100":"#FFD7E0","fire200":"#FFA3B9","fire300":"#FF547D","fire400":"#FF144D","fire400Transparent":"rgba(255, 20, 77, 0.4)","fire500":"#EB0032","stone100":"#F3E6D7","stone200":"#E3D4C2","stone400":"#BFA78B","stone500":"#AF8859","water100":"#BDCEFF","water200":"#81A1FF","water300":"#517DFF","water400":"#2A60FE","water400Transparent":"rgba(42, 96, 254, 0.4)","water500":"#0F4CFF","wind100":"#EEEAFF","wind200":"#CCC1F4","wind300":"#A698DD","wind400":"#6B50D7","wind400SuperTransparent":"rgba(107, 80, 215, 0.12)","wind400Transparent":"rgba(107, 80, 215, 0.4)","wind500":"#4E32BC"},"chart":{"backgroundPrimary":"#7D55EC","backgroundSecondary":"#FF144D","backgroundTertiary":"#86E2FF","button1":"#4877FF","button2":"#FFCC19","button3":"#8ADE00","button4":"#FF4FF8","button5":"#B98D95","lines":"#9B6CA7","primary":"#6B50D7","secondary":"#FF144D","tertiary":"#2A60FE"},"content":{"active":"#FFFFFF","default":"#AEAEAE","disabled":"rgba(255, 255, 255, 0.3)","inverted":"#2C2C2C","muted":"#787A85"},"elevation":{"visualizationAccent":"#996CFF","visualizationAccentAlt":"#C1ACF7"},"feature":{"active":"rgba(250, 248, 254, 0.14)","disabled":"rgba(201, 206, 218, 0.12)"},"icons":{"neutral":"#787878"},"interactive":{"activeBorder":"#060606","checked":"#060606","dangerBorder":"#FF144D","defaultBackground":"#36383F","defaultBorder":"#2E3036","disabledBorder":"#B1B8C3","focusBackground":"#B1B8C3","focusBorder":"#86E2FF","hoverBackground":"#4E4E4E","hoverBorder":"#B9BFCA","hoverOverlay":"rgba(255, 255, 255, 0.1)","linkPrimary":"#1752FF","linkPrimaryHover":"#4877FF","linkPrimaryLight":"#5982ff","linkSecondary":"#6B50D7","linkSecondaryDisabled":"#C4B9EF","linkText":"#6AA1E0","rowHoverBackground":"rgba(0, 0, 0, 0.1)","transparent":"rgba(255, 255, 255, 0)"},"loader":{"color":"#EB0032","colorInverted":"#8ADE00"},"logo":{"color":"#FFFFFF"},"monotone":{"black":"#060606","blackTransparent":"rgba(0, 0, 0, 0.6)","gray":"#B1B8C3","grey100":"#F2F2F2","grey200":"#D5D7DC","grey300":"#B4B8C0","grey400":"#70747C","grey500":"#51535C","purple":"#6B50D7","white":"#FFFFFF","whiteTransparent":"rgba(255, 255, 255, 0.6)"},"neutral":{"n100":"#E7E8EA","n200":"#D8DADE","n300":"#CBCCD0","n400":"#BCBEC4","n500":"#AEB0B6"},"progress":{"negative":"#FF144D","positive":"#6B50D7"},"shadow":{"base":"12px 40px 120px rgba(106, 117, 139, 0.4)","frame":"0px 10px 40px rgba(0, 0, 0, 0.26)","menu":"4px 10px 20px rgba(6, 6, 6, 0.12)","popup":"10px 20px 40px rgba(0, 0, 0, 0.2)","small":"0px, 4px, rgba(0, 0, 0, 0.25)","window":"0px 10px 60px rgba(0, 0, 0, 0.7)"},"status":{"negative":"#FF144D","positive":"#24B400"},"text":{"fileBrowser":"#787A85"}}},"page":"/_error","query":{},"buildId":"RdDEYzOW6lfmOEilKsz4V","nextExport":true,"isFallback":false,"gip":true,"appGip":true,"scriptLoader":[]}</script></body></html>
22
+ }</style><h1 class="next-error-h1" style="display:inline-block;margin:0;margin-right:20px;padding:10px 23px 10px 0;font-size:24px;font-weight:500;vertical-align:top">404<!-- --></h1><div style="display:inline-block;text-align:left;line-height:49px;height:49px;vertical-align:middle"><h2 style="font-size:14px;font-weight:normal;line-height:inherit;margin:0;padding:0">This page could not be found<!-- -->.<!-- --></h2></div></div></div><div></div><div></div><div></div><div class="ToastWrapper-sc-1a33ph1-0 kOVcuR"><div class="Toastify"></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404},"currentTheme":{"accent":{"alert":"#F6540B","blue":"#4877FF","blueLight":"rgba(72, 119, 255, 0.5)","contentDefaultTransparent":"rgba(174, 174, 174, 0.5)","cyan":"#65E3FF","cyanLight":"rgba(101, 227, 255, 0.3)","cyanTransparent":"rgba(101, 227, 255, 0.12)","dbt":"#fc6949","dbtLight":"rgba(252, 105, 73, 0.5)","info":"#00ABFF","infoTransparent":"rgba(0, 171, 255, 0.5)","negative":"#FF1E59","negativeTransparent":"rgba(255, 30, 89, 0.3)","pink":"#FF4FF8","pinkLight":"rgb(255, 79, 248, 0.5)","positive":"#00A81A","primaryTransparent":"rgba(155, 108, 167, 0.5)","purple":"#7D55EC","purpleLight":"rgba(125, 85, 236, 0.5)","rose":"#D1A2AB","roseLight":"rgba(209, 162, 171, 0.5)","sky":"#6AA1E0","skyLight":"rgba(106, 161, 224, 0.05)","teal":"#00B4CC","tealLight":"rgba(0, 180, 204, 0.5)","warning":"#DD9900","warningTransparent":"rgba(221, 153, 0, 0.5)","yellow":"#FFCC19","yellowLight":"rgba(255, 204, 25, 0.5)"},"background":{"chartBlock":"#2E3036","codeArea":"#1E1F24","codeTextarea":"#000000","content":"#1B1C20","danger":"#FFD0DB","dark":"#B1B8C3","dashboard":"#18181C","header":"#1B1B1B","menu":"#0F4CFF","muted":"#F9FAFC","navigation":"#EDEDED","output":"#2E3036","page":"#1E1F24","panel":"#232429","popup":"#27292E","row":"#2C2C2C","row2":"#51535C","scrollbarThumb":"rgba(100, 100, 100, 0.5)","scrollbarThumbHover":"rgba(255, 255, 255, 0.3)","scrollbarTrack":"#2E3036","success":"#8ADE00","successLight":"rgb(138, 222, 0, 0.3)","table":"#292A2F","tag":"#3A4550"},"borders":{"button":"#454850","contrast":"#FFFFFF","danger":"#FF144D","dark":"#000000","info":"#FFCC19","light":"#2F3034","medium":"#1C1C1C","medium2":"#141414","success":"#2FCB52"},"brand":{"earth100":"#C6EEDB","earth200":"#9DDFBF","earth300":"#6BBF96","earth400":"#37A46F","earth400Transparent":"rgba(55, 164, 111, 0.4)","earth500":"#00954C","energy100":"#FFF4BA","energy200":"#FFED92","energy300":"#FFE662","energy400":"#FFDA19","energy400Transparent":"rgba(255, 218, 25, 0.04)","energy500":"#F6C000","fire100":"#FFD7E0","fire200":"#FFA3B9","fire300":"#FF547D","fire400":"#FF144D","fire400Transparent":"rgba(255, 20, 77, 0.4)","fire500":"#EB0032","stone100":"#F3E6D7","stone200":"#E3D4C2","stone400":"#BFA78B","stone500":"#AF8859","water100":"#BDCEFF","water200":"#81A1FF","water300":"#517DFF","water400":"#2A60FE","water400Transparent":"rgba(42, 96, 254, 0.4)","water500":"#0F4CFF","wind100":"#EEEAFF","wind200":"#CCC1F4","wind300":"#A698DD","wind400":"#6B50D7","wind400SuperTransparent":"rgba(107, 80, 215, 0.12)","wind400Transparent":"rgba(107, 80, 215, 0.4)","wind500":"#4E32BC"},"chart":{"backgroundPrimary":"#7D55EC","backgroundSecondary":"#FF144D","backgroundTertiary":"#86E2FF","button1":"#4877FF","button2":"#FFCC19","button3":"#8ADE00","button4":"#FF4FF8","button5":"#B98D95","lines":"#9B6CA7","primary":"#6B50D7","secondary":"#FF144D","tertiary":"#2A60FE"},"content":{"active":"#FFFFFF","default":"#AEAEAE","disabled":"rgba(255, 255, 255, 0.3)","inverted":"#2C2C2C","muted":"#787A85"},"elevation":{"visualizationAccent":"#996CFF","visualizationAccentAlt":"#C1ACF7"},"feature":{"active":"rgba(250, 248, 254, 0.14)","disabled":"rgba(201, 206, 218, 0.12)"},"icons":{"neutral":"#787878"},"interactive":{"activeBorder":"#060606","checked":"#060606","dangerBorder":"#FF144D","defaultBackground":"#36383F","defaultBorder":"#2E3036","disabledBorder":"#B1B8C3","focusBackground":"#B1B8C3","focusBorder":"#86E2FF","hoverBackground":"#4E4E4E","hoverBorder":"#B9BFCA","hoverOverlay":"rgba(255, 255, 255, 0.1)","linkPrimary":"#1752FF","linkPrimaryHover":"#4877FF","linkPrimaryLight":"#5982ff","linkSecondary":"#6B50D7","linkSecondaryDisabled":"#C4B9EF","linkText":"#6AA1E0","linkTextLight":"#9ECBFF","rowHoverBackground":"rgba(0, 0, 0, 0.1)","transparent":"rgba(255, 255, 255, 0)"},"loader":{"color":"#EB0032","colorInverted":"#8ADE00"},"logo":{"color":"#FFFFFF"},"monotone":{"black":"#060606","blackTransparent":"rgba(0, 0, 0, 0.6)","gray":"#B1B8C3","grey100":"#F2F2F2","grey200":"#D5D7DC","grey300":"#B4B8C0","grey400":"#70747C","grey500":"#51535C","purple":"#6B50D7","white":"#FFFFFF","whiteTransparent":"rgba(255, 255, 255, 0.6)"},"neutral":{"n100":"#E7E8EA","n200":"#D8DADE","n300":"#CBCCD0","n400":"#BCBEC4","n500":"#AEB0B6"},"progress":{"negative":"#FF144D","positive":"#6B50D7"},"shadow":{"base":"12px 40px 120px rgba(106, 117, 139, 0.4)","frame":"0px 10px 40px rgba(0, 0, 0, 0.26)","menu":"4px 10px 20px rgba(6, 6, 6, 0.12)","popup":"10px 20px 40px rgba(0, 0, 0, 0.2)","small":"0px, 4px, rgba(0, 0, 0, 0.25)","window":"0px 10px 60px rgba(0, 0, 0, 0.7)"},"status":{"negative":"#FF144D","positive":"#24B400"},"text":{"fileBrowser":"#787A85"}}},"page":"/_error","query":{},"buildId":"CNjkRIWPaAu1yJUmIaX_q","nextExport":true,"isFallback":false,"gip":true,"appGip":true,"scriptLoader":[]}</script></body></html>