tinybird 0.0.1.dev47__py3-none-any.whl → 0.0.1.dev49__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 tinybird might be problematic. Click here for more details.
- tinybird/client.py +1 -6
- tinybird/prompts.py +8 -61
- tinybird/tb/__cli__.py +2 -2
- tinybird/tb/cli.py +0 -1
- tinybird/tb/modules/build.py +22 -9
- tinybird/tb/modules/cli.py +18 -63
- tinybird/tb/modules/create.py +17 -12
- tinybird/tb/modules/datafile/build.py +1 -2
- tinybird/tb/modules/datafile/common.py +8 -10
- tinybird/tb/modules/datasource.py +33 -0
- tinybird/tb/modules/deployment.py +65 -14
- tinybird/tb/modules/feedback_manager.py +1 -3
- tinybird/tb/modules/local_common.py +8 -12
- tinybird/tb/modules/login.py +1 -1
- tinybird/tb/modules/mock.py +2 -2
- tinybird/tb/modules/project.py +2 -2
- tinybird/tb/modules/shell.py +50 -17
- tinybird/tb/modules/test.py +9 -8
- tinybird/tb/modules/workspace.py +1 -1
- {tinybird-0.0.1.dev47.dist-info → tinybird-0.0.1.dev49.dist-info}/METADATA +1 -1
- {tinybird-0.0.1.dev47.dist-info → tinybird-0.0.1.dev49.dist-info}/RECORD +24 -25
- {tinybird-0.0.1.dev47.dist-info → tinybird-0.0.1.dev49.dist-info}/top_level.txt +1 -0
- tinybird/tb/modules/update.py +0 -182
- {tinybird-0.0.1.dev47.dist-info → tinybird-0.0.1.dev49.dist-info}/WHEEL +0 -0
- {tinybird-0.0.1.dev47.dist-info → tinybird-0.0.1.dev49.dist-info}/entry_points.txt +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
+
import sys
|
|
3
4
|
import time
|
|
4
5
|
from datetime import datetime
|
|
5
6
|
from pathlib import Path
|
|
@@ -14,7 +15,7 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
|
14
15
|
from tinybird.tb.modules.project import Project
|
|
15
16
|
|
|
16
17
|
|
|
17
|
-
def promote_deployment(host: Optional[str], headers: dict) -> None:
|
|
18
|
+
def promote_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
18
19
|
TINYBIRD_API_URL = f"{host}/v1/deployments"
|
|
19
20
|
r = requests.get(TINYBIRD_API_URL, headers=headers)
|
|
20
21
|
result = r.json()
|
|
@@ -23,11 +24,11 @@ def promote_deployment(host: Optional[str], headers: dict) -> None:
|
|
|
23
24
|
deployments = result.get("deployments")
|
|
24
25
|
if not deployments:
|
|
25
26
|
click.echo(FeedbackManager.error(message="No deployments found"))
|
|
26
|
-
|
|
27
|
+
sys.exit(1)
|
|
27
28
|
|
|
28
29
|
if len(deployments) < 2:
|
|
29
30
|
click.echo(FeedbackManager.error(message="Only one deployment found"))
|
|
30
|
-
|
|
31
|
+
sys.exit(1)
|
|
31
32
|
|
|
32
33
|
last_deployment, candidate_deployment = deployments[0], deployments[1]
|
|
33
34
|
|
|
@@ -36,7 +37,7 @@ def promote_deployment(host: Optional[str], headers: dict) -> None:
|
|
|
36
37
|
deploy_errors = candidate_deployment.get("errors", [])
|
|
37
38
|
for deploy_error in deploy_errors:
|
|
38
39
|
click.echo(FeedbackManager.error(message=f"* {deploy_error}"))
|
|
39
|
-
|
|
40
|
+
sys.exit(1)
|
|
40
41
|
|
|
41
42
|
if candidate_deployment.get("live"):
|
|
42
43
|
click.echo(FeedbackManager.error(message="Candidate deployment is already live"))
|
|
@@ -55,10 +56,23 @@ def promote_deployment(host: Optional[str], headers: dict) -> None:
|
|
|
55
56
|
result = r.json()
|
|
56
57
|
logging.debug(json.dumps(result, indent=2))
|
|
57
58
|
|
|
59
|
+
if wait:
|
|
60
|
+
while True:
|
|
61
|
+
TINYBIRD_API_URL = f"{host}/v1/deployments/{last_deployment.get('id')}"
|
|
62
|
+
r = requests.get(TINYBIRD_API_URL, headers=headers)
|
|
63
|
+
result = r.json()
|
|
64
|
+
logging.debug(json.dumps(result, indent=2))
|
|
65
|
+
|
|
66
|
+
last_deployment = result.get("deployment")
|
|
67
|
+
if last_deployment.get("status") == "deleted":
|
|
68
|
+
break
|
|
69
|
+
|
|
70
|
+
time.sleep(5)
|
|
71
|
+
|
|
58
72
|
click.echo(FeedbackManager.success(message="Deployment promoted successfully"))
|
|
59
73
|
|
|
60
74
|
|
|
61
|
-
def rollback_deployment(host: Optional[str], headers: dict) -> None:
|
|
75
|
+
def rollback_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
62
76
|
TINYBIRD_API_URL = f"{host}/v1/deployments"
|
|
63
77
|
r = requests.get(TINYBIRD_API_URL, headers=headers)
|
|
64
78
|
result = r.json()
|
|
@@ -99,6 +113,18 @@ def rollback_deployment(host: Optional[str], headers: dict) -> None:
|
|
|
99
113
|
result = r.json()
|
|
100
114
|
logging.debug(json.dumps(result, indent=2))
|
|
101
115
|
|
|
116
|
+
if wait:
|
|
117
|
+
while True:
|
|
118
|
+
TINYBIRD_API_URL = f"{host}/v1/deployments/{current_deployment.get('id')}"
|
|
119
|
+
r = requests.get(TINYBIRD_API_URL, headers=headers)
|
|
120
|
+
result = r.json()
|
|
121
|
+
logging.debug(json.dumps(result, indent=2))
|
|
122
|
+
|
|
123
|
+
current_deployment = result.get("deployment")
|
|
124
|
+
if current_deployment.get("status") == "deleted":
|
|
125
|
+
break
|
|
126
|
+
time.sleep(5)
|
|
127
|
+
|
|
102
128
|
click.echo(FeedbackManager.success(message="Deployment rolled back successfully"))
|
|
103
129
|
|
|
104
130
|
|
|
@@ -165,7 +191,13 @@ def deployment_ls(ctx: click.Context) -> None:
|
|
|
165
191
|
|
|
166
192
|
@deployment_group.command(name="promote")
|
|
167
193
|
@click.pass_context
|
|
168
|
-
|
|
194
|
+
@click.option(
|
|
195
|
+
"--wait/--no-wait",
|
|
196
|
+
is_flag=True,
|
|
197
|
+
default=False,
|
|
198
|
+
help="Wait for deploy to finish. Disabled by default.",
|
|
199
|
+
)
|
|
200
|
+
def deployment_promote(ctx: click.Context, wait: bool) -> None:
|
|
169
201
|
"""
|
|
170
202
|
Promote last deploy to ready and remove old one.
|
|
171
203
|
"""
|
|
@@ -174,12 +206,18 @@ def deployment_promote(ctx: click.Context) -> None:
|
|
|
174
206
|
TINYBIRD_API_KEY = client.token
|
|
175
207
|
HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
|
|
176
208
|
|
|
177
|
-
promote_deployment(client.host, HEADERS)
|
|
209
|
+
promote_deployment(client.host, HEADERS, wait=wait)
|
|
178
210
|
|
|
179
211
|
|
|
180
212
|
@deployment_group.command(name="rollback")
|
|
181
213
|
@click.pass_context
|
|
182
|
-
|
|
214
|
+
@click.option(
|
|
215
|
+
"--wait/--no-wait",
|
|
216
|
+
is_flag=True,
|
|
217
|
+
default=False,
|
|
218
|
+
help="Wait for deploy to finish. Disabled by default.",
|
|
219
|
+
)
|
|
220
|
+
def deployment_rollback(ctx: click.Context, wait: bool) -> None:
|
|
183
221
|
"""
|
|
184
222
|
Rollback to the previous deployment.
|
|
185
223
|
"""
|
|
@@ -188,7 +226,7 @@ def deployment_rollback(ctx: click.Context) -> None:
|
|
|
188
226
|
TINYBIRD_API_KEY = client.token
|
|
189
227
|
HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
|
|
190
228
|
|
|
191
|
-
rollback_deployment(client.host, HEADERS)
|
|
229
|
+
rollback_deployment(client.host, HEADERS, wait=wait)
|
|
192
230
|
|
|
193
231
|
|
|
194
232
|
@cli.command(name="deploy", hidden=True)
|
|
@@ -248,6 +286,12 @@ def create_deployment(ctx: click.Context, wait: bool, auto: bool) -> None:
|
|
|
248
286
|
if deploy_result == "success":
|
|
249
287
|
click.echo(FeedbackManager.success(message="Deployment submitted successfully"))
|
|
250
288
|
deployment = result.get("deployment")
|
|
289
|
+
feedback = deployment.get("feedback", [])
|
|
290
|
+
for f in feedback:
|
|
291
|
+
click.echo(
|
|
292
|
+
FeedbackManager.warning(message=f"△ {f.get('level')}: {f.get('resource')}: {f.get('message')}")
|
|
293
|
+
)
|
|
294
|
+
|
|
251
295
|
elif deploy_result == "failed":
|
|
252
296
|
click.echo(FeedbackManager.error(message="Deployment failed"))
|
|
253
297
|
deploy_errors = result.get("errors")
|
|
@@ -264,9 +308,11 @@ def create_deployment(ctx: click.Context, wait: bool, auto: bool) -> None:
|
|
|
264
308
|
for fd in fds:
|
|
265
309
|
fd.close()
|
|
266
310
|
|
|
311
|
+
if not deployment:
|
|
312
|
+
sys.exit(1)
|
|
313
|
+
|
|
267
314
|
if deployment and wait:
|
|
268
|
-
while
|
|
269
|
-
time.sleep(5)
|
|
315
|
+
while True:
|
|
270
316
|
TINYBIRD_API_URL = f"{client.host}/v1/deployments/{deployment.get('id')}"
|
|
271
317
|
r = requests.get(TINYBIRD_API_URL, headers=HEADERS)
|
|
272
318
|
result = r.json()
|
|
@@ -281,10 +327,15 @@ def create_deployment(ctx: click.Context, wait: bool, auto: bool) -> None:
|
|
|
281
327
|
|
|
282
328
|
if auto:
|
|
283
329
|
click.echo(FeedbackManager.error(message="Rolling back deployment"))
|
|
284
|
-
rollback_deployment(client.host, HEADERS)
|
|
285
|
-
|
|
330
|
+
rollback_deployment(client.host, HEADERS, wait=wait)
|
|
331
|
+
sys.exit(1)
|
|
332
|
+
|
|
333
|
+
if deployment.get("status") == "data_ready":
|
|
334
|
+
break
|
|
335
|
+
|
|
336
|
+
time.sleep(5)
|
|
286
337
|
|
|
287
338
|
click.echo(FeedbackManager.success(message="Deployment is ready"))
|
|
288
339
|
|
|
289
340
|
if auto:
|
|
290
|
-
promote_deployment(client.host, HEADERS)
|
|
341
|
+
promote_deployment(client.host, HEADERS, wait=wait)
|
|
@@ -73,9 +73,7 @@ class FeedbackManager:
|
|
|
73
73
|
error_exception = error_exception("{error}")
|
|
74
74
|
simple_error_exception = simple_error_message("{error}")
|
|
75
75
|
error_exception_trace = error_message("{error}\n** Trace:\n{trace}")
|
|
76
|
-
error_notoken = error_message(
|
|
77
|
-
"No auth token provided. Run 'tb auth' to configure them or re-run the command passing the --token param (example: tb --token <the_token> datasource ls)."
|
|
78
|
-
)
|
|
76
|
+
error_notoken = error_message("This action requires authentication. Run 'tb login' first")
|
|
79
77
|
error_auth_config = error_message("{config_file} does not exist")
|
|
80
78
|
error_file_config = error_message("{config_file} can't be written, check write permissions on this folder")
|
|
81
79
|
error_load_file_config = error_message("{config_file} can't be loaded, remove it and run the command again")
|
|
@@ -4,7 +4,7 @@ import os
|
|
|
4
4
|
|
|
5
5
|
import requests
|
|
6
6
|
|
|
7
|
-
from tinybird.client import TinyB
|
|
7
|
+
from tinybird.client import AuthNoTokenException, TinyB
|
|
8
8
|
from tinybird.tb.modules.config import CLIConfig
|
|
9
9
|
from tinybird.tb.modules.exceptions import CLIException
|
|
10
10
|
|
|
@@ -40,27 +40,23 @@ async def get_tinybird_local_config(path: str, build: bool = False) -> CLIConfig
|
|
|
40
40
|
if path:
|
|
41
41
|
folder_hash = hashlib.sha256(path.encode()).hexdigest()
|
|
42
42
|
user_client = config.get_client(host=TB_LOCAL_HOST, token=user_token)
|
|
43
|
-
ws_name = f"Tinybird_Local_Build_{folder_hash}" if build else
|
|
43
|
+
ws_name = f"Tinybird_Local_Build_{folder_hash}" if build else config.get("name")
|
|
44
|
+
if not ws_name:
|
|
45
|
+
raise AuthNoTokenException()
|
|
46
|
+
|
|
44
47
|
logging.debug(f"Workspace used for build: {ws_name}")
|
|
45
48
|
|
|
46
49
|
user_workspaces = requests.get(f"{TB_LOCAL_HOST}/v0/user/workspaces?token={user_token}").json()
|
|
47
|
-
local_workspaces = (
|
|
48
|
-
[ws for ws in user_workspaces["workspaces"] if ws["name"].startswith(ws_name)]
|
|
49
|
-
if user_workspaces.get("workspaces")
|
|
50
|
-
else []
|
|
51
|
-
)
|
|
52
|
-
local_workspaces = sorted(local_workspaces, key=lambda x: x["name"])
|
|
50
|
+
local_workspaces = user_workspaces.get("workspaces", [])
|
|
53
51
|
|
|
54
|
-
ws = None
|
|
55
|
-
if len(local_workspaces) > 0:
|
|
56
|
-
ws = local_workspaces[-1]
|
|
52
|
+
ws = next((ws for ws in local_workspaces if ws["name"] == ws_name), None)
|
|
57
53
|
|
|
58
54
|
if not ws:
|
|
59
55
|
await user_client.create_workspace(ws_name, template=None)
|
|
60
56
|
user_workspaces = requests.get(f"{TB_LOCAL_HOST}/v0/user/workspaces?token={user_token}").json()
|
|
61
57
|
ws = next((ws for ws in user_workspaces["workspaces"] if ws["name"] == ws_name), None)
|
|
62
58
|
if not ws:
|
|
63
|
-
raise
|
|
59
|
+
raise AuthNoTokenException()
|
|
64
60
|
|
|
65
61
|
ws_token = ws["token"]
|
|
66
62
|
|
tinybird/tb/modules/login.py
CHANGED
|
@@ -121,7 +121,7 @@ async def login(host: str, workspace: str):
|
|
|
121
121
|
"""Authenticate using the browser."""
|
|
122
122
|
auth_event = threading.Event()
|
|
123
123
|
auth_code = [None] # Using a list to store the code, as it's mutable
|
|
124
|
-
host = host or "https://api.tinybird.co"
|
|
124
|
+
host = host or "https://api.wadus2.gcp.tinybird.co"
|
|
125
125
|
|
|
126
126
|
def auth_callback(code):
|
|
127
127
|
auth_code[0] = code
|
tinybird/tb/modules/mock.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import Optional
|
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
7
|
|
|
8
|
+
from tinybird.client import TinyB
|
|
8
9
|
from tinybird.prompts import mock_prompt
|
|
9
10
|
from tinybird.tb.modules.cli import cli
|
|
10
11
|
from tinybird.tb.modules.common import CLIException, check_user_token_with_client, coro
|
|
@@ -13,7 +14,6 @@ from tinybird.tb.modules.datafile.fixture import build_fixture_name, persist_fix
|
|
|
13
14
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
14
15
|
from tinybird.tb.modules.llm import LLM
|
|
15
16
|
from tinybird.tb.modules.llm_utils import extract_xml
|
|
16
|
-
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
17
17
|
from tinybird.tb.modules.project import Project
|
|
18
18
|
|
|
19
19
|
|
|
@@ -40,6 +40,7 @@ async def mock(ctx: click.Context, datasource: str, rows: int, prompt: str, skip
|
|
|
40
40
|
"""
|
|
41
41
|
|
|
42
42
|
try:
|
|
43
|
+
tb_client: TinyB = ctx.ensure_object(dict)["client"]
|
|
43
44
|
project: Project = ctx.ensure_object(dict)["project"]
|
|
44
45
|
datasource_path = Path(datasource)
|
|
45
46
|
datasource_name = datasource
|
|
@@ -76,7 +77,6 @@ async def mock(ctx: click.Context, datasource: str, rows: int, prompt: str, skip
|
|
|
76
77
|
click.echo(FeedbackManager.error(message="This action requires authentication. Run 'tb login' first."))
|
|
77
78
|
return
|
|
78
79
|
llm = LLM(user_token=user_token, host=user_client.host)
|
|
79
|
-
tb_client = await get_tinybird_local_client(folder)
|
|
80
80
|
prompt = f"<datasource_schema>{datasource_content}</datasource_schema>\n<user_input>{prompt}</user_input>"
|
|
81
81
|
iterations = 0
|
|
82
82
|
history = ""
|
tinybird/tb/modules/project.py
CHANGED
|
@@ -40,11 +40,11 @@ class Project:
|
|
|
40
40
|
|
|
41
41
|
@property
|
|
42
42
|
def datasources(self) -> List[str]:
|
|
43
|
-
return [Path(f).stem for f in glob.glob(f"{self.path}/**/*.datasource", recursive=True)]
|
|
43
|
+
return sorted([Path(f).stem for f in glob.glob(f"{self.path}/**/*.datasource", recursive=True)])
|
|
44
44
|
|
|
45
45
|
@property
|
|
46
46
|
def pipes(self) -> List[str]:
|
|
47
|
-
return [Path(f).stem for f in glob.glob(f"{self.path}/**/*.pipe", recursive=True)]
|
|
47
|
+
return sorted([Path(f).stem for f in glob.glob(f"{self.path}/**/*.pipe", recursive=True)])
|
|
48
48
|
|
|
49
49
|
def get_pipe_datafile(self, filename: str) -> Optional[Datafile]:
|
|
50
50
|
try:
|
tinybird/tb/modules/shell.py
CHANGED
|
@@ -69,14 +69,27 @@ class DynamicCompleter(Completer):
|
|
|
69
69
|
if not words:
|
|
70
70
|
return
|
|
71
71
|
|
|
72
|
-
# If we
|
|
73
|
-
if
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
# If we're after FROM, suggest filtered datasources and pipes
|
|
73
|
+
if "from" in words:
|
|
74
|
+
from_index = words.index("from")
|
|
75
|
+
# Check if we're typing after FROM
|
|
76
|
+
if len(words) > from_index + 1:
|
|
77
|
+
current_word = words[-1].lower()
|
|
78
|
+
# Suggest filtered datasources and pipes based on current word
|
|
79
|
+
for x in self.project.datasources:
|
|
80
|
+
if current_word in x.lower():
|
|
81
|
+
yield Completion(
|
|
82
|
+
x, start_position=-len(current_word), display=x, style="class:completion.datasource"
|
|
83
|
+
)
|
|
84
|
+
for x in self.project.pipes:
|
|
85
|
+
if current_word in x.lower():
|
|
86
|
+
yield Completion(x, start_position=-len(current_word), display=x, style="class:completion.pipe")
|
|
87
|
+
else:
|
|
88
|
+
# Just typed FROM, show all datasources and pipes
|
|
89
|
+
for x in self.project.datasources:
|
|
90
|
+
yield Completion(x, start_position=0, display=x, style="class:completion.datasource")
|
|
91
|
+
for x in self.project.pipes:
|
|
92
|
+
yield Completion(x, start_position=0, display=x, style="class:completion.pipe")
|
|
80
93
|
return
|
|
81
94
|
|
|
82
95
|
# If we're starting a query, suggest SQL keywords
|
|
@@ -88,13 +101,20 @@ class DynamicCompleter(Completer):
|
|
|
88
101
|
)
|
|
89
102
|
|
|
90
103
|
def _handle_mock_completions(self, words: List[str]):
|
|
91
|
-
if len(words) == 1:
|
|
104
|
+
if len(words) == 1 or len(words) == 2:
|
|
92
105
|
# After 'mock', show datasources
|
|
93
|
-
|
|
94
|
-
|
|
106
|
+
current_word = words[-1]
|
|
107
|
+
for cmd in self.project.datasources:
|
|
108
|
+
if current_word in cmd.lower():
|
|
109
|
+
yield Completion(
|
|
110
|
+
cmd,
|
|
111
|
+
start_position=-len(current_word) if current_word else 0,
|
|
112
|
+
display=cmd,
|
|
113
|
+
style="class:completion.datasource",
|
|
114
|
+
)
|
|
95
115
|
return
|
|
96
116
|
|
|
97
|
-
if len(words) ==
|
|
117
|
+
if len(words) == 3 or len(words) == 4:
|
|
98
118
|
# After datasource or after a flag value, show available flags
|
|
99
119
|
available_flags = [f for f in self.mock_flags if f not in words]
|
|
100
120
|
for flag in available_flags:
|
|
@@ -113,9 +133,16 @@ class DynamicCompleter(Completer):
|
|
|
113
133
|
for cmd in self.test_commands:
|
|
114
134
|
yield Completion(cmd, start_position=0, display=cmd, style="class:completion.cmd")
|
|
115
135
|
return
|
|
116
|
-
elif len(words) == 2:
|
|
136
|
+
elif len(words) == 2 or len(words) == 3:
|
|
137
|
+
current_word = words[-1]
|
|
117
138
|
for cmd in self.project.pipes:
|
|
118
|
-
|
|
139
|
+
if current_word in cmd.lower():
|
|
140
|
+
yield Completion(
|
|
141
|
+
cmd,
|
|
142
|
+
start_position=-len(current_word) if current_word else 0,
|
|
143
|
+
display=cmd,
|
|
144
|
+
style="class:completion.pipe",
|
|
145
|
+
)
|
|
119
146
|
return
|
|
120
147
|
|
|
121
148
|
def _yield_static_commands(self, current_word: str):
|
|
@@ -129,7 +156,7 @@ class DynamicCompleter(Completer):
|
|
|
129
156
|
)
|
|
130
157
|
|
|
131
158
|
for cmd in self.project.datasources:
|
|
132
|
-
if cmd.
|
|
159
|
+
if current_word in cmd.lower():
|
|
133
160
|
yield Completion(
|
|
134
161
|
cmd,
|
|
135
162
|
start_position=-len(current_word) if current_word else 0,
|
|
@@ -138,7 +165,7 @@ class DynamicCompleter(Completer):
|
|
|
138
165
|
)
|
|
139
166
|
|
|
140
167
|
for cmd in self.project.pipes:
|
|
141
|
-
if cmd.
|
|
168
|
+
if current_word in cmd.lower():
|
|
142
169
|
yield Completion(
|
|
143
170
|
cmd,
|
|
144
171
|
start_position=-len(current_word) if current_word else 0,
|
|
@@ -245,7 +272,7 @@ class Shell:
|
|
|
245
272
|
click.echo(FeedbackManager.error(message=f"'tb {arg}' command is not available in watch mode"))
|
|
246
273
|
|
|
247
274
|
def handle_mock(self, arg):
|
|
248
|
-
subprocess.run(f"tb --build --folder {self.project.folder} mock {arg}", shell=True, text=True)
|
|
275
|
+
subprocess.run(f"tb --build --folder {self.project.folder} mock {arg} --skip", shell=True, text=True)
|
|
249
276
|
|
|
250
277
|
def handle_tb(self, arg):
|
|
251
278
|
click.echo("")
|
|
@@ -259,6 +286,9 @@ class Shell:
|
|
|
259
286
|
elif arg.startswith("mock"):
|
|
260
287
|
self.handle_mock(arg)
|
|
261
288
|
else:
|
|
289
|
+
need_skip = ("mock", "test create", "create")
|
|
290
|
+
if any(arg.startswith(cmd) for cmd in need_skip):
|
|
291
|
+
arg = f"{arg} --skip"
|
|
262
292
|
subprocess.run(f"tb --build --folder {self.project.folder} {arg}", shell=True, text=True)
|
|
263
293
|
|
|
264
294
|
def default(self, argline):
|
|
@@ -271,6 +301,9 @@ class Shell:
|
|
|
271
301
|
elif len(arg.split()) == 1 and arg in self.project.pipes + self.project.datasources:
|
|
272
302
|
self.run_sql(f"select * from {arg}")
|
|
273
303
|
else:
|
|
304
|
+
need_skip = ("mock", "test create", "create")
|
|
305
|
+
if any(arg.startswith(cmd) for cmd in need_skip):
|
|
306
|
+
arg = f"{arg} --skip"
|
|
274
307
|
subprocess.run(f"tb --build --folder {self.project.folder} {arg}", shell=True, text=True)
|
|
275
308
|
|
|
276
309
|
def run_sql(self, query, rows_limit=20):
|
tinybird/tb/modules/test.py
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import difflib
|
|
7
7
|
import glob
|
|
8
|
-
import os
|
|
9
8
|
import urllib.parse
|
|
10
9
|
from pathlib import Path
|
|
11
10
|
from typing import Any, Dict, List, Optional, Tuple
|
|
@@ -14,6 +13,7 @@ import click
|
|
|
14
13
|
import yaml
|
|
15
14
|
from requests import Response
|
|
16
15
|
|
|
16
|
+
from tinybird.client import TinyB
|
|
17
17
|
from tinybird.prompts import test_create_prompt
|
|
18
18
|
from tinybird.tb.modules.cli import cli
|
|
19
19
|
from tinybird.tb.modules.common import coro
|
|
@@ -22,7 +22,6 @@ from tinybird.tb.modules.exceptions import CLIException
|
|
|
22
22
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
23
23
|
from tinybird.tb.modules.llm import LLM
|
|
24
24
|
from tinybird.tb.modules.llm_utils import extract_xml, parse_xml
|
|
25
|
-
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
26
25
|
from tinybird.tb.modules.project import Project
|
|
27
26
|
|
|
28
27
|
yaml.SafeDumper.org_represent_str = yaml.SafeDumper.represent_str # type: ignore[attr-defined]
|
|
@@ -79,6 +78,7 @@ async def test_create(ctx: click.Context, name_or_filename: str, prompt: str, sk
|
|
|
79
78
|
Create a test for an existing pipe
|
|
80
79
|
"""
|
|
81
80
|
project: Project = ctx.ensure_object(dict)["project"]
|
|
81
|
+
client: TinyB = ctx.ensure_object(dict)["client"]
|
|
82
82
|
root_path = Path(project.folder)
|
|
83
83
|
folder = project.folder
|
|
84
84
|
try:
|
|
@@ -102,7 +102,6 @@ async def test_create(ctx: click.Context, name_or_filename: str, prompt: str, sk
|
|
|
102
102
|
pipe_path = root_path / pipe_path
|
|
103
103
|
pipe_content = pipe_path.read_text()
|
|
104
104
|
|
|
105
|
-
client = await get_tinybird_local_client(folder, build=True)
|
|
106
105
|
pipe = await client._req(f"/v0/pipes/{pipe_name}")
|
|
107
106
|
parameters = set([param["name"] for node in pipe["nodes"] for param in node["params"]])
|
|
108
107
|
|
|
@@ -200,10 +199,11 @@ async def test_create(ctx: click.Context, name_or_filename: str, prompt: str, sk
|
|
|
200
199
|
type=click.Path(exists=True, file_okay=False),
|
|
201
200
|
help="Folder where datafiles will be placed",
|
|
202
201
|
)
|
|
202
|
+
@click.pass_context
|
|
203
203
|
@coro
|
|
204
|
-
async def test_update(pipe: str, folder: str) -> None:
|
|
204
|
+
async def test_update(ctx: click.Context, pipe: str, folder: str) -> None:
|
|
205
205
|
try:
|
|
206
|
-
client =
|
|
206
|
+
client: TinyB = ctx.ensure_object(dict)["client"]
|
|
207
207
|
pipe_tests_path = Path(pipe)
|
|
208
208
|
pipe_name = pipe
|
|
209
209
|
if pipe_tests_path.suffix == ".yaml":
|
|
@@ -252,10 +252,11 @@ async def test_update(pipe: str, folder: str) -> None:
|
|
|
252
252
|
type=click.Path(exists=True, file_okay=False),
|
|
253
253
|
help="Folder where tests will be placed",
|
|
254
254
|
)
|
|
255
|
+
@click.pass_context
|
|
255
256
|
@coro
|
|
256
|
-
async def run_tests(name: Tuple[str, ...], folder: str) -> None:
|
|
257
|
+
async def run_tests(ctx: click.Context, name: Tuple[str, ...], folder: str) -> None:
|
|
257
258
|
click.echo(FeedbackManager.highlight(message="\n» Running tests"))
|
|
258
|
-
client =
|
|
259
|
+
client: TinyB = ctx.ensure_object(dict)["client"]
|
|
259
260
|
paths = [Path(n) for n in name]
|
|
260
261
|
endpoints = [f"./tests/{p.stem}.yaml" for p in paths]
|
|
261
262
|
test_files: List[str] = endpoints if len(endpoints) > 0 else glob.glob("./tests/**/*.y*ml", recursive=True)
|
|
@@ -311,7 +312,7 @@ async def run_tests(name: Tuple[str, ...], folder: str) -> None:
|
|
|
311
312
|
click.echo(FeedbackManager.success(message=f"\n✓ {test_count}/{test_count} passed"))
|
|
312
313
|
|
|
313
314
|
|
|
314
|
-
async def get_pipe_data(client, pipe_name: str, test_params: str) -> Response:
|
|
315
|
+
async def get_pipe_data(client: TinyB, pipe_name: str, test_params: str) -> Response:
|
|
315
316
|
pipe = await client._req(f"/v0/pipes/{pipe_name}")
|
|
316
317
|
output_node = next(
|
|
317
318
|
(node for node in pipe["nodes"] if node["node_type"] != "default" and node["node_type"] != "standard"),
|
tinybird/tb/modules/workspace.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
tinybird/__cli__.py,sha256=esPl5QDTzuQgHe5FuxWLm-fURFigGGwjnYLh9GuWUw4,232
|
|
2
|
-
tinybird/client.py,sha256=
|
|
2
|
+
tinybird/client.py,sha256=W5Xttnz0bzwqqVGNJJs-4Ca2AbtCMh3URuQYPJ5APsE,52013
|
|
3
3
|
tinybird/config.py,sha256=ENRNyEMXHj_P882o31iFz0hTveziLabVRrxiWE5RRBE,6233
|
|
4
4
|
tinybird/connectors.py,sha256=7Gjms7b5MAaBFGi3xytsJurCylprONpFcYrzp4Fw2Rc,15241
|
|
5
5
|
tinybird/context.py,sha256=A3GBApac9xO6hrAMJ1s9dMrI_ou9aKF84CdEjtPddMk,1417
|
|
6
6
|
tinybird/datatypes.py,sha256=XNypumfqNjsvLJ5iNXnbVHRvAJe0aQwI3lS6Cxox-e0,10979
|
|
7
7
|
tinybird/feedback_manager.py,sha256=g1r9NcFfKXdk_13soaiTZLvdoUGleVfawl6Yfj3zmRw,67823
|
|
8
8
|
tinybird/git_settings.py,sha256=Sw_8rGmribEFJ4Z_6idrVytxpFYk7ez8ei0qHULzs3E,3934
|
|
9
|
-
tinybird/prompts.py,sha256=
|
|
9
|
+
tinybird/prompts.py,sha256=unaqHksayhVtxFaTTxuL6Dftb1IM9vQncXtpTI3pxuY,30545
|
|
10
10
|
tinybird/sql.py,sha256=LBi74GxhNAYTb6m2-KNGpAkguSKh7rcvBbERbE7nalA,46195
|
|
11
11
|
tinybird/sql_template.py,sha256=GmMLAI10MTqjQo9qztuQHLRWs67teozsWDxUBdvkAn4,93668
|
|
12
12
|
tinybird/sql_template_fmt.py,sha256=KUHdj5rYCYm_rKKdXYSJAE9vIyXUQLB0YSZnUXHeBlY,10196
|
|
@@ -15,48 +15,47 @@ tinybird/syncasync.py,sha256=IPnOx6lMbf9SNddN1eBtssg8vCLHMt76SuZ6YNYm-Yk,27761
|
|
|
15
15
|
tinybird/tornado_template.py,sha256=FL85SMPq2dH4JqKovmSbaolGdEzwOO91NqOzqXo2Qr0,41863
|
|
16
16
|
tinybird/ch_utils/constants.py,sha256=aYvg2C_WxYWsnqPdZB1ZFoIr8ZY-XjUXYyHKE9Ansj0,3890
|
|
17
17
|
tinybird/ch_utils/engine.py,sha256=OXkBhlzGjZotjD0vaT-rFIbSGV4tpiHxE8qO_ip0SyQ,40454
|
|
18
|
-
tinybird/tb/__cli__.py,sha256=
|
|
19
|
-
tinybird/tb/cli.py,sha256=
|
|
18
|
+
tinybird/tb/__cli__.py,sha256=Yocwg57d8BTpRpM9BAwbi73DJuatECKd9hhtsD5-Y3U,251
|
|
19
|
+
tinybird/tb/cli.py,sha256=FD1pfbzu9YHJHEG6Vtn_EwPLTYhwqw-I6AxXeTaRHU8,926
|
|
20
20
|
tinybird/tb/modules/auth.py,sha256=EzRWFmwRkXNhUmRaruEVFLdkbUg8xMSix0cAWl5D4Jg,9029
|
|
21
|
-
tinybird/tb/modules/build.py,sha256=
|
|
21
|
+
tinybird/tb/modules/build.py,sha256=LvopBeGSuTey7UDMOABl7xpLRyyVQS2E2wiUHxxWPnc,8340
|
|
22
22
|
tinybird/tb/modules/cicd.py,sha256=xxXwy-QekJcG14kkJeGNl7LkHduhZXfvBZE8WrU6-t4,5351
|
|
23
|
-
tinybird/tb/modules/cli.py,sha256=
|
|
23
|
+
tinybird/tb/modules/cli.py,sha256=882TimWnFyq1v0sfLDTtmPA_lFuVyL-GwmFpufB5Rxg,16075
|
|
24
24
|
tinybird/tb/modules/common.py,sha256=TWcGJUgzJCQvzI1oMKbNdx-KTRmMGvB25BawHpsaV8Q,70610
|
|
25
25
|
tinybird/tb/modules/config.py,sha256=mie3oMVTf5YOUFEiLs88P16U4LkJafJjSpjwyAkFHog,10979
|
|
26
26
|
tinybird/tb/modules/copy.py,sha256=wxyxZg8BPiWDgbW5HXJKYQp7_EumBXmAilo3McbCQOo,5916
|
|
27
|
-
tinybird/tb/modules/create.py,sha256=
|
|
28
|
-
tinybird/tb/modules/datasource.py,sha256=
|
|
29
|
-
tinybird/tb/modules/deployment.py,sha256=
|
|
27
|
+
tinybird/tb/modules/create.py,sha256=_eAMjntZ85uub1HqHoDekWC7ks79FQ2Zbc_6grjhT_g,14472
|
|
28
|
+
tinybird/tb/modules/datasource.py,sha256=TQ4wSag3CCw34d54FEXPJFGLQNYyNqv2nQbU6QT9uAE,14725
|
|
29
|
+
tinybird/tb/modules/deployment.py,sha256=Ezb_7ZK6ym967GNPzuSUH3K6ukAMWXaHb1gFXNet2pA,11859
|
|
30
30
|
tinybird/tb/modules/endpoint.py,sha256=9arqN1JQCMb0Nd3-EJ7lukOYkGHHCpQmiiZpp5FqPhc,9432
|
|
31
31
|
tinybird/tb/modules/exceptions.py,sha256=4A2sSjCEqKUMqpP3WI00zouCWW4uLaghXXLZBSw04mY,3363
|
|
32
|
-
tinybird/tb/modules/feedback_manager.py,sha256=
|
|
32
|
+
tinybird/tb/modules/feedback_manager.py,sha256=mrw5tdYycfvg6WLXlM0KIjfJardm_aNpnJkUg2vH0cA,68463
|
|
33
33
|
tinybird/tb/modules/fmt.py,sha256=poh6_cwVGSf-sBu6LKWuO2TANL_J8Sgm25sPpwxa3Aw,3558
|
|
34
34
|
tinybird/tb/modules/job.py,sha256=956Pj8BEEsiD2GZsV9RKKVM3I_CveOLgS82lykO5ukk,2963
|
|
35
35
|
tinybird/tb/modules/llm.py,sha256=AC0VSphTOM2t-v1_3NLvNN_FIbgMo4dTyMqIv5nniPo,835
|
|
36
36
|
tinybird/tb/modules/llm_utils.py,sha256=nS9r4FAElJw8yXtmdYrx-rtI2zXR8qXfi1QqUDCfxvg,3469
|
|
37
37
|
tinybird/tb/modules/local.py,sha256=x4xuCGVkoa8KLYGZEJnFUP8HUkKX05Frp_djRVjVjTs,5669
|
|
38
|
-
tinybird/tb/modules/local_common.py,sha256=
|
|
39
|
-
tinybird/tb/modules/login.py,sha256=
|
|
38
|
+
tinybird/tb/modules/local_common.py,sha256=UW6tNexC98aGRC6ca2w8qDDzyTTn-GDfr3uRy7zRHBM,2767
|
|
39
|
+
tinybird/tb/modules/login.py,sha256=cnB2Vwjc94FpG9C-7Y-l7Lb0Xilp2oUFDzqbQW0tpkU,6519
|
|
40
40
|
tinybird/tb/modules/materialization.py,sha256=HQKRTH6lkcYiDQJihbFqF_in58ezXG4ggZ_7Ywp_nUM,5738
|
|
41
|
-
tinybird/tb/modules/mock.py,sha256=
|
|
41
|
+
tinybird/tb/modules/mock.py,sha256=PzFtZL-6bZAZ3EiCC2nYJo058I4m50fD7FcBHISn3cI,5235
|
|
42
42
|
tinybird/tb/modules/pipe.py,sha256=pH2KwgH6Xbvl3kT8vMelpKvT6bcyB4EKFDvGfOsxXbg,2418
|
|
43
|
-
tinybird/tb/modules/project.py,sha256=
|
|
43
|
+
tinybird/tb/modules/project.py,sha256=rucAh_6K1EsW2dxjmqHPJ7bt6IliOWR0dNtEYG454fw,2620
|
|
44
44
|
tinybird/tb/modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
|
|
45
|
-
tinybird/tb/modules/shell.py,sha256=
|
|
45
|
+
tinybird/tb/modules/shell.py,sha256=LShGXwP_kzYAOUiTcvHMmcDugVr0crIfdNb5En6cfxo,14604
|
|
46
46
|
tinybird/tb/modules/table.py,sha256=4XrtjM-N0zfNtxVkbvLDQQazno1EPXnxTyo7llivfXk,11035
|
|
47
47
|
tinybird/tb/modules/tag.py,sha256=anPmMUBc-TbFovlpFi8GPkKA18y7Y0GczMsMms5TZsU,3502
|
|
48
48
|
tinybird/tb/modules/telemetry.py,sha256=iEGnMuCuNhvF6ln__j6X9MSTwL_0Hm-GgFHHHvhfknk,10466
|
|
49
|
-
tinybird/tb/modules/test.py,sha256=
|
|
49
|
+
tinybird/tb/modules/test.py,sha256=UoYGwTSY6_0ijS2sClMq-1OdOBbg-IXMDD8oLfZXvUg,13093
|
|
50
50
|
tinybird/tb/modules/token.py,sha256=sPdJoBE-6dd3Sd6W-prst7VOoJ0NbvP0uTaB6dXHs5s,12711
|
|
51
|
-
tinybird/tb/modules/update.py,sha256=GWYfbKnB0yf4ywAUp8jItaZY0ltBnaIMcLSiPpwtbMc,6832
|
|
52
51
|
tinybird/tb/modules/watch.py,sha256=Kredt5C7OOiI6YOivuR5QBdiDY4J_xLiwqHOROnfcsU,8591
|
|
53
|
-
tinybird/tb/modules/workspace.py,sha256=
|
|
52
|
+
tinybird/tb/modules/workspace.py,sha256=sfT9QkoeFlN7ndUXxyImp4a7EFEHjY9MlGlldOViz0Y,6404
|
|
54
53
|
tinybird/tb/modules/workspace_members.py,sha256=Ai6iCOzXX1zQ8q9iXIFSFHsBJlT-8Q28DaG5Ie-UweY,8726
|
|
55
|
-
tinybird/tb/modules/datafile/build.py,sha256=
|
|
54
|
+
tinybird/tb/modules/datafile/build.py,sha256=seGFSvmgyRrAM1-icsKBkuog3WccfGUYFTPT-xoA5W8,50940
|
|
56
55
|
tinybird/tb/modules/datafile/build_common.py,sha256=IXl-Z51zUi1dypV7meNenX0iu2UmowNeqgG6WHyMHlk,4562
|
|
57
56
|
tinybird/tb/modules/datafile/build_datasource.py,sha256=4aP8_DYCRGghXntZSeWDNJxjps1QRVa7WHoYCzQwQts,17355
|
|
58
57
|
tinybird/tb/modules/datafile/build_pipe.py,sha256=Jgv3YKIvMfjPiSIdw1k2mpaoDdAWMiMRaSHwRgyI97E,28258
|
|
59
|
-
tinybird/tb/modules/datafile/common.py,sha256=
|
|
58
|
+
tinybird/tb/modules/datafile/common.py,sha256=E_JDdlYqsPq3TVEt8FMcMpuF5xbKLtl8uLpj99RXSgE,78848
|
|
60
59
|
tinybird/tb/modules/datafile/diff.py,sha256=-0J7PsBO64T7LOZSkZ4ZFHHCPvT7cKItnJkbz2PkndU,6754
|
|
61
60
|
tinybird/tb/modules/datafile/exceptions.py,sha256=8rw2umdZjtby85QbuRKFO5ETz_eRHwUY5l7eHsy1wnI,556
|
|
62
61
|
tinybird/tb/modules/datafile/fixture.py,sha256=bdZndItV6ibOegPCrN3OgKdkpjDFCFvoSoiZVsCV_XQ,1852
|
|
@@ -75,8 +74,8 @@ tinybird/tb_cli_modules/config.py,sha256=6u6B5QCdiQLbJkCkwtnKGs9H3nP-KXXhC75mF7B
|
|
|
75
74
|
tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
|
|
76
75
|
tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
|
|
77
76
|
tinybird/tb_cli_modules/telemetry.py,sha256=iEGnMuCuNhvF6ln__j6X9MSTwL_0Hm-GgFHHHvhfknk,10466
|
|
78
|
-
tinybird-0.0.1.
|
|
79
|
-
tinybird-0.0.1.
|
|
80
|
-
tinybird-0.0.1.
|
|
81
|
-
tinybird-0.0.1.
|
|
82
|
-
tinybird-0.0.1.
|
|
77
|
+
tinybird-0.0.1.dev49.dist-info/METADATA,sha256=xwzvzDJ7ucjTfGvI0bPguc6fKa-C06ub0NSPwUmqC3g,2482
|
|
78
|
+
tinybird-0.0.1.dev49.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
79
|
+
tinybird-0.0.1.dev49.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
|
|
80
|
+
tinybird-0.0.1.dev49.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
|
|
81
|
+
tinybird-0.0.1.dev49.dist-info/RECORD,,
|