tinybird 0.0.1.dev148__py3-none-any.whl → 0.0.1.dev152__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/prompts.py +38 -14
- tinybird/tb/__cli__.py +2 -2
- tinybird/tb/modules/cli.py +10 -3
- tinybird/tb/modules/create.py +62 -45
- tinybird/tb/modules/datafile/common.py +9 -0
- tinybird/tb/modules/deprecations.py +7 -0
- tinybird/tb/modules/local_common.py +19 -5
- tinybird/tb/modules/mock.py +58 -30
- tinybird/tb/modules/project.py +9 -0
- tinybird/tb/modules/test.py +33 -5
- {tinybird-0.0.1.dev148.dist-info → tinybird-0.0.1.dev152.dist-info}/METADATA +1 -1
- {tinybird-0.0.1.dev148.dist-info → tinybird-0.0.1.dev152.dist-info}/RECORD +15 -15
- {tinybird-0.0.1.dev148.dist-info → tinybird-0.0.1.dev152.dist-info}/WHEEL +0 -0
- {tinybird-0.0.1.dev148.dist-info → tinybird-0.0.1.dev152.dist-info}/entry_points.txt +0 -0
- {tinybird-0.0.1.dev148.dist-info → tinybird-0.0.1.dev152.dist-info}/top_level.txt +0 -0
tinybird/prompts.py
CHANGED
|
@@ -401,7 +401,7 @@ Follow the instructions and generate the following response with no additional t
|
|
|
401
401
|
def create_prompt(existing_resources: str, feedback: str = "", history: str = "") -> str:
|
|
402
402
|
feedback_history = ""
|
|
403
403
|
if feedback and history:
|
|
404
|
-
feedback_history = f"""In case the <feedback> and <history> tags are present and not empty,
|
|
404
|
+
feedback_history = f"""In case the <feedback> and <history> tags are present and not empty,
|
|
405
405
|
it means there was a previous attempt to generate the resources and the user provided feedback and history about previous responses.
|
|
406
406
|
Use the following feedback and history to regenerate the response:
|
|
407
407
|
Feedback to improve the response:
|
|
@@ -420,7 +420,9 @@ You are a Tinybird expert. You will be given a prompt to generate new or update
|
|
|
420
420
|
{copy_pipe_instructions}
|
|
421
421
|
{materialized_pipe_instructions}
|
|
422
422
|
{connection_instructions}
|
|
423
|
-
{
|
|
423
|
+
{kafka_connection_example}
|
|
424
|
+
{gcs_connection_example}
|
|
425
|
+
{s3_connection_example}
|
|
424
426
|
|
|
425
427
|
{feedback_history}
|
|
426
428
|
|
|
@@ -443,14 +445,16 @@ Use the following format to generate the response and do not wrap it in any othe
|
|
|
443
445
|
copy_pipe_instructions=copy_pipe_instructions,
|
|
444
446
|
materialized_pipe_instructions=materialized_pipe_instructions,
|
|
445
447
|
connection_instructions=connection_instructions,
|
|
446
|
-
|
|
448
|
+
kafka_connection_example=kafka_connection_example,
|
|
449
|
+
gcs_connection_example=gcs_connection_example,
|
|
450
|
+
s3_connection_example=s3_connection_example,
|
|
447
451
|
feedback_history=feedback_history,
|
|
448
452
|
)
|
|
449
453
|
|
|
450
454
|
|
|
451
455
|
def mock_prompt(rows: int, feedback: str = "") -> str:
|
|
452
456
|
if feedback:
|
|
453
|
-
feedback = f"""In case the <feedback> tag is present and not empty,
|
|
457
|
+
feedback = f"""In case the <feedback> tag is present and not empty,
|
|
454
458
|
it means there was a previous attempt to generate the resources and the system provided feedback about the previous response.
|
|
455
459
|
Use the following feedback to regenerate the response:
|
|
456
460
|
<feedback>{feedback}</feedback>
|
|
@@ -515,7 +519,7 @@ SCHEMA >
|
|
|
515
519
|
`customer_id` UInt64 `json:$.customer_id`,
|
|
516
520
|
`order_date` DateTime `json:$.order_date`,
|
|
517
521
|
`total_amount` Float64 `json:$.total_amount`,
|
|
518
|
-
`items` Array(String) `json:$.items[:]` // This is an array field
|
|
522
|
+
`items` Array(String) `json:$.items[:]` // This is an array field
|
|
519
523
|
|
|
520
524
|
### Desired final output of the query:
|
|
521
525
|
{{
|
|
@@ -680,19 +684,34 @@ connection_instructions = """
|
|
|
680
684
|
- Content cannot be empty.
|
|
681
685
|
- The connection names must be unique.
|
|
682
686
|
- No indentation is allowed for property names
|
|
683
|
-
- We
|
|
687
|
+
- We support kafka, gcs and s3 connections for now
|
|
684
688
|
</connection_file_instructions>
|
|
685
689
|
"""
|
|
686
690
|
|
|
687
|
-
|
|
688
|
-
<
|
|
691
|
+
kafka_connection_example = """
|
|
692
|
+
<kafka_connection_content>
|
|
689
693
|
TYPE kafka
|
|
690
694
|
KAFKA_BOOTSTRAP_SERVERS {{ tb_secret("PRODUCTION_KAFKA_SERVERS", "localhost:9092") }}
|
|
691
695
|
KAFKA_SECURITY_PROTOCOL SASL_SSL
|
|
692
696
|
KAFKA_SASL_MECHANISM PLAIN
|
|
693
697
|
KAFKA_KEY {{ tb_secret("PRODUCTION_KAFKA_USERNAME", "") }}
|
|
694
698
|
KAFKA_SECRET {{ tb_secret("PRODUCTION_KAFKA_PASSWORD", "") }}
|
|
695
|
-
</
|
|
699
|
+
</kafka_connection_content>
|
|
700
|
+
"""
|
|
701
|
+
|
|
702
|
+
gcs_connection_example = """
|
|
703
|
+
<gcs_connection_content>
|
|
704
|
+
TYPE gcs
|
|
705
|
+
GCS_SERVICE_ACCOUNT_CREDENTIALS_JSON {{ tb_secret("PRODUCTION_GCS_SERVICE_ACCOUNT_CREDENTIALS_JSON", "") }}
|
|
706
|
+
</gcs_connection_content>
|
|
707
|
+
"""
|
|
708
|
+
|
|
709
|
+
s3_connection_example = """
|
|
710
|
+
<s3_connection_content>
|
|
711
|
+
TYPE s3
|
|
712
|
+
S3_REGION {{ tb_secret("PRODUCTION_S3_REGION", "") }}
|
|
713
|
+
S3_ARN {{ tb_secret("PRODUCTION_S3_ARN", "") }}
|
|
714
|
+
</s3_connection_content>
|
|
696
715
|
"""
|
|
697
716
|
|
|
698
717
|
datasource_instructions = """
|
|
@@ -703,6 +722,7 @@ datasource_instructions = """
|
|
|
703
722
|
- Use MergeTree engine by default.
|
|
704
723
|
- Use AggregatingMergeTree engine when the datasource is the target of a materialized pipe.
|
|
705
724
|
- Use always json paths to define the schema. Example: `user_id` String `json:$.user_id`,
|
|
725
|
+
- If the datasource is using an S3 or GCS connection, they need to set IMPORT_CONNECTION_NAME, IMPORT_BUCKET_URI and IMPORT_SCHEDULE (GCS @on-demand only, S3 supports @auto too)
|
|
706
726
|
</datasource_file_instructions>
|
|
707
727
|
"""
|
|
708
728
|
|
|
@@ -775,7 +795,7 @@ sql_instructions = """
|
|
|
775
795
|
{{%if not defined(end_date)%}}
|
|
776
796
|
AND now()
|
|
777
797
|
{{%else%}}
|
|
778
|
-
AND {{{{DateTime(end_date)}}}}
|
|
798
|
+
AND {{{{DateTime(end_date)}}}}
|
|
779
799
|
{{%end%}}
|
|
780
800
|
</valid_condition_without_now>
|
|
781
801
|
- Parameters must not be quoted.
|
|
@@ -862,7 +882,9 @@ Follow these instructions when creating or updating .pipe files:
|
|
|
862
882
|
{copy_pipe_instructions}
|
|
863
883
|
{materialized_pipe_instructions}
|
|
864
884
|
{connection_instructions}
|
|
865
|
-
{
|
|
885
|
+
{kafka_connection_example}
|
|
886
|
+
{gcs_connection_example}
|
|
887
|
+
{s3_connection_example}
|
|
866
888
|
</pipe_file_instructions>
|
|
867
889
|
<test_file_instructions>
|
|
868
890
|
Follow these instructions when creating or updating .yaml files for tests:
|
|
@@ -884,7 +906,9 @@ Follow these instructions when evolving a datasource schema:
|
|
|
884
906
|
test_instructions=test_instructions,
|
|
885
907
|
deployment_instructions=deployment_instructions,
|
|
886
908
|
connection_instructions=connection_instructions,
|
|
887
|
-
|
|
909
|
+
kafka_connection_example=kafka_connection_example,
|
|
910
|
+
gcs_connection_example=gcs_connection_example,
|
|
911
|
+
s3_connection_example=s3_connection_example,
|
|
888
912
|
)
|
|
889
913
|
|
|
890
914
|
|
|
@@ -950,7 +974,7 @@ SCHEMA >
|
|
|
950
974
|
`payload` String `json:$.payload`
|
|
951
975
|
|
|
952
976
|
FORWARD_QUERY >
|
|
953
|
-
select timestamp, toUUID(session_id) as session_id, action, version, payload
|
|
977
|
+
select timestamp, toUUID(session_id) as session_id, action, version, payload
|
|
954
978
|
</forward_query_example>
|
|
955
979
|
</deployment_instruction>
|
|
956
980
|
"""
|
|
@@ -968,7 +992,7 @@ Current README.md file:
|
|
|
968
992
|
- If it is not present in the current readme, generate a new ## Tinybird section with the following content:
|
|
969
993
|
- ### Overview section:
|
|
970
994
|
- Explaining the purpose of the project.
|
|
971
|
-
- ### Data sources section:
|
|
995
|
+
- ### Data sources section:
|
|
972
996
|
- Explaining the purpose of each datasource.
|
|
973
997
|
- Add a snippet of how to ingest data into each datasource like the following (where the payload example matches the datasource schema respecting non-nullable types):
|
|
974
998
|
curl -X POST "{host}/v0/events?name=events" \
|
tinybird/tb/__cli__.py
CHANGED
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/cli/introduction.html'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '0.0.1.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '0.0.1.dev152'
|
|
8
|
+
__revision__ = '100f32b'
|
tinybird/tb/modules/cli.py
CHANGED
|
@@ -323,16 +323,23 @@ async def create_ctx_client(ctx: Context, config: Dict[str, Any], cloud: bool, s
|
|
|
323
323
|
return None
|
|
324
324
|
|
|
325
325
|
commands_always_cloud = ["pull", "infra"]
|
|
326
|
-
commands_always_local = ["build", "
|
|
327
|
-
|
|
326
|
+
commands_always_local = ["build", "dev"]
|
|
327
|
+
command_always_test = ["test"]
|
|
328
|
+
|
|
329
|
+
if (
|
|
330
|
+
(cloud or command in commands_always_cloud)
|
|
331
|
+
and command not in commands_always_local
|
|
332
|
+
and command not in command_always_test
|
|
333
|
+
):
|
|
328
334
|
click.echo(
|
|
329
335
|
FeedbackManager.gray(message=f"Running against Tinybird Cloud: Workspace {config.get('name', 'default')}")
|
|
330
336
|
)
|
|
331
337
|
return _get_tb_client(config.get("token", None), config["host"], staging=staging)
|
|
332
338
|
local = command in commands_always_local
|
|
339
|
+
test = command in command_always_test
|
|
333
340
|
if not local and command not in commands_always_local and command:
|
|
334
341
|
click.echo(FeedbackManager.gray(message="Running against Tinybird Local"))
|
|
335
|
-
return await get_tinybird_local_client(config, staging=staging)
|
|
342
|
+
return await get_tinybird_local_client(config, test=test, staging=staging)
|
|
336
343
|
|
|
337
344
|
|
|
338
345
|
def get_target_env(cloud: bool) -> str:
|
tinybird/tb/modules/create.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import glob
|
|
1
2
|
import os
|
|
2
3
|
import re
|
|
3
4
|
from pathlib import Path
|
|
@@ -5,7 +6,7 @@ from typing import Any, Dict, Optional, Tuple
|
|
|
5
6
|
|
|
6
7
|
import click
|
|
7
8
|
|
|
8
|
-
from tinybird.prompts import create_prompt,
|
|
9
|
+
from tinybird.prompts import create_prompt, readme_prompt, rules_prompt
|
|
9
10
|
from tinybird.tb.client import TinyB
|
|
10
11
|
from tinybird.tb.modules.cicd import init_cicd
|
|
11
12
|
from tinybird.tb.modules.cli import cli
|
|
@@ -17,6 +18,7 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
|
17
18
|
from tinybird.tb.modules.llm import LLM
|
|
18
19
|
from tinybird.tb.modules.llm_utils import extract_xml, parse_xml
|
|
19
20
|
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
21
|
+
from tinybird.tb.modules.mock import create_mock_data
|
|
20
22
|
from tinybird.tb.modules.project import Project
|
|
21
23
|
|
|
22
24
|
|
|
@@ -83,7 +85,7 @@ async def create(
|
|
|
83
85
|
|
|
84
86
|
if data or (prompt and user_token):
|
|
85
87
|
click.echo(FeedbackManager.highlight(message="\n» Creating resources..."))
|
|
86
|
-
result, created_something = await create_resources(tb_client, user_token, data, prompt,
|
|
88
|
+
result, created_something = await create_resources(tb_client, user_token, data, prompt, project, ctx_config)
|
|
87
89
|
click.echo(FeedbackManager.success(message="✓ Done!\n"))
|
|
88
90
|
if prompt:
|
|
89
91
|
readme_path = Path(root_folder) / "README.md"
|
|
@@ -132,22 +134,26 @@ async def create(
|
|
|
132
134
|
persist_fixture(ds_name, data_content, folder, format=data_format)
|
|
133
135
|
created_something = True
|
|
134
136
|
elif prompt and user_token:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
datasource_path = Path(folder) / "datasources" / datasource_file
|
|
138
|
-
llm = LLM(user_token=user_token, host=tb_client.host)
|
|
137
|
+
for datasource_file in project.get_datasource_files():
|
|
138
|
+
datasource_path = Path(datasource_file)
|
|
139
139
|
datasource_name = datasource_path.stem
|
|
140
140
|
datasource_content = datasource_path.read_text()
|
|
141
141
|
has_json_path = "`json:" in datasource_content
|
|
142
142
|
if has_json_path:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
143
|
+
mock_data = await create_mock_data(
|
|
144
|
+
datasource_name,
|
|
145
|
+
datasource_content,
|
|
146
|
+
rows,
|
|
147
|
+
prompt,
|
|
148
|
+
config,
|
|
149
|
+
ctx_config,
|
|
150
|
+
user_token,
|
|
151
|
+
tb_client,
|
|
152
|
+
format_="ndjson",
|
|
153
|
+
folder=project.folder,
|
|
154
|
+
)
|
|
155
|
+
if mock_data:
|
|
156
|
+
persist_fixture(datasource_name, mock_data, folder, format="ndjson")
|
|
151
157
|
click.echo(FeedbackManager.info(message=f"✓ /fixtures/{datasource_name}"))
|
|
152
158
|
created_something = True
|
|
153
159
|
|
|
@@ -204,12 +210,12 @@ async def create_resources(
|
|
|
204
210
|
user_token: Optional[str],
|
|
205
211
|
data: Optional[str],
|
|
206
212
|
prompt: Optional[str],
|
|
207
|
-
|
|
213
|
+
project: Project,
|
|
208
214
|
config: Dict[str, Any],
|
|
209
215
|
) -> Tuple[str, bool]:
|
|
210
216
|
result = ""
|
|
211
217
|
created_any_resource = False
|
|
212
|
-
folder_path =
|
|
218
|
+
folder_path = project.path
|
|
213
219
|
if data:
|
|
214
220
|
local_client = await get_tinybird_local_client(config)
|
|
215
221
|
path = folder_path / data
|
|
@@ -224,7 +230,7 @@ SQL >
|
|
|
224
230
|
SELECT * from {name}
|
|
225
231
|
TYPE ENDPOINT
|
|
226
232
|
""",
|
|
227
|
-
folder,
|
|
233
|
+
project.folder,
|
|
228
234
|
)
|
|
229
235
|
result = (
|
|
230
236
|
f"<response><resource><type>datasource</type><name>{name}</name><content></content></resource></response>"
|
|
@@ -232,14 +238,9 @@ TYPE ENDPOINT
|
|
|
232
238
|
created_any_resource = True
|
|
233
239
|
|
|
234
240
|
elif prompt and user_token:
|
|
235
|
-
datasource_paths = [
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if f.endswith(".datasource")
|
|
239
|
-
]
|
|
240
|
-
pipes_paths = [
|
|
241
|
-
Path(folder) / "endpoints" / f for f in os.listdir(Path(folder) / "endpoints") if f.endswith(".pipe")
|
|
242
|
-
]
|
|
241
|
+
datasource_paths = [Path(ds_file) for ds_file in project.get_datasource_files()]
|
|
242
|
+
pipes_paths = [Path(pipe_file) for pipe_file in project.get_pipe_files()]
|
|
243
|
+
connections_paths = [Path(conn_file) for conn_file in project.get_connection_files()]
|
|
243
244
|
resources_xml = "\n".join(
|
|
244
245
|
[
|
|
245
246
|
f"<resource><type>{resource_type}</type><name>{resource_name}</name><content>{resource_content}</content></resource>"
|
|
@@ -254,6 +255,14 @@ TYPE ENDPOINT
|
|
|
254
255
|
)
|
|
255
256
|
for pipe in pipes_paths
|
|
256
257
|
]
|
|
258
|
+
+ [
|
|
259
|
+
(
|
|
260
|
+
"connection",
|
|
261
|
+
conn.stem,
|
|
262
|
+
conn.read_text(),
|
|
263
|
+
)
|
|
264
|
+
for conn in connections_paths
|
|
265
|
+
]
|
|
257
266
|
]
|
|
258
267
|
)
|
|
259
268
|
llm = LLM(user_token=user_token, host=tb_client.host)
|
|
@@ -287,19 +296,19 @@ TYPE ENDPOINT
|
|
|
287
296
|
data=None,
|
|
288
297
|
_format="ndjson",
|
|
289
298
|
force=True,
|
|
290
|
-
folder=folder,
|
|
299
|
+
folder=project.folder,
|
|
291
300
|
)
|
|
292
301
|
created_any_resource = True
|
|
293
302
|
|
|
294
303
|
for pipe in pipes:
|
|
295
304
|
content = pipe["content"].replace("```", "")
|
|
296
|
-
generate_pipe_file(pipe["name"], content, folder)
|
|
305
|
+
generate_pipe_file(pipe["name"], content, project.folder)
|
|
297
306
|
created_any_resource = True
|
|
298
307
|
|
|
299
308
|
for conn in connections:
|
|
300
309
|
content = conn["content"].replace("```", "")
|
|
301
310
|
filename = f"{conn['name']}.connection"
|
|
302
|
-
generate_connection_file(conn["name"], content, folder)
|
|
311
|
+
generate_connection_file(conn["name"], content, project.folder)
|
|
303
312
|
created_any_resource = True
|
|
304
313
|
|
|
305
314
|
return result, created_any_resource
|
|
@@ -335,21 +344,25 @@ def generate_pipe_file(name: str, content: str, folder: str) -> Path:
|
|
|
335
344
|
def is_endpoint(content: str) -> bool:
|
|
336
345
|
return re.search(r"TYPE endpoint", content, re.IGNORECASE) is not None
|
|
337
346
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
pathname = "materializations"
|
|
342
|
-
elif is_sink(content):
|
|
343
|
-
pathname = "sinks"
|
|
344
|
-
elif is_endpoint(content):
|
|
345
|
-
pathname = "endpoints"
|
|
347
|
+
already_exists = glob.glob(f"{folder}/**/{name}.pipe")
|
|
348
|
+
if already_exists:
|
|
349
|
+
f = Path(already_exists[0])
|
|
346
350
|
else:
|
|
347
|
-
|
|
351
|
+
if is_copy(content):
|
|
352
|
+
pathname = "copies"
|
|
353
|
+
elif is_materialization(content):
|
|
354
|
+
pathname = "materializations"
|
|
355
|
+
elif is_sink(content):
|
|
356
|
+
pathname = "sinks"
|
|
357
|
+
elif is_endpoint(content):
|
|
358
|
+
pathname = "endpoints"
|
|
359
|
+
else:
|
|
360
|
+
pathname = "pipes"
|
|
348
361
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
362
|
+
base = Path(folder) / pathname
|
|
363
|
+
if not base.exists():
|
|
364
|
+
base.mkdir()
|
|
365
|
+
f = base / (f"{name}.pipe")
|
|
353
366
|
with open(f"{f}", "w") as file:
|
|
354
367
|
file.write(content)
|
|
355
368
|
click.echo(FeedbackManager.info_file_created(file=f.relative_to(folder)))
|
|
@@ -357,10 +370,14 @@ def generate_pipe_file(name: str, content: str, folder: str) -> Path:
|
|
|
357
370
|
|
|
358
371
|
|
|
359
372
|
def generate_connection_file(name: str, content: str, folder: str, skip_feedback: bool = False) -> Path:
|
|
360
|
-
|
|
361
|
-
if
|
|
362
|
-
|
|
363
|
-
|
|
373
|
+
already_exists = glob.glob(f"{folder}/**/{name}.connection")
|
|
374
|
+
if already_exists:
|
|
375
|
+
f = Path(already_exists[0])
|
|
376
|
+
else:
|
|
377
|
+
base = Path(folder) / "connections"
|
|
378
|
+
if not base.exists():
|
|
379
|
+
base.mkdir()
|
|
380
|
+
f = base / (f"{name}.connection")
|
|
364
381
|
with open(f"{f}", "w") as file:
|
|
365
382
|
file.write(content)
|
|
366
383
|
if not skip_feedback:
|
|
@@ -846,6 +846,15 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
846
846
|
lineno=line,
|
|
847
847
|
pos=pos,
|
|
848
848
|
)
|
|
849
|
+
if detected_type in ("Int", "UInt"):
|
|
850
|
+
t = detected_type
|
|
851
|
+
raise SchemaSyntaxError(
|
|
852
|
+
message=f"Precision is mandatory for {t} types",
|
|
853
|
+
hint=f"Hint: use one of {t}8, {t}16, {t}32, {t}64, {t}128, {t}256",
|
|
854
|
+
lineno=line,
|
|
855
|
+
pos=pos - len(t),
|
|
856
|
+
)
|
|
857
|
+
|
|
849
858
|
try:
|
|
850
859
|
# Imported in the body to be compatible with the CLI
|
|
851
860
|
from chtoolset.query import check_compatible_types
|
|
@@ -9,6 +9,7 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
|
9
9
|
context_settings=dict(
|
|
10
10
|
ignore_unknown_options=True,
|
|
11
11
|
),
|
|
12
|
+
hidden=True,
|
|
12
13
|
)
|
|
13
14
|
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
|
14
15
|
def branch(args) -> None:
|
|
@@ -30,6 +31,7 @@ def branch(args) -> None:
|
|
|
30
31
|
context_settings=dict(
|
|
31
32
|
ignore_unknown_options=True,
|
|
32
33
|
),
|
|
34
|
+
hidden=True,
|
|
33
35
|
)
|
|
34
36
|
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
|
35
37
|
def check(args) -> None:
|
|
@@ -47,6 +49,7 @@ def check(args) -> None:
|
|
|
47
49
|
context_settings=dict(
|
|
48
50
|
ignore_unknown_options=True,
|
|
49
51
|
),
|
|
52
|
+
hidden=True,
|
|
50
53
|
)
|
|
51
54
|
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
|
52
55
|
def diff(args) -> None:
|
|
@@ -64,6 +67,7 @@ def diff(args) -> None:
|
|
|
64
67
|
context_settings=dict(
|
|
65
68
|
ignore_unknown_options=True,
|
|
66
69
|
),
|
|
70
|
+
hidden=True,
|
|
67
71
|
)
|
|
68
72
|
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
|
69
73
|
def fmt(args) -> None:
|
|
@@ -81,6 +85,7 @@ def fmt(args) -> None:
|
|
|
81
85
|
context_settings=dict(
|
|
82
86
|
ignore_unknown_options=True,
|
|
83
87
|
),
|
|
88
|
+
hidden=True,
|
|
84
89
|
)
|
|
85
90
|
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
|
86
91
|
def init(args) -> None:
|
|
@@ -98,6 +103,7 @@ def init(args) -> None:
|
|
|
98
103
|
context_settings=dict(
|
|
99
104
|
ignore_unknown_options=True,
|
|
100
105
|
),
|
|
106
|
+
hidden=True,
|
|
101
107
|
)
|
|
102
108
|
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
|
103
109
|
def push(args) -> None:
|
|
@@ -115,6 +121,7 @@ def push(args) -> None:
|
|
|
115
121
|
context_settings=dict(
|
|
116
122
|
ignore_unknown_options=True,
|
|
117
123
|
),
|
|
124
|
+
hidden=True,
|
|
118
125
|
)
|
|
119
126
|
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
|
|
120
127
|
def tag(args) -> None:
|
|
@@ -18,14 +18,14 @@ TB_LOCAL_HOST = re.sub(r"^https?://", "", os.getenv("TB_LOCAL_HOST", "localhost"
|
|
|
18
18
|
TB_LOCAL_ADDRESS = f"http://{TB_LOCAL_HOST}:{TB_LOCAL_PORT}"
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
async def get_tinybird_local_client(config_obj: Dict[str, Any], staging: bool = False) -> TinyB:
|
|
21
|
+
async def get_tinybird_local_client(config_obj: Dict[str, Any], test: bool = False, staging: bool = False) -> TinyB:
|
|
22
22
|
"""Get a Tinybird client connected to the local environment."""
|
|
23
23
|
|
|
24
|
-
config = await get_tinybird_local_config(config_obj)
|
|
24
|
+
config = await get_tinybird_local_config(config_obj, test=test)
|
|
25
25
|
return config.get_client(host=TB_LOCAL_ADDRESS, staging=staging)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
async def get_tinybird_local_config(config_obj: Dict[str, Any]) -> CLIConfig:
|
|
28
|
+
async def get_tinybird_local_config(config_obj: Dict[str, Any], test: bool = False) -> CLIConfig:
|
|
29
29
|
"""Craft a client config with a workspace name based on the path of the project files
|
|
30
30
|
|
|
31
31
|
It uses the tokens from tinybird local
|
|
@@ -47,7 +47,10 @@ async def get_tinybird_local_config(config_obj: Dict[str, Any]) -> CLIConfig:
|
|
|
47
47
|
# Create a new workspace if path is provided. This is used to isolate the build in a different workspace.
|
|
48
48
|
if path:
|
|
49
49
|
user_client = config.get_client(host=TB_LOCAL_ADDRESS, token=user_token)
|
|
50
|
-
|
|
50
|
+
if test:
|
|
51
|
+
ws_name = get_test_workspace_name(path)
|
|
52
|
+
else:
|
|
53
|
+
ws_name = config.get("name") or config_obj.get("name") or get_build_workspace_name(path)
|
|
51
54
|
if not ws_name:
|
|
52
55
|
raise AuthNoTokenException()
|
|
53
56
|
|
|
@@ -61,6 +64,13 @@ async def get_tinybird_local_config(config_obj: Dict[str, Any]) -> CLIConfig:
|
|
|
61
64
|
|
|
62
65
|
ws = next((ws for ws in local_workspaces if ws["name"] == ws_name), None)
|
|
63
66
|
|
|
67
|
+
# If we are running a test, we need to delete the workspace if it already exists
|
|
68
|
+
if test and ws:
|
|
69
|
+
requests.delete(
|
|
70
|
+
f"{TB_LOCAL_ADDRESS}/v1/workspaces/{ws['id']}?token={user_token}&hard_delete_confirmation=yes"
|
|
71
|
+
)
|
|
72
|
+
ws = None
|
|
73
|
+
|
|
64
74
|
if not ws:
|
|
65
75
|
await user_client.create_workspace(
|
|
66
76
|
ws_name, template=None, assign_to_organization_id=user_org_id, version="v1"
|
|
@@ -71,7 +81,6 @@ async def get_tinybird_local_config(config_obj: Dict[str, Any]) -> CLIConfig:
|
|
|
71
81
|
raise AuthNoTokenException()
|
|
72
82
|
|
|
73
83
|
ws_token = ws["token"]
|
|
74
|
-
|
|
75
84
|
config.set_token(ws_token)
|
|
76
85
|
config.set_token_for_host(TB_LOCAL_ADDRESS, ws_token)
|
|
77
86
|
config.set_host(TB_LOCAL_ADDRESS)
|
|
@@ -86,3 +95,8 @@ async def get_tinybird_local_config(config_obj: Dict[str, Any]) -> CLIConfig:
|
|
|
86
95
|
def get_build_workspace_name(path: str) -> str:
|
|
87
96
|
folder_hash = hashlib.sha256(path.encode()).hexdigest()
|
|
88
97
|
return f"Tinybird_Local_Build_{folder_hash}"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_test_workspace_name(path: str) -> str:
|
|
101
|
+
folder_hash = hashlib.sha256(path.encode()).hexdigest()
|
|
102
|
+
return f"Tinybird_Local_Test_{folder_hash}"
|
tinybird/tb/modules/mock.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import glob
|
|
2
2
|
from pathlib import Path
|
|
3
|
+
from typing import Any, Dict, List
|
|
3
4
|
|
|
4
5
|
import click
|
|
5
6
|
|
|
@@ -65,41 +66,23 @@ async def mock(ctx: click.Context, datasource: str, rows: int, prompt: str, form
|
|
|
65
66
|
|
|
66
67
|
datasource_content = datasource_path.read_text()
|
|
67
68
|
config = CLIConfig.get_project_config()
|
|
68
|
-
user_client = config.get_client(token=ctx_config.get("token"), host=ctx_config.get("host"))
|
|
69
69
|
user_token = ctx_config.get("user_token")
|
|
70
70
|
|
|
71
71
|
if not user_token:
|
|
72
72
|
raise Exception("This action requires authentication. Run 'tb login' first.")
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
sql_format = "JSON" if format_ == "ndjson" else "CSV"
|
|
87
|
-
result = await tb_client.query(f"SELECT * FROM ({sql}) LIMIT {rows} FORMAT {sql_format}")
|
|
88
|
-
if sql_format == "JSON":
|
|
89
|
-
data = result.get("data", [])[:rows]
|
|
90
|
-
error_response = result.get("error", None)
|
|
91
|
-
if error_response:
|
|
92
|
-
raise Exception(error_response)
|
|
93
|
-
else:
|
|
94
|
-
data = result
|
|
95
|
-
break
|
|
96
|
-
except Exception as e:
|
|
97
|
-
error = str(e)
|
|
98
|
-
attempts += 1
|
|
99
|
-
if attempts > 5:
|
|
100
|
-
raise Exception(f"Failed to generate a valid solution. Check {str(sql_path)} and try again.")
|
|
101
|
-
else:
|
|
102
|
-
continue
|
|
74
|
+
data = await create_mock_data(
|
|
75
|
+
datasource_name,
|
|
76
|
+
datasource_content,
|
|
77
|
+
rows,
|
|
78
|
+
prompt,
|
|
79
|
+
config,
|
|
80
|
+
ctx_config,
|
|
81
|
+
user_token,
|
|
82
|
+
tb_client,
|
|
83
|
+
format_,
|
|
84
|
+
folder,
|
|
85
|
+
)
|
|
103
86
|
|
|
104
87
|
fixture_path = persist_fixture(datasource_name, data, folder, format=format_)
|
|
105
88
|
click.echo(FeedbackManager.info(message=f"✓ /fixtures/{datasource_name}.{format_} created"))
|
|
@@ -125,3 +108,48 @@ async def append_fixture(
|
|
|
125
108
|
concurrency=1,
|
|
126
109
|
silent=True,
|
|
127
110
|
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
async def create_mock_data(
|
|
114
|
+
datasource_name: str,
|
|
115
|
+
datasource_content: str,
|
|
116
|
+
rows: int,
|
|
117
|
+
prompt: str,
|
|
118
|
+
config: CLIConfig,
|
|
119
|
+
ctx_config: Dict[str, Any],
|
|
120
|
+
user_token: str,
|
|
121
|
+
tb_client: TinyB,
|
|
122
|
+
format_: str,
|
|
123
|
+
folder: str,
|
|
124
|
+
) -> List[Dict[str, Any]]:
|
|
125
|
+
user_client = config.get_client(token=ctx_config.get("token"), host=ctx_config.get("host"))
|
|
126
|
+
llm = LLM(user_token=user_token, host=user_client.host)
|
|
127
|
+
prompt = f"<datasource_schema>{datasource_content}</datasource_schema>\n<user_input>{prompt}</user_input>"
|
|
128
|
+
sql = ""
|
|
129
|
+
attempts = 0
|
|
130
|
+
data = []
|
|
131
|
+
error = ""
|
|
132
|
+
sql_path = None
|
|
133
|
+
while True:
|
|
134
|
+
try:
|
|
135
|
+
response = llm.ask(system_prompt=mock_prompt(rows, error), prompt=prompt)
|
|
136
|
+
sql = extract_xml(response, "sql")
|
|
137
|
+
sql_path = persist_fixture_sql(datasource_name, sql, folder)
|
|
138
|
+
sql_format = "JSON" if format_ == "ndjson" else "CSV"
|
|
139
|
+
result = await tb_client.query(f"SELECT * FROM ({sql}) LIMIT {rows} FORMAT {sql_format}")
|
|
140
|
+
if sql_format == "JSON":
|
|
141
|
+
data = result.get("data", [])[:rows]
|
|
142
|
+
error_response = result.get("error", None)
|
|
143
|
+
if error_response:
|
|
144
|
+
raise Exception(error_response)
|
|
145
|
+
else:
|
|
146
|
+
data = result
|
|
147
|
+
break
|
|
148
|
+
except Exception as e:
|
|
149
|
+
error = str(e)
|
|
150
|
+
attempts += 1
|
|
151
|
+
if attempts > 5:
|
|
152
|
+
raise Exception(f"Failed to generate a valid solution. Check {str(sql_path)} and try again.")
|
|
153
|
+
else:
|
|
154
|
+
continue
|
|
155
|
+
return data
|
tinybird/tb/modules/project.py
CHANGED
|
@@ -55,6 +55,15 @@ class Project:
|
|
|
55
55
|
def connections(self) -> List[str]:
|
|
56
56
|
return sorted([Path(f).stem for f in glob.glob(f"{self.path}/**/*.connection", recursive=False)])
|
|
57
57
|
|
|
58
|
+
def get_datasource_files(self) -> List[str]:
|
|
59
|
+
return glob.glob(f"{self.path}/**/*.datasource", recursive=False)
|
|
60
|
+
|
|
61
|
+
def get_pipe_files(self) -> List[str]:
|
|
62
|
+
return glob.glob(f"{self.path}/**/*.pipe", recursive=False)
|
|
63
|
+
|
|
64
|
+
def get_connection_files(self) -> List[str]:
|
|
65
|
+
return glob.glob(f"{self.path}/**/*.connection", recursive=False)
|
|
66
|
+
|
|
58
67
|
def get_pipe_datafile(self, filename: str) -> Optional[Datafile]:
|
|
59
68
|
try:
|
|
60
69
|
return parse_pipe(filename).datafile
|
tinybird/tb/modules/test.py
CHANGED
|
@@ -8,22 +8,25 @@ import difflib
|
|
|
8
8
|
import glob
|
|
9
9
|
import sys
|
|
10
10
|
import urllib.parse
|
|
11
|
+
from copy import deepcopy
|
|
11
12
|
from pathlib import Path
|
|
12
13
|
from typing import Any, Dict, List, Optional, Tuple
|
|
13
14
|
|
|
14
15
|
import click
|
|
16
|
+
import requests
|
|
15
17
|
import yaml
|
|
16
18
|
from requests import Response
|
|
17
19
|
|
|
18
20
|
from tinybird.prompts import test_create_prompt
|
|
19
21
|
from tinybird.tb.client import TinyB
|
|
20
|
-
from tinybird.tb.modules.build import process
|
|
22
|
+
from tinybird.tb.modules.build import process as build_project
|
|
21
23
|
from tinybird.tb.modules.cli import cli
|
|
22
24
|
from tinybird.tb.modules.config import CLIConfig
|
|
23
|
-
from tinybird.tb.modules.exceptions import CLITestException
|
|
25
|
+
from tinybird.tb.modules.exceptions import CLILocalException, CLITestException
|
|
24
26
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
25
27
|
from tinybird.tb.modules.llm import LLM
|
|
26
28
|
from tinybird.tb.modules.llm_utils import extract_xml, parse_xml
|
|
29
|
+
from tinybird.tb.modules.local_common import TB_LOCAL_ADDRESS, get_test_workspace_name
|
|
27
30
|
from tinybird.tb.modules.project import Project
|
|
28
31
|
|
|
29
32
|
yaml.SafeDumper.org_represent_str = yaml.SafeDumper.represent_str # type: ignore[attr-defined]
|
|
@@ -77,7 +80,7 @@ def test_create(ctx: click.Context, name_or_filename: str, prompt: str) -> None:
|
|
|
77
80
|
project: Project = ctx.ensure_object(dict)["project"]
|
|
78
81
|
client: TinyB = ctx.ensure_object(dict)["client"]
|
|
79
82
|
click.echo(FeedbackManager.highlight(message="\n» Building project"))
|
|
80
|
-
|
|
83
|
+
build_project(project=project, tb_client=client, watch=False, silent=True)
|
|
81
84
|
click.echo(FeedbackManager.info(message="✓ Done!\n"))
|
|
82
85
|
config = CLIConfig.get_project_config()
|
|
83
86
|
folder = project.folder
|
|
@@ -140,6 +143,8 @@ def test_create(ctx: click.Context, name_or_filename: str, prompt: str) -> None:
|
|
|
140
143
|
click.echo(FeedbackManager.success(message="✓ Done!\n"))
|
|
141
144
|
except Exception as e:
|
|
142
145
|
raise CLITestException(FeedbackManager.error(message=str(e)))
|
|
146
|
+
finally:
|
|
147
|
+
cleanup_test_workspace(client, project.folder)
|
|
143
148
|
|
|
144
149
|
|
|
145
150
|
@test.command(
|
|
@@ -154,7 +159,7 @@ def test_update(ctx: click.Context, pipe: str) -> None:
|
|
|
154
159
|
project: Project = ctx.ensure_object(dict)["project"]
|
|
155
160
|
folder = project.folder
|
|
156
161
|
click.echo(FeedbackManager.highlight(message="\n» Building project"))
|
|
157
|
-
|
|
162
|
+
build_project(project=project, tb_client=client, watch=False, silent=True)
|
|
158
163
|
click.echo(FeedbackManager.info(message="✓ Done!"))
|
|
159
164
|
pipe_tests_path = get_pipe_path(pipe, folder)
|
|
160
165
|
pipe_name = pipe_tests_path.stem
|
|
@@ -191,6 +196,8 @@ def test_update(ctx: click.Context, pipe: str) -> None:
|
|
|
191
196
|
click.echo(FeedbackManager.success(message="✓ Done!\n"))
|
|
192
197
|
except Exception as e:
|
|
193
198
|
raise CLITestException(FeedbackManager.error(message=str(e)))
|
|
199
|
+
finally:
|
|
200
|
+
cleanup_test_workspace(client, project.folder)
|
|
194
201
|
|
|
195
202
|
|
|
196
203
|
@test.command(
|
|
@@ -204,7 +211,7 @@ def run_tests(ctx: click.Context, name: Tuple[str, ...]) -> None:
|
|
|
204
211
|
client: TinyB = ctx.ensure_object(dict)["client"]
|
|
205
212
|
project: Project = ctx.ensure_object(dict)["project"]
|
|
206
213
|
click.echo(FeedbackManager.highlight(message="\n» Building project"))
|
|
207
|
-
|
|
214
|
+
build_project(project=project, tb_client=client, watch=False, silent=True)
|
|
208
215
|
click.echo(FeedbackManager.info(message="✓ Done!"))
|
|
209
216
|
|
|
210
217
|
click.echo(FeedbackManager.highlight(message="\n» Running tests"))
|
|
@@ -268,6 +275,8 @@ def run_tests(ctx: click.Context, name: Tuple[str, ...]) -> None:
|
|
|
268
275
|
click.echo(FeedbackManager.success(message=f"\n✓ {test_count}/{test_count} passed"))
|
|
269
276
|
except Exception as e:
|
|
270
277
|
raise CLITestException(FeedbackManager.error(message=str(e)))
|
|
278
|
+
finally:
|
|
279
|
+
cleanup_test_workspace(client, project.folder)
|
|
271
280
|
|
|
272
281
|
|
|
273
282
|
async def get_pipe_data(client: TinyB, pipe_name: str, test_params: str) -> Response:
|
|
@@ -301,3 +310,22 @@ def get_pipe_path(name_or_filename: str, folder: str) -> Path:
|
|
|
301
310
|
raise Exception(f"Pipe {name_or_filename} not found")
|
|
302
311
|
|
|
303
312
|
return pipe_path
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def cleanup_test_workspace(client: TinyB, path: str) -> None:
|
|
316
|
+
user_client = deepcopy(client)
|
|
317
|
+
try:
|
|
318
|
+
# ruff: noqa: ASYNC210
|
|
319
|
+
tokens = requests.get(f"{TB_LOCAL_ADDRESS}/tokens").json()
|
|
320
|
+
except Exception:
|
|
321
|
+
raise CLILocalException(
|
|
322
|
+
FeedbackManager.error(message="Tinybird local is not running. Please run `tb local start` first.")
|
|
323
|
+
)
|
|
324
|
+
try:
|
|
325
|
+
user_token = tokens["user_token"]
|
|
326
|
+
user_client.token = user_token
|
|
327
|
+
asyncio.run(
|
|
328
|
+
user_client.delete_workspace(get_test_workspace_name(path), hard_delete_confirmation="yes", version="v1")
|
|
329
|
+
)
|
|
330
|
+
except Exception:
|
|
331
|
+
pass
|
|
@@ -3,7 +3,7 @@ tinybird/context.py,sha256=FfqYfrGX_I7PKGTQo93utaKPDNVYWelg4Hsp3evX5wM,1291
|
|
|
3
3
|
tinybird/datatypes.py,sha256=r4WCvspmrXTJHiPjjyOTiZyZl31FO3Ynkwq4LQsYm6E,11059
|
|
4
4
|
tinybird/feedback_manager.py,sha256=a_ZhFX2zcB7vRknIcmHKMdQbb0c7TqlTBQ_5hPuWh88,69267
|
|
5
5
|
tinybird/git_settings.py,sha256=Sw_8rGmribEFJ4Z_6idrVytxpFYk7ez8ei0qHULzs3E,3934
|
|
6
|
-
tinybird/prompts.py,sha256=
|
|
6
|
+
tinybird/prompts.py,sha256=yLXzHB7_P0zjriIvI9UsfnIRwmcwLSEA1tcJMzYJqjw,36456
|
|
7
7
|
tinybird/sql.py,sha256=C_B81wwv3BsqyXGhF5oTk9DcTUkrp7NwIFqSzd3Dmjc,47854
|
|
8
8
|
tinybird/sql_template.py,sha256=mK0yeRFctbXTAu0VNMjIzoFBJoh9PoniAVgEatA5SG4,99832
|
|
9
9
|
tinybird/sql_template_fmt.py,sha256=KUHdj5rYCYm_rKKdXYSJAE9vIyXUQLB0YSZnUXHeBlY,10196
|
|
@@ -12,7 +12,7 @@ tinybird/syncasync.py,sha256=IPnOx6lMbf9SNddN1eBtssg8vCLHMt76SuZ6YNYm-Yk,27761
|
|
|
12
12
|
tinybird/tornado_template.py,sha256=jjNVDMnkYFWXflmT8KU_Ssbo5vR8KQq3EJMk5vYgXRw,41959
|
|
13
13
|
tinybird/ch_utils/constants.py,sha256=aYvg2C_WxYWsnqPdZB1ZFoIr8ZY-XjUXYyHKE9Ansj0,3890
|
|
14
14
|
tinybird/ch_utils/engine.py,sha256=BZuPM7MFS7vaEKK5tOMR2bwSAgJudPrJt27uVEwZmTY,40512
|
|
15
|
-
tinybird/tb/__cli__.py,sha256=
|
|
15
|
+
tinybird/tb/__cli__.py,sha256=GgehmhHmo8VV_VXA3EVctUEaD_qi0Fd6UJAECARm81o,252
|
|
16
16
|
tinybird/tb/check_pypi.py,sha256=rW4QmDRbtgKdUUwJCnBkVjmTjZSZGN-XgZhx7vMkC0w,1009
|
|
17
17
|
tinybird/tb/cli.py,sha256=uPV6pvi4aYVfaiGs0DQO-eoi1g9dHlrgvhutkXkdJko,1075
|
|
18
18
|
tinybird/tb/client.py,sha256=aaPKq5C77e72kR7IMv9WrvnvNki8mKMOTi9EsCp0eUc,55962
|
|
@@ -20,15 +20,15 @@ tinybird/tb/config.py,sha256=jT9xndpeCY_g0HdB5qE2EquC0TFRRnkPnQFWZWd04jo,3998
|
|
|
20
20
|
tinybird/tb/modules/auth.py,sha256=_OeYnmTH83lnqCgQEdS6K0bx1KBUeRmZk2M7JnRmWpk,9037
|
|
21
21
|
tinybird/tb/modules/build.py,sha256=5SX59ssq0KaRrgzk21KmYUnB6xOdQ_O59n7rxFBQQ1Y,17393
|
|
22
22
|
tinybird/tb/modules/cicd.py,sha256=Cn1DyE28w2maQgIJF4IjZU7J7ULPvMG11DjN2OH-cqE,7161
|
|
23
|
-
tinybird/tb/modules/cli.py,sha256=
|
|
23
|
+
tinybird/tb/modules/cli.py,sha256=AJooz6uiluC7eMO2ZlXluWL-NNLwTKb9kqkv3yqg6S4,14227
|
|
24
24
|
tinybird/tb/modules/common.py,sha256=WzF_zRtAl3FKqbzK6yi_IjeeGIjQNu6SKnP-PX-o3Kk,85196
|
|
25
25
|
tinybird/tb/modules/config.py,sha256=ziqW_t_mRVvWOd85VoB4vKyvgMkEfpXDf9H4v38p2xc,11422
|
|
26
26
|
tinybird/tb/modules/connection.py,sha256=7oOR7x4PhBcm1ETFFCH2YJ_3oeGXjAbmx1cnZX9_L70,9014
|
|
27
27
|
tinybird/tb/modules/copy.py,sha256=2Mm4FWKehOG7CoOhiF1m9UZJgJn0W1_cMolqju8ONYg,5805
|
|
28
|
-
tinybird/tb/modules/create.py,sha256=
|
|
28
|
+
tinybird/tb/modules/create.py,sha256=OHUvuHuvP0iecPPGI4eVOHOgR20qy7a_Sw7sbJKuG8g,17411
|
|
29
29
|
tinybird/tb/modules/datasource.py,sha256=V314rkpdVxVMjsp5qcSCTqDlmp4Vu--qM07BoWh-aqs,17783
|
|
30
30
|
tinybird/tb/modules/deployment.py,sha256=T0lwhAT8FwZZcRnA-JDMfPUrj5MOXcQ8blxYIK2igbc,24363
|
|
31
|
-
tinybird/tb/modules/deprecations.py,sha256=
|
|
31
|
+
tinybird/tb/modules/deprecations.py,sha256=nI_VPCB0Seyhlk2Foomoj3oUnx6GV_8Q5DMYVDi9L-o,3751
|
|
32
32
|
tinybird/tb/modules/endpoint.py,sha256=XySDt3pk66vxOZ0egUfz4bY8bEk3BjOXkv-L0OIJ3sc,12083
|
|
33
33
|
tinybird/tb/modules/exceptions.py,sha256=5jK91w1LPmtqIUfDpHe_Op5OxGz8-p1BPgtLREMIni0,5217
|
|
34
34
|
tinybird/tb/modules/feedback_manager.py,sha256=NoflMdTcUs6JF2IUZS8TatItxWDNCfwaIJnKtbY8e3w,77447
|
|
@@ -37,20 +37,20 @@ tinybird/tb/modules/job.py,sha256=n4dSSBgnA8NqD7srGahf2xRj6wxkmX9Vl0J-QJ_a2w0,29
|
|
|
37
37
|
tinybird/tb/modules/llm.py,sha256=KfsCYmKeW1VQz0iDZhGKCRkQv_Y3kTHh6JuxvofOguE,1076
|
|
38
38
|
tinybird/tb/modules/llm_utils.py,sha256=nS9r4FAElJw8yXtmdYrx-rtI2zXR8qXfi1QqUDCfxvg,3469
|
|
39
39
|
tinybird/tb/modules/local.py,sha256=kxdF8NXZYYwtUwlFHxHKq_PA9CpMrG-rXOg_i_hlvnY,12158
|
|
40
|
-
tinybird/tb/modules/local_common.py,sha256=
|
|
40
|
+
tinybird/tb/modules/local_common.py,sha256=jNbVG_nk5sNduPo3JDSNtop1H2X1Tdd5j4q3xXUR6W8,3965
|
|
41
41
|
tinybird/tb/modules/login.py,sha256=fmXPSdvJnKPv03chptGuu3_Fm6LhP6kUsUKhrmT8rJc,8269
|
|
42
42
|
tinybird/tb/modules/logout.py,sha256=ULooy1cDBD02-r7voZmhV7udA0ML5tVuflJyShrh56Y,1022
|
|
43
43
|
tinybird/tb/modules/materialization.py,sha256=QJX5kCPhhm6IXBO1JsalVfbQdypCe_eOUDZ_WHJZWS8,5478
|
|
44
|
-
tinybird/tb/modules/mock.py,sha256=
|
|
44
|
+
tinybird/tb/modules/mock.py,sha256=z_mYNVAu5aeq-5qGB0kSkliOX4j62fgUuLi1-ZcTamA,5304
|
|
45
45
|
tinybird/tb/modules/open.py,sha256=OuctINN77oexpSjth9uoIZPCelKO4Li-yyVxeSnk1io,1371
|
|
46
46
|
tinybird/tb/modules/pipe.py,sha256=AQKEDagO6e3psPVjJkS_MDbn8aK-apAiLp26k7jgAV0,2432
|
|
47
|
-
tinybird/tb/modules/project.py,sha256=
|
|
47
|
+
tinybird/tb/modules/project.py,sha256=vjw9RB3XcRWqj0izWbYSiTKqzP2n9QdIDXTu8QoRcK0,3502
|
|
48
48
|
tinybird/tb/modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
|
|
49
49
|
tinybird/tb/modules/secret.py,sha256=WsqzxxLh9W_jkuHL2JofMXdIJy0lT5WEI-7bQSIDgAc,2921
|
|
50
50
|
tinybird/tb/modules/shell.py,sha256=Zd_4Ak_5tKVX-cw6B4ag36xZeEGHeh-jZpAsIXkoMoE,14116
|
|
51
51
|
tinybird/tb/modules/table.py,sha256=4XrtjM-N0zfNtxVkbvLDQQazno1EPXnxTyo7llivfXk,11035
|
|
52
52
|
tinybird/tb/modules/telemetry.py,sha256=IHHks8-jnrkyQIY_Y6ZmU8hdVHMGSS0pkSUOgCPcYY8,11346
|
|
53
|
-
tinybird/tb/modules/test.py,sha256=
|
|
53
|
+
tinybird/tb/modules/test.py,sha256=Yopg89cRwOQpgRzsb9nvu2Z-UR2as2vBjVa5PF3uiK0,13420
|
|
54
54
|
tinybird/tb/modules/token.py,sha256=2fmKwu10_M0pqs6YmJVeILR9ZQB0ejRAET86agASbKM,13488
|
|
55
55
|
tinybird/tb/modules/watch.py,sha256=_92co0BjTikQuy7MbHr4TDu9A75QdHsrAO8v7DlYLg4,8898
|
|
56
56
|
tinybird/tb/modules/workspace.py,sha256=SlK08psp0tu5t_URHyIczm696buW6KD6FPs9Lg1aNRE,6614
|
|
@@ -59,7 +59,7 @@ tinybird/tb/modules/datafile/build.py,sha256=d_h3pRFDPFrDKGhpFx2iejY25GuB2k8yfNo
|
|
|
59
59
|
tinybird/tb/modules/datafile/build_common.py,sha256=LU24kAQmxDJIyoIapDaYG-SU3P4FrMG9UBf8m9PgVSI,4565
|
|
60
60
|
tinybird/tb/modules/datafile/build_datasource.py,sha256=nXEQ0qHdq2ai7jJTv8H2d7eeDPBYzLn8VY7zMtOYb8M,17382
|
|
61
61
|
tinybird/tb/modules/datafile/build_pipe.py,sha256=6Cwjf3BKEF3-oQ9PipsQfK-Z43nSwtA4qJAUoysI7Uc,11385
|
|
62
|
-
tinybird/tb/modules/datafile/common.py,sha256=
|
|
62
|
+
tinybird/tb/modules/datafile/common.py,sha256=1xM8R2NVmk8uQpU910Iqp_YGM1SHYoXaLZgjBYIJl54,89771
|
|
63
63
|
tinybird/tb/modules/datafile/diff.py,sha256=MTmj53RYjER4neLgWVjabn-FKVFgh8h8uYiBo55lFQg,6757
|
|
64
64
|
tinybird/tb/modules/datafile/exceptions.py,sha256=8rw2umdZjtby85QbuRKFO5ETz_eRHwUY5l7eHsy1wnI,556
|
|
65
65
|
tinybird/tb/modules/datafile/fixture.py,sha256=DrRWivcvo_1rn7LlVUnHcXccdgx9yVj63mzBkUwCzk8,1420
|
|
@@ -79,8 +79,8 @@ tinybird/tb_cli_modules/config.py,sha256=IsgdtFRnUrkY8-Zo32lmk6O7u3bHie1QCxLwgp4
|
|
|
79
79
|
tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
|
|
80
80
|
tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
|
|
81
81
|
tinybird/tb_cli_modules/telemetry.py,sha256=Hh2Io8ZPROSunbOLuMvuIFU4TqwWPmQTqal4WS09K1A,10449
|
|
82
|
-
tinybird-0.0.1.
|
|
83
|
-
tinybird-0.0.1.
|
|
84
|
-
tinybird-0.0.1.
|
|
85
|
-
tinybird-0.0.1.
|
|
86
|
-
tinybird-0.0.1.
|
|
82
|
+
tinybird-0.0.1.dev152.dist-info/METADATA,sha256=vHFPvsfjueEX_1WXokHN42243Qf31_7kRfUZqrwS2IA,1612
|
|
83
|
+
tinybird-0.0.1.dev152.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
84
|
+
tinybird-0.0.1.dev152.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
|
|
85
|
+
tinybird-0.0.1.dev152.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
|
|
86
|
+
tinybird-0.0.1.dev152.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|