mage-ai 0.9.13__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 (148) 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/PipelineRunPolicy.py +1 -0
  5. mage_ai/api/presenters/BlockRunPresenter.py +4 -1
  6. mage_ai/api/presenters/PipelineRunPresenter.py +2 -0
  7. mage_ai/api/resources/BlockRunResource.py +18 -12
  8. mage_ai/api/resources/GitBranchResource.py +8 -1
  9. mage_ai/api/resources/PipelineResource.py +30 -14
  10. mage_ai/data_integrations/sources/constants.py +1 -0
  11. mage_ai/data_preparation/git/__init__.py +18 -0
  12. mage_ai/data_preparation/models/block/__init__.py +13 -1
  13. mage_ai/data_preparation/models/block/dbt/utils/__init__.py +5 -2
  14. mage_ai/data_preparation/models/block/integration/__init__.py +1 -1
  15. mage_ai/data_preparation/models/custom_templates/utils.py +14 -4
  16. mage_ai/data_preparation/models/variable.py +5 -2
  17. mage_ai/orchestration/db/models/schedules.py +4 -0
  18. mage_ai/server/constants.py +1 -1
  19. mage_ai/server/frontend_dist/404.html +2 -2
  20. mage_ai/server/frontend_dist/404.html.html +2 -2
  21. mage_ai/server/frontend_dist/_next/static/{O4HzlRY2U3Q47jF8s3D-E → CNjkRIWPaAu1yJUmIaX_q}/_buildManifest.js +1 -1
  22. mage_ai/server/frontend_dist/_next/static/chunks/{1005-ee665ba499795660.js → 1005-a2f0e3ee378ef02b.js} +1 -1
  23. mage_ai/server/frontend_dist/_next/static/chunks/1424-fca78f21a81a7183.js +1 -0
  24. mage_ai/server/frontend_dist/_next/static/chunks/2786-f71862671f66d948.js +1 -0
  25. mage_ai/server/frontend_dist/_next/static/chunks/7496-7e4dd11e3f3b8e79.js +1 -0
  26. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/9605-e40d076d9fc36d83.js → frontend_dist/_next/static/chunks/9605-9332e1686c46da7d.js} +1 -1
  27. mage_ai/server/frontend_dist/_next/static/chunks/pages/{_app-ccc78f4c29a2a431.js → _app-9dae6fa5126cf001.js} +1 -1
  28. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-54cb4936accdd2d9.js +1 -0
  29. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-4a2671811a153411.js +1 -0
  30. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{syncs-ddaca2c267def72a.js → syncs-484581ae34a1c596.js} +1 -1
  31. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-ff1faac7a72b1af1.js → triggers-624a2d7cbe6303b4.js} +1 -1
  32. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/triggers-eee16a91f281f92d.js → frontend_dist/_next/static/chunks/pages/triggers-71bbb30dd9b57f80.js} +1 -1
  33. mage_ai/server/frontend_dist/files.html +2 -2
  34. mage_ai/server/frontend_dist/global-data-products/[...slug].html +2 -2
  35. mage_ai/server/frontend_dist/global-data-products.html +2 -2
  36. mage_ai/server/frontend_dist/index.html +2 -2
  37. mage_ai/server/frontend_dist/manage/settings.html +2 -2
  38. mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
  39. mage_ai/server/frontend_dist/manage/users/new.html +2 -2
  40. mage_ai/server/frontend_dist/manage/users.html +2 -2
  41. mage_ai/server/frontend_dist/manage.html +2 -2
  42. mage_ai/server/frontend_dist/overview.html +2 -2
  43. mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
  44. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  45. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
  46. mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
  47. mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
  48. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  49. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  50. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
  51. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
  52. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
  53. mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
  54. mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
  55. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  56. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
  57. mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
  58. mage_ai/server/frontend_dist/pipelines.html +2 -2
  59. mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
  60. mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
  61. mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
  62. mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
  63. mage_ai/server/frontend_dist/settings.html +2 -2
  64. mage_ai/server/frontend_dist/sign-in.html +11 -11
  65. mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
  66. mage_ai/server/frontend_dist/templates.html +2 -2
  67. mage_ai/server/frontend_dist/terminal.html +2 -2
  68. mage_ai/server/frontend_dist/test.html +3 -3
  69. mage_ai/server/frontend_dist/triggers.html +2 -2
  70. mage_ai/server/frontend_dist/version-control.html +2 -2
  71. mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
  72. mage_ai/server/frontend_dist_base_path_template/404.html.html +2 -2
  73. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1005-ee665ba499795660.js → 1005-a2f0e3ee378ef02b.js} +1 -1
  74. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1424-fca78f21a81a7183.js +1 -0
  75. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2786-f71862671f66d948.js +1 -0
  76. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7496-7e4dd11e3f3b8e79.js +1 -0
  77. mage_ai/server/{frontend_dist/_next/static/chunks/9605-e40d076d9fc36d83.js → frontend_dist_base_path_template/_next/static/chunks/9605-9332e1686c46da7d.js} +1 -1
  78. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{_app-ccc78f4c29a2a431.js → _app-9dae6fa5126cf001.js} +1 -1
  79. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-54cb4936accdd2d9.js +1 -0
  80. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-4a2671811a153411.js +1 -0
  81. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{syncs-ddaca2c267def72a.js → syncs-484581ae34a1c596.js} +1 -1
  82. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-ff1faac7a72b1af1.js → triggers-624a2d7cbe6303b4.js} +1 -1
  83. mage_ai/server/{frontend_dist/_next/static/chunks/pages/triggers-eee16a91f281f92d.js → frontend_dist_base_path_template/_next/static/chunks/pages/triggers-71bbb30dd9b57f80.js} +1 -1
  84. mage_ai/server/frontend_dist_base_path_template/_next/static/{gJQ7p6K0VGDZzX1HXtRED → yJvL-3bfsNF3WCStZ10Dm}/_buildManifest.js +1 -1
  85. mage_ai/server/frontend_dist_base_path_template/files.html +2 -2
  86. mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +2 -2
  87. mage_ai/server/frontend_dist_base_path_template/global-data-products.html +2 -2
  88. mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
  89. mage_ai/server/frontend_dist_base_path_template/manage/settings.html +2 -2
  90. mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +2 -2
  91. mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +2 -2
  92. mage_ai/server/frontend_dist_base_path_template/manage/users.html +2 -2
  93. mage_ai/server/frontend_dist_base_path_template/manage.html +2 -2
  94. mage_ai/server/frontend_dist_base_path_template/overview.html +2 -2
  95. mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +2 -2
  96. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  97. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +2 -2
  98. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
  99. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +2 -2
  100. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  101. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  102. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +2 -2
  103. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +2 -2
  104. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +2 -2
  105. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +2 -2
  106. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +2 -2
  107. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  108. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +2 -2
  109. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
  110. mage_ai/server/frontend_dist_base_path_template/pipelines.html +2 -2
  111. mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +2 -2
  112. mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +2 -2
  113. mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +2 -2
  114. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +2 -2
  115. mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
  116. mage_ai/server/frontend_dist_base_path_template/sign-in.html +11 -11
  117. mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +2 -2
  118. mage_ai/server/frontend_dist_base_path_template/templates.html +2 -2
  119. mage_ai/server/frontend_dist_base_path_template/terminal.html +2 -2
  120. mage_ai/server/frontend_dist_base_path_template/test.html +3 -3
  121. mage_ai/server/frontend_dist_base_path_template/triggers.html +2 -2
  122. mage_ai/server/frontend_dist_base_path_template/version-control.html +2 -2
  123. mage_ai/services/spark/spark.py +75 -2
  124. mage_ai/tests/data_preparation/models/custom_templates/__init__.py +0 -0
  125. mage_ai/tests/data_preparation/models/custom_templates/test_utils.py +36 -0
  126. mage_ai/tests/data_preparation/models/test_block.py +48 -0
  127. mage_ai/tests/services/spark/__init__.py +0 -0
  128. mage_ai/tests/services/spark/test_spark.py +52 -0
  129. {mage_ai-0.9.13.dist-info → mage_ai-0.9.14.dist-info}/METADATA +1 -1
  130. {mage_ai-0.9.13.dist-info → mage_ai-0.9.14.dist-info}/RECORD +138 -134
  131. mage_ai/server/frontend_dist/_next/static/chunks/1424-846b754e84e6eac1.js +0 -1
  132. mage_ai/server/frontend_dist/_next/static/chunks/2786-ba6f486fcaf52ba0.js +0 -1
  133. mage_ai/server/frontend_dist/_next/static/chunks/7496-7d0f9adf0b333801.js +0 -1
  134. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-615ab9e61f0f39ed.js +0 -1
  135. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/runs-df014ddb14ebcef4.js +0 -1
  136. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/1424-846b754e84e6eac1.js +0 -1
  137. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/2786-ba6f486fcaf52ba0.js +0 -1
  138. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/7496-7d0f9adf0b333801.js +0 -1
  139. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/edit-615ab9e61f0f39ed.js +0 -1
  140. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/runs-df014ddb14ebcef4.js +0 -1
  141. /mage_ai/server/frontend_dist/_next/static/{O4HzlRY2U3Q47jF8s3D-E → CNjkRIWPaAu1yJUmIaX_q}/_middlewareManifest.js +0 -0
  142. /mage_ai/server/frontend_dist/_next/static/{O4HzlRY2U3Q47jF8s3D-E → CNjkRIWPaAu1yJUmIaX_q}/_ssgManifest.js +0 -0
  143. /mage_ai/server/frontend_dist_base_path_template/_next/static/{gJQ7p6K0VGDZzX1HXtRED → yJvL-3bfsNF3WCStZ10Dm}/_middlewareManifest.js +0 -0
  144. /mage_ai/server/frontend_dist_base_path_template/_next/static/{gJQ7p6K0VGDZzX1HXtRED → yJvL-3bfsNF3WCStZ10Dm}/_ssgManifest.js +0 -0
  145. {mage_ai-0.9.13.dist-info → mage_ai-0.9.14.dist-info}/LICENSE +0 -0
  146. {mage_ai-0.9.13.dist-info → mage_ai-0.9.14.dist-info}/WHEEL +0 -0
  147. {mage_ai-0.9.13.dist-info → mage_ai-0.9.14.dist-info}/entry_points.txt +0 -0
  148. {mage_ai-0.9.13.dist-info → mage_ai-0.9.14.dist-info}/top_level.txt +0 -0
mage_ai/ai/generator.py CHANGED
@@ -33,7 +33,7 @@ class Generator:
33
33
  elif use_case == LLMUseCase.GENERATE_PIPELINE_WITH_DESCRIPTION:
34
34
  from mage_ai.ai.llm_pipeline_wizard import LLMPipelineWizard
35
35
 
36
- return await LLMPipelineWizard().async_generate_pipeline_with_description(
36
+ return await LLMPipelineWizard().async_generate_pipeline_from_description(
37
37
  request.get('pipeline_description'),
38
38
  )
39
39
  elif use_case == LLMUseCase.GENERATE_COMMENT_FOR_CODE:
@@ -49,7 +49,7 @@ def generate_block_with_description(block_description: str):
49
49
 
50
50
  @app.command()
51
51
  def generate_pipeline_with_description(pipeline_description: str):
52
- print(asyncio.run(LLMPipelineWizard().async_generate_pipeline_with_description(
52
+ print(asyncio.run(LLMPipelineWizard().async_generate_pipeline_from_description(
53
53
  pipeline_description)))
54
54
 
55
55
 
@@ -2,6 +2,7 @@ import ast
2
2
  import asyncio
3
3
  import json
4
4
  import os
5
+ import re
5
6
  from typing import Dict
6
7
 
7
8
  import openai
@@ -53,23 +54,24 @@ PROMPT_TO_SPLIT_BLOCKS = """
53
54
  A BLOCK does one action either reading data from one data source, transforming the data from
54
55
  one format to another or exporting data into a data source.
55
56
  Based on the code description delimited by triple backticks, your task is to identify
56
- how many BLOCKS required and function for each BLOCK.
57
+ how many BLOCKS required, function for each BLOCK and upstream blocks between BLOCKs.
57
58
 
58
59
  Use the following format:
59
- BLOCK 1: <block function>
60
- BLOCK 2: <block function>
61
- BLOCK 3: <block function>
60
+ BLOCK 1: function: <block function>. upstream: <upstream blocks>
61
+ BLOCK 2: function: <block function>. upstream: <upstream blocks>
62
+ BLOCK 3: function: <block function>. upstream: <upstream blocks>
62
63
  ...
63
64
 
64
65
  Example:
65
66
  <code description>: ```
66
- Read data from MySQL, filter out rows with book_price > 100, and save data to BigQuery.
67
+ Read data from MySQL and Postgres, filter out rows with book_price > 100, and save data to BigQuery.
67
68
  ```
68
69
 
69
70
  Answer:
70
- BLOCK 1: load data from MySQL
71
- BLOCK 2: filter out rows with book_price > 100
72
- BLOCK 3: export data to BigQuery
71
+ BLOCK 1: function: load data from MySQL. upstream:
72
+ BLOCK 2: function: load data from Postgres. upstream:
73
+ BLOCK 3: function: filter out rows with book_price > 100. upstream: 1, 2
74
+ BLOCK 4: function: export data to BigQuery. upstream: 3
73
75
 
74
76
  <code description>: ```{code_description}```"""
75
77
  PROMPT_FOR_FUNCTION_COMMENT = """
@@ -81,6 +83,7 @@ Your task is to write comments for each function inside.
81
83
  The comment should follow Google Docstring format.
82
84
  Return your response in JSON format with function name as key and the comment as value.
83
85
  """
86
+ BLOCK_SPLIT_PATTERN = r"BLOCK\s+(\w+):\s+function:\s+(.*?)\.\s+upstream:\s*(.*?)$"
84
87
  TRANSFORMERS_FOLDER = 'transformers'
85
88
  CLASSIFICATION_FUNCTION_NAME = "classify_description"
86
89
  TEMPLATE_CLASSIFICATION_FUNCTION = [
@@ -197,7 +200,10 @@ class LLMPipelineWizard:
197
200
  function_args.get(DataSource.__name__))
198
201
  return block_type, block_language, pipeline_type, config
199
202
 
200
- async def async_generate_block_with_description(self, block_description: str) -> dict:
203
+ async def async_generate_block_with_description(
204
+ self,
205
+ block_description: str,
206
+ upstream_blocks: [str]) -> dict:
201
207
  messages = [{"role": "user", "content": block_description}]
202
208
  response = await openai.ChatCompletion.acreate(
203
209
  model="gpt-3.5-turbo-0613",
@@ -220,6 +226,7 @@ class LLMPipelineWizard:
220
226
  pipeline_type=pipeline_type,
221
227
  ),
222
228
  language=block_language,
229
+ upstream_blocks=upstream_blocks,
223
230
  )
224
231
  else:
225
232
  logger.error("Failed to interpret the description as a block template.")
@@ -238,11 +245,12 @@ class LLMPipelineWizard:
238
245
  async def __async_generate_blocks(self,
239
246
  block_dict: dict,
240
247
  block_id: int,
241
- block_description: str) -> dict:
242
- block = await self.async_generate_block_with_description(block_description)
248
+ block_description: str,
249
+ upstream_blocks: [str]) -> dict:
250
+ block = await self.async_generate_block_with_description(block_description, upstream_blocks)
243
251
  block_dict[block_id] = block
244
252
 
245
- async def async_generate_pipeline_with_description(self, pipeline_description: str) -> dict:
253
+ async def async_generate_pipeline_from_description(self, pipeline_description: str) -> dict:
246
254
  splited_block_descriptions = await self.__async_split_description_by_blocks(
247
255
  pipeline_description)
248
256
  blocks = {}
@@ -250,11 +258,17 @@ class LLMPipelineWizard:
250
258
  for line in splited_block_descriptions.strip().split('\n'):
251
259
  if line.startswith("BLOCK") and ":" in line:
252
260
  # Extract the block_id and block_description from the line
253
- raw_block_id, block_description = line.split(":", 1)
254
- block_id = raw_block_id.strip().split(" ")[-1]
255
- block_description = block_description.strip()
256
- block_tasks.append(
257
- self.__async_generate_blocks(blocks, block_id, block_description))
261
+ match = re.search(BLOCK_SPLIT_PATTERN, line)
262
+ if match:
263
+ block_id = match.group(1)
264
+ block_description = match.group(2).strip()
265
+ upstream_blocks = match.group(3).split(", ")
266
+ block_tasks.append(
267
+ self.__async_generate_blocks(
268
+ blocks,
269
+ block_id,
270
+ block_description,
271
+ upstream_blocks))
258
272
  await asyncio.gather(*block_tasks)
259
273
  return blocks
260
274
 
@@ -47,6 +47,7 @@ PipelineRunPolicy.allow_read(PipelineRunPresenter.default_attributes + [
47
47
  PipelineRunPolicy.allow_read(PipelineRunPresenter.default_attributes + [
48
48
  'block_runs',
49
49
  'block_runs_count',
50
+ 'completed_block_runs_count',
50
51
  'pipeline_schedule_name',
51
52
  'pipeline_schedule_token',
52
53
  'pipeline_schedule_type',
@@ -17,4 +17,7 @@ class BlockRunPresenter(BasePresenter):
17
17
  ]
18
18
 
19
19
  def present(self, **kwargs):
20
- return self.model.to_dict()
20
+ if isinstance(self.model, dict):
21
+ return self.model
22
+ else:
23
+ return self.model.to_dict()
@@ -27,6 +27,7 @@ class PipelineRunPresenter(BasePresenter):
27
27
  additional_attributes = [
28
28
  'block_runs',
29
29
  'block_runs_count',
30
+ 'completed_block_runs_count',
30
31
  'pipeline_schedule_name',
31
32
  'pipeline_schedule_token',
32
33
  'pipeline_schedule_type',
@@ -66,6 +67,7 @@ PipelineRunPresenter.register_format(
66
67
  PipelineRunPresenter.default_attributes + [
67
68
  'block_runs',
68
69
  'block_runs_count',
70
+ 'completed_block_runs_count',
69
71
  'pipeline_schedule_name',
70
72
  'pipeline_schedule_token',
71
73
  'pipeline_schedule_type',
@@ -1,7 +1,12 @@
1
+ from sqlalchemy.orm import aliased
2
+
1
3
  from mage_ai.api.resources.DatabaseResource import DatabaseResource
2
- from mage_ai.orchestration.db.models.schedules import BlockRun, PipelineRun, PipelineSchedule
3
4
  from mage_ai.orchestration.db import safe_db_query
4
- from sqlalchemy.orm import aliased
5
+ from mage_ai.orchestration.db.models.schedules import (
6
+ BlockRun,
7
+ PipelineRun,
8
+ PipelineSchedule,
9
+ )
5
10
 
6
11
 
7
12
  class BlockRunResource(DatabaseResource):
@@ -24,16 +29,17 @@ class BlockRunResource(DatabaseResource):
24
29
  pipeline_schedule_name,
25
30
  ) = tup
26
31
 
27
- block_run = BlockRun()
28
- block_run.block_uuid = block_uuid
29
- block_run.completed_at = completed_at
30
- block_run.created_at = created_at
31
- block_run.id = id
32
- block_run.pipeline_run_id = pipeline_run_id
33
- block_run.status = status
34
- block_run.updated_at = updated_at
35
- block_run.pipeline_schedule_id = pipeline_schedule_id
36
- block_run.pipeline_schedule_name = pipeline_schedule_name
32
+ block_run = dict(
33
+ block_uuid=block_uuid,
34
+ completed_at=completed_at,
35
+ created_at=created_at,
36
+ id=id,
37
+ pipeline_run_id=pipeline_run_id,
38
+ status=status,
39
+ updated_at=updated_at,
40
+ pipeline_schedule_id=pipeline_schedule_id,
41
+ pipeline_schedule_name=pipeline_schedule_name,
42
+ )
37
43
 
38
44
  block_runs.append(block_run)
39
45
 
@@ -265,7 +265,14 @@ class GitBranchResource(GenericResource):
265
265
  untracked_files: List[str],
266
266
  limit: int = None
267
267
  ) -> Dict:
268
- arr = modified_files + staged_files + untracked_files
268
+ arr = []
269
+
270
+ if modified_files and isinstance(modified_files, list):
271
+ arr += modified_files
272
+ if staged_files and isinstance(staged_files, list):
273
+ arr += staged_files
274
+ if untracked_files and isinstance(untracked_files, list):
275
+ arr += untracked_files
269
276
 
270
277
  if limit:
271
278
  arr = arr[:limit]
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ from typing import Dict, List
2
3
 
3
4
  from sqlalchemy import or_
4
5
  from sqlalchemy.orm import aliased
@@ -312,17 +313,28 @@ class PipelineResource(BaseResource):
312
313
  schedule.update(status=status)
313
314
 
314
315
  @safe_db_query
315
- def cancel_pipeline_runs(status, pipeline_uuid):
316
- pipeline_runs = (
317
- PipelineRun.
318
- query.
319
- filter(PipelineRun.pipeline_uuid == pipeline_uuid).
320
- filter(PipelineRun.status.in_([
321
- PipelineRun.PipelineRunStatus.INITIAL,
322
- PipelineRun.PipelineRunStatus.RUNNING,
323
- ]))
324
- )
325
- for pipeline_run in pipeline_runs:
316
+ def cancel_pipeline_runs(
317
+ pipeline_uuid: str = None,
318
+ pipeline_runs: List[Dict] = None,
319
+ ):
320
+ if pipeline_runs is not None:
321
+ pipeline_run_ids = [run.get('id') for run in pipeline_runs]
322
+ pipeline_runs_to_cancel = (
323
+ PipelineRun.
324
+ query.
325
+ filter(PipelineRun.id.in_(pipeline_run_ids))
326
+ )
327
+ else:
328
+ pipeline_runs_to_cancel = (
329
+ PipelineRun.
330
+ query.
331
+ filter(PipelineRun.pipeline_uuid == pipeline_uuid).
332
+ filter(PipelineRun.status.in_([
333
+ PipelineRun.PipelineRunStatus.INITIAL,
334
+ PipelineRun.PipelineRunStatus.RUNNING,
335
+ ]))
336
+ )
337
+ for pipeline_run in pipeline_runs_to_cancel:
326
338
  PipelineScheduler(pipeline_run).stop()
327
339
 
328
340
  def retry_pipeline_runs(pipeline_runs):
@@ -334,15 +346,19 @@ class PipelineResource(BaseResource):
334
346
 
335
347
  def _update_callback(resource):
336
348
  if status:
349
+ pipeline_runs = payload.get('pipeline_runs')
337
350
  if status in [
338
351
  ScheduleStatus.ACTIVE.value,
339
352
  ScheduleStatus.INACTIVE.value,
340
353
  ]:
341
354
  update_schedule_status(status, pipeline_uuid)
342
355
  elif status == PipelineRun.PipelineRunStatus.CANCELLED.value:
343
- cancel_pipeline_runs(status, pipeline_uuid)
344
- elif status == 'retry' and payload.get('pipeline_runs'):
345
- retry_pipeline_runs(payload.get('pipeline_runs'))
356
+ if pipeline_runs is None:
357
+ cancel_pipeline_runs(pipeline_uuid=pipeline_uuid)
358
+ else:
359
+ cancel_pipeline_runs(pipeline_runs=pipeline_runs)
360
+ elif status == 'retry' and pipeline_runs:
361
+ retry_pipeline_runs(pipeline_runs)
346
362
 
347
363
  self.on_update_callback = _update_callback
348
364
 
@@ -38,6 +38,7 @@ SOURCES = sorted([
38
38
  dict(name='Pipedrive'),
39
39
  dict(name='Postmark'),
40
40
  dict(name='Salesforce'),
41
+ dict(name='Sftp'),
41
42
  dict(name='Stripe'),
42
43
  dict(name='Twitter Ads'),
43
44
  dict(name='Zendesk'),
@@ -434,6 +434,24 @@ class Git:
434
434
  for url in remote.urls:
435
435
  if url.lower().startswith('https'):
436
436
  repository_names.append('/'.join(url.split('/')[-2:]).replace('.git', ''))
437
+
438
+ # Remove the token from the URL
439
+ # e.g. https://[user]:[token]@[netloc]
440
+ parts = url.split('@')
441
+
442
+ parts_arr = []
443
+ if len(parts) >= 2:
444
+ # https://[user]:[token]
445
+ parts2 = parts[0].split(':')
446
+ # ['https', '', 'user', 'token']
447
+ parts2[len(parts2) - 1] = '[token]'
448
+ parts_arr.append(':'.join(parts2))
449
+ parts_arr += parts[1:]
450
+ else:
451
+ parts_arr += parts
452
+
453
+ url = '@'.join(parts_arr)
454
+
437
455
  urls.append(url)
438
456
  except GitCommandError as err:
439
457
  print('WARNING (mage_ai.data_preparation.git.remotes):')
@@ -17,6 +17,7 @@ import pandas as pd
17
17
  import simplejson
18
18
  from jinja2 import Template
19
19
 
20
+ import mage_ai.data_preparation.decorators
20
21
  from mage_ai.cache.block import BlockCache
21
22
  from mage_ai.data_cleaner.shared.utils import is_geo_dataframe, is_spark_dataframe
22
23
  from mage_ai.data_preparation.logging.logger import DictLogger
@@ -1110,6 +1111,8 @@ class Block:
1110
1111
  ) -> List:
1111
1112
  if logging_tags is None:
1112
1113
  logging_tags = dict()
1114
+ if input_vars is None:
1115
+ input_vars = list()
1113
1116
 
1114
1117
  decorated_functions = []
1115
1118
  test_functions = []
@@ -1177,9 +1180,18 @@ class Block:
1177
1180
  block_uuid = self.replicated_block
1178
1181
  block_file_path = self.replicated_block_object.file_path
1179
1182
  spec = importlib.util.spec_from_file_location(
1180
- block_uuid, block_file_path,
1183
+ block_uuid,
1184
+ block_file_path,
1181
1185
  )
1182
1186
  module = importlib.util.module_from_spec(spec)
1187
+ # Set the decorators in the module in case they are not defined in the block
1188
+ # code
1189
+ setattr(
1190
+ module,
1191
+ self.type,
1192
+ getattr(mage_ai.data_preparation.decorators, self.type),
1193
+ )
1194
+ module.test = mage_ai.data_preparation.decorators.test
1183
1195
  spec.loader.exec_module(module)
1184
1196
  block_function_updated = getattr(module, block_function.__name__)
1185
1197
  self.module = module
@@ -501,9 +501,12 @@ def config_file_loader_and_configuration(
501
501
  database = kwargs.get('database') or profile.get('project')
502
502
  schema = profile.get('dataset')
503
503
 
504
- config_file_loader = ConfigFileLoader(config=dict(
504
+ config_file_loader_kwargs = dict(
505
505
  GOOGLE_SERVICE_ACC_KEY_FILEPATH=keyfile,
506
- ))
506
+ )
507
+ if profile.get('location'):
508
+ config_file_loader_kwargs['GOOGLE_LOCATION'] = profile.get('location')
509
+ config_file_loader = ConfigFileLoader(config=config_file_loader_kwargs)
507
510
  configuration = dict(
508
511
  data_provider=profile_type,
509
512
  data_provider_database=database,
@@ -122,7 +122,7 @@ class IntegrationBlock(Block):
122
122
  proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
123
123
 
124
124
  for line in proc.stdout:
125
- f.write(filter_out_config_values(line.decode(), config)),
125
+ f.write(line.decode()),
126
126
  print_log_from_line(
127
127
  line,
128
128
  config=config,
@@ -56,13 +56,23 @@ def group_and_hydrate_files(
56
56
  file_dicts: List[Dict],
57
57
  custom_template_class,
58
58
  ) -> List:
59
- groups = group_by(lambda x: os.path.join(*x.get('parent_names', [])), file_dicts)
59
+ def _func(x):
60
+ arr = ['']
60
61
 
61
- arr = []
62
+ if x:
63
+ parent_names = x.get('parent_names', []) or []
64
+ if parent_names and len(parent_names) >= 1:
65
+ arr = [str(parent_name) for parent_name in parent_names]
66
+
67
+ return os.path.join(*arr)
68
+
69
+ groups = group_by(_func, file_dicts)
70
+
71
+ custom_templates = []
62
72
 
63
73
  for template_uuid, _ in groups.items():
64
74
  custom_template = custom_template_class.load(template_uuid=template_uuid)
65
75
  if custom_template:
66
- arr.append(custom_template)
76
+ custom_templates.append(custom_template)
67
77
 
68
- return arr
78
+ return custom_templates
@@ -430,11 +430,14 @@ class Variable:
430
430
  df_output = data.copy()
431
431
  # Clean up data types since parquet doesn't support mixed data types
432
432
  for c in df_output.columns:
433
- c_dtype = df_output[c].dtype
433
+ df_col = df_output[c]
434
+ if type(df_col) is pd.DataFrame:
435
+ raise Exception(f'Please do not use duplicate column name: "{c}"')
436
+ c_dtype = df_col.dtype
434
437
  if not is_object_dtype(c_dtype):
435
438
  column_types[c] = str(c_dtype)
436
439
  else:
437
- series_non_null = df_output[c].dropna()
440
+ series_non_null = df_col.dropna()
438
441
  if len(series_non_null) > 0:
439
442
  coltype = type(series_non_null.iloc[0])
440
443
  if is_object_dtype(series_non_null.dtype):
@@ -434,6 +434,10 @@ class PipelineRun(BaseModel):
434
434
  def block_runs_count(self) -> int:
435
435
  return len(self.block_runs)
436
436
 
437
+ @property
438
+ def completed_block_runs_count(self) -> int:
439
+ return len(self.completed_block_runs)
440
+
437
441
  @property
438
442
  def execution_partition(self) -> str:
439
443
  if self.variables and self.variables.get('execution_partition'):
@@ -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.13'
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-ccc78f4c29a2a431.js" defer=""></script><script src="/_next/static/chunks/pages/_error-235304e5badb19eb.js" defer=""></script><script src="/_next/static/O4HzlRY2U3Q47jF8s3D-E/_buildManifest.js" defer=""></script><script src="/_next/static/O4HzlRY2U3Q47jF8s3D-E/_ssgManifest.js" defer=""></script><script src="/_next/static/O4HzlRY2U3Q47jF8s3D-E/_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":"O4HzlRY2U3Q47jF8s3D-E","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>
@@ -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-ccc78f4c29a2a431.js" defer=""></script><script src="/_next/static/chunks/pages/_error-235304e5badb19eb.js" defer=""></script><script src="/_next/static/O4HzlRY2U3Q47jF8s3D-E/_buildManifest.js" defer=""></script><script src="/_next/static/O4HzlRY2U3Q47jF8s3D-E/_ssgManifest.js" defer=""></script><script src="/_next/static/O4HzlRY2U3Q47jF8s3D-E/_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":"O4HzlRY2U3Q47jF8s3D-E","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>