tinybird 0.0.1.dev35__tar.gz → 0.0.1.dev37__tar.gz
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-0.0.1.dev35 → tinybird-0.0.1.dev37}/PKG-INFO +1 -1
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/client.py +1 -1
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/prompts.py +4 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/__cli__.py +2 -2
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/cli.py +1 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/build.py +66 -35
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/build_client.py +9 -15
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/cli.py +20 -105
- tinybird-0.0.1.dev37/tinybird/tb/modules/copy.py +68 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/create.py +4 -4
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/build.py +2 -2
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/deployment.py +23 -25
- tinybird-0.0.1.dev37/tinybird/tb/modules/llm.py +32 -0
- tinybird-0.0.1.dev37/tinybird/tb/modules/llm_utils.py +108 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/local_common.py +2 -2
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/mock.py +3 -4
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/pipe.py +3 -8
- tinybird-0.0.1.dev37/tinybird/tb/modules/project.py +44 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/shell.py +16 -33
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/test.py +2 -2
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/token.py +1 -1
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/update.py +4 -4
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/watch.py +18 -12
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird.egg-info/PKG-INFO +1 -1
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird.egg-info/SOURCES.txt +2 -0
- tinybird-0.0.1.dev35/tinybird/tb/modules/llm.py +0 -38
- tinybird-0.0.1.dev35/tinybird/tb/modules/llm_utils.py +0 -24
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/setup.cfg +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/__cli__.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/check_pypi.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/config.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/connectors.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/context.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/datafile.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/datatypes.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/git_settings.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/sql.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/sql_template.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/sql_toolset.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/syncasync.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/auth.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/common.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/config.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/common.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/exceptions.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/parse_datasource.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/parse_pipe.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/job.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/local.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/login.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/table.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/tag.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird/tornado_template.py +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-0.0.1.dev35 → tinybird-0.0.1.dev37}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -641,6 +641,7 @@ The previous instructions are explanations of how things work in Tinybird. Answe
|
|
|
641
641
|
|
|
642
642
|
datasource_instructions = """
|
|
643
643
|
<datasource_file_instructions>
|
|
644
|
+
- Content cannot be empty.
|
|
644
645
|
- The datasource names must be unique.
|
|
645
646
|
- No indentation is allowed for property names: DESCRIPTION, SCHEMA, ENGINE, ENGINE_PARTITION_KEY, ENGINE_SORTING_KEY, etc.
|
|
646
647
|
- Use MergeTree engine by default.
|
|
@@ -673,6 +674,7 @@ DESCRIPTION >
|
|
|
673
674
|
NODE node_1
|
|
674
675
|
SQL >
|
|
675
676
|
[sql query using clickhouse syntax and tinybird templating syntax and starting always with SELECT or %\nSELECT]
|
|
677
|
+
TYPE endpoint
|
|
676
678
|
|
|
677
679
|
</pipe_content>
|
|
678
680
|
"""
|
|
@@ -685,6 +687,7 @@ pipe_instructions = """
|
|
|
685
687
|
- Avoid more than one node per pipe unless it is really necessary or requested by the user.
|
|
686
688
|
- No indentation is allowed for property names: DESCRIPTION, NODE, SQL, TYPE, etc.
|
|
687
689
|
- Allowed TYPE values are: endpoint, copy, materialized, sink
|
|
690
|
+
- Add always the output node in the TYPE section.
|
|
688
691
|
</pipe_file_instructions>
|
|
689
692
|
"""
|
|
690
693
|
|
|
@@ -701,6 +704,7 @@ sql_instructions = """
|
|
|
701
704
|
</valid_query_with_parameters_with_%_on_top>
|
|
702
705
|
- The Parameter functions like this one {{{{String(my_param_name,default_value)}}}} can be one of the following: String, DateTime, Date, Float32, Float64, Int, Integer, UInt8, UInt16, UInt32, UInt64, UInt128, UInt256, Int8, Int16, Int32, Int64, Int128, Int256
|
|
703
706
|
- Parameter names must be different from column names. Pass always the param name and a default value to the function.
|
|
707
|
+
- Use ALWAYS hardcoded values for default values for parameters.
|
|
704
708
|
- Code inside the template {{{{template_expression}}}} follows the rules of Tornado templating language so no module is allowed to be imported. So for example you can't use now() as default value for a DateTime parameter. You need an if else block like this:
|
|
705
709
|
<invalid_condition_with_now>
|
|
706
710
|
AND timestamp BETWEEN {{DateTime(start_date, now() - interval 30 day)}} AND {{DateTime(end_date, now())}}
|
|
@@ -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.dev37'
|
|
8
|
+
__revision__ = '255b7f6'
|
|
@@ -9,6 +9,7 @@ import tinybird.tb.modules.build
|
|
|
9
9
|
import tinybird.tb.modules.build_client
|
|
10
10
|
import tinybird.tb.modules.cli
|
|
11
11
|
import tinybird.tb.modules.common
|
|
12
|
+
import tinybird.tb.modules.copy
|
|
12
13
|
import tinybird.tb.modules.create
|
|
13
14
|
import tinybird.tb.modules.datasource
|
|
14
15
|
import tinybird.tb.modules.deployment
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import glob
|
|
3
2
|
import json
|
|
4
3
|
import logging
|
|
5
4
|
import threading
|
|
6
5
|
import time
|
|
7
6
|
from pathlib import Path
|
|
8
|
-
from typing import
|
|
7
|
+
from typing import Optional
|
|
9
8
|
|
|
10
9
|
import click
|
|
11
10
|
import requests
|
|
@@ -13,55 +12,53 @@ import requests
|
|
|
13
12
|
from tinybird.client import TinyB
|
|
14
13
|
from tinybird.tb.modules.cli import cli
|
|
15
14
|
from tinybird.tb.modules.common import push_data
|
|
15
|
+
from tinybird.tb.modules.datafile.fixture import build_fixture_name, get_fixture_dir
|
|
16
16
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
17
17
|
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
18
|
+
from tinybird.tb.modules.project import Project
|
|
18
19
|
from tinybird.tb.modules.shell import Shell
|
|
19
20
|
from tinybird.tb.modules.watch import watch_project
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
@cli.command()
|
|
23
|
-
@click.option("--folder", type=str, default=".")
|
|
24
24
|
@click.option("--watch", is_flag=True, default=False, help="Watch for changes and rebuild automatically")
|
|
25
|
-
|
|
25
|
+
@click.pass_context
|
|
26
|
+
def build(ctx: click.Context, watch: bool) -> None:
|
|
26
27
|
"""
|
|
27
28
|
Validate and build the project server side.
|
|
28
29
|
"""
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
project: Project = ctx.ensure_object(dict)["project"]
|
|
32
|
+
tb_client = asyncio.run(get_tinybird_local_client(str(project.path)))
|
|
31
33
|
click.echo(FeedbackManager.highlight(message="\n» Building project..."))
|
|
32
34
|
|
|
33
|
-
def process() -> None:
|
|
34
|
-
build_project(folder, tb_client)
|
|
35
|
-
|
|
36
35
|
time_start = time.time()
|
|
36
|
+
|
|
37
|
+
def process(file_changed: Optional[str] = None) -> None:
|
|
38
|
+
if file_changed and file_changed.endswith(".ndjson"):
|
|
39
|
+
rebuild_fixture(project, tb_client, file_changed)
|
|
40
|
+
else:
|
|
41
|
+
build_project(project, tb_client)
|
|
42
|
+
|
|
37
43
|
process()
|
|
44
|
+
|
|
38
45
|
time_end = time.time()
|
|
39
46
|
elapsed_time = time_end - time_start
|
|
40
47
|
click.echo(FeedbackManager.success(message=f"\n✓ Build completed in {elapsed_time:.1f}s"))
|
|
41
48
|
|
|
42
49
|
if watch:
|
|
43
|
-
shell = Shell(
|
|
50
|
+
shell = Shell(project=project, client=tb_client)
|
|
44
51
|
click.echo(FeedbackManager.gray(message="\nWatching for changes..."))
|
|
45
52
|
watcher_thread = threading.Thread(
|
|
46
53
|
target=watch_project,
|
|
47
|
-
args=(shell, process,
|
|
54
|
+
args=(shell, process, project),
|
|
48
55
|
daemon=True,
|
|
49
56
|
)
|
|
50
57
|
watcher_thread.start()
|
|
51
58
|
shell.run()
|
|
52
59
|
|
|
53
60
|
|
|
54
|
-
def
|
|
55
|
-
project_file_extensions = ("datasource", "pipe")
|
|
56
|
-
project_files = []
|
|
57
|
-
for extension in project_file_extensions:
|
|
58
|
-
for project_file in glob.glob(f"{project_path}/**/*.{extension}", recursive=True):
|
|
59
|
-
logging.debug(f"Found project file: {project_file}")
|
|
60
|
-
project_files.append(project_file)
|
|
61
|
-
return project_files
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def build_project(folder: str, tb_client: TinyB) -> None:
|
|
61
|
+
def build_project(project: Project, tb_client: TinyB) -> None:
|
|
65
62
|
MULTIPART_BOUNDARY_DATA_PROJECT = "data_project://"
|
|
66
63
|
DATAFILE_TYPE_TO_CONTENT_TYPE = {
|
|
67
64
|
".datasource": "text/plain",
|
|
@@ -75,8 +72,8 @@ def build_project(folder: str, tb_client: TinyB) -> None:
|
|
|
75
72
|
("context://", ("cli-version", "1.0.0", "text/plain")),
|
|
76
73
|
]
|
|
77
74
|
fds = []
|
|
78
|
-
project_path =
|
|
79
|
-
project_files = get_project_files(
|
|
75
|
+
project_path = project.path
|
|
76
|
+
project_files = project.get_project_files()
|
|
80
77
|
|
|
81
78
|
for file_path in project_files:
|
|
82
79
|
relative_path = str(Path(file_path).relative_to(project_path))
|
|
@@ -103,15 +100,29 @@ def build_project(folder: str, tb_client: TinyB) -> None:
|
|
|
103
100
|
for ds in datasources:
|
|
104
101
|
ds_path = next((p for p in project_files if p.endswith(ds.get("name") + ".datasource")), None)
|
|
105
102
|
if ds_path:
|
|
106
|
-
ds_path = ds_path.replace(f"{folder}/", "")
|
|
103
|
+
ds_path = ds_path.replace(f"{project.folder}/", "")
|
|
107
104
|
click.echo(FeedbackManager.info(message=f"✓ {ds_path} created"))
|
|
108
105
|
for pipe in pipes:
|
|
109
106
|
pipe_name = pipe.get("name")
|
|
110
107
|
pipe_path = next((p for p in project_files if p.endswith(pipe_name + ".pipe")), None)
|
|
111
108
|
if pipe_path:
|
|
112
|
-
pipe_path = pipe_path.replace(f"{folder}/", "")
|
|
109
|
+
pipe_path = pipe_path.replace(f"{project.folder}/", "")
|
|
113
110
|
click.echo(FeedbackManager.info(message=f"✓ {pipe_path} created"))
|
|
114
111
|
|
|
112
|
+
for filename in project_files:
|
|
113
|
+
if filename.endswith(".datasource"):
|
|
114
|
+
ds_path = Path(filename)
|
|
115
|
+
ds_name = ds_path.stem
|
|
116
|
+
name = build_fixture_name(filename, ds_name, ds_path.read_text())
|
|
117
|
+
fixture_folder = get_fixture_dir(project.folder)
|
|
118
|
+
fixture_path = fixture_folder / f"{name}.ndjson"
|
|
119
|
+
|
|
120
|
+
if not fixture_path.exists():
|
|
121
|
+
fixture_path = fixture_folder / f"{ds_name}.ndjson"
|
|
122
|
+
|
|
123
|
+
if fixture_path.exists():
|
|
124
|
+
append_fixture(tb_client, ds_name, str(fixture_path))
|
|
125
|
+
|
|
115
126
|
elif build_result == "failed":
|
|
116
127
|
click.echo(FeedbackManager.error(message="Build failed"))
|
|
117
128
|
build_errors = result.get("errors")
|
|
@@ -121,24 +132,44 @@ def build_project(folder: str, tb_client: TinyB) -> None:
|
|
|
121
132
|
click.echo(FeedbackManager.error(message=error_msg))
|
|
122
133
|
else:
|
|
123
134
|
click.echo(FeedbackManager.error(message=f"Unknown build result. Error: {result.get('error')}"))
|
|
135
|
+
|
|
124
136
|
except Exception as e:
|
|
125
|
-
click.echo(FeedbackManager.error_exception(error="Error
|
|
137
|
+
click.echo(FeedbackManager.error_exception(error="Error: " + str(e)))
|
|
126
138
|
finally:
|
|
127
139
|
for fd in fds:
|
|
128
140
|
fd.close()
|
|
129
141
|
|
|
130
142
|
|
|
131
|
-
|
|
143
|
+
def append_fixture(
|
|
132
144
|
tb_client: TinyB,
|
|
133
145
|
datasource_name: str,
|
|
134
146
|
url: str,
|
|
135
147
|
):
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
asyncio.run(tb_client.datasource_truncate(datasource_name))
|
|
149
|
+
asyncio.run(
|
|
150
|
+
push_data(
|
|
151
|
+
tb_client,
|
|
152
|
+
datasource_name,
|
|
153
|
+
url,
|
|
154
|
+
mode="append",
|
|
155
|
+
concurrency=1,
|
|
156
|
+
silent=True,
|
|
157
|
+
)
|
|
144
158
|
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def rebuild_fixture(project: Project, tb_client: TinyB, fixture_path: str) -> None:
|
|
162
|
+
fixture_path = Path(fixture_path)
|
|
163
|
+
datasources_path = Path(project.folder) / "datasources"
|
|
164
|
+
ds_name = fixture_path.stem
|
|
165
|
+
|
|
166
|
+
if ds_name not in project.datasources:
|
|
167
|
+
try:
|
|
168
|
+
ds_name = "_".join(fixture_path.stem.split("_")[:-1])
|
|
169
|
+
except Exception:
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
ds_path = datasources_path / f"{ds_name}.datasource"
|
|
173
|
+
|
|
174
|
+
if ds_path.exists():
|
|
175
|
+
append_fixture(tb_client, ds_name, str(fixture_path))
|
|
@@ -13,13 +13,14 @@ from tinybird.config import FeatureFlags
|
|
|
13
13
|
from tinybird.tb.modules.cli import cli
|
|
14
14
|
from tinybird.tb.modules.common import push_data
|
|
15
15
|
from tinybird.tb.modules.datafile.build import folder_build
|
|
16
|
-
from tinybird.tb.modules.datafile.common import
|
|
16
|
+
from tinybird.tb.modules.datafile.common import get_project_fixtures, has_internal_datafiles
|
|
17
17
|
from tinybird.tb.modules.datafile.exceptions import ParseException
|
|
18
18
|
from tinybird.tb.modules.datafile.fixture import build_fixture_name, get_fixture_dir
|
|
19
19
|
from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
|
|
20
20
|
from tinybird.tb.modules.datafile.parse_pipe import parse_pipe
|
|
21
21
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
22
22
|
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
23
|
+
from tinybird.tb.modules.project import Project
|
|
23
24
|
from tinybird.tb.modules.shell import Shell, print_table_formatted
|
|
24
25
|
from tinybird.tb.modules.watch import watch_files
|
|
25
26
|
|
|
@@ -45,9 +46,6 @@ def check_filenames(filenames: List[str]):
|
|
|
45
46
|
incl_suffix = ".incl"
|
|
46
47
|
|
|
47
48
|
for filename in filenames:
|
|
48
|
-
if os.path.isdir(filename):
|
|
49
|
-
check_filenames(filenames=get_project_filenames(filename))
|
|
50
|
-
|
|
51
49
|
file_suffix = Path(filename).suffix
|
|
52
50
|
if file_suffix == incl_suffix:
|
|
53
51
|
continue
|
|
@@ -60,23 +58,19 @@ def check_filenames(filenames: List[str]):
|
|
|
60
58
|
|
|
61
59
|
|
|
62
60
|
@cli.command()
|
|
63
|
-
@click.option(
|
|
64
|
-
"--folder",
|
|
65
|
-
default=".",
|
|
66
|
-
help="Folder from where to execute the command. By default the current folder.",
|
|
67
|
-
hidden=True,
|
|
68
|
-
type=click.types.STRING,
|
|
69
|
-
)
|
|
70
61
|
@click.option(
|
|
71
62
|
"--watch",
|
|
72
63
|
is_flag=True,
|
|
73
64
|
help="Watch for changes in the files and rebuild them.",
|
|
74
65
|
)
|
|
66
|
+
@click.pass_context
|
|
75
67
|
def build_client(
|
|
76
|
-
|
|
68
|
+
ctx: click.Context,
|
|
77
69
|
watch: bool,
|
|
78
70
|
) -> None:
|
|
79
71
|
"""Build the project in Tinybird Local."""
|
|
72
|
+
project: Project = ctx.ensure_object(dict)["project"]
|
|
73
|
+
folder = project.folder
|
|
80
74
|
ignore_sql_errors = FeatureFlags.ignore_sql_errors()
|
|
81
75
|
context.disable_template_security_validation.set(True)
|
|
82
76
|
is_internal = has_internal_datafiles(folder)
|
|
@@ -130,7 +124,7 @@ def build_client(
|
|
|
130
124
|
if not filename.endswith(".ndjson"):
|
|
131
125
|
await build_and_print_resource(tb_client, filename)
|
|
132
126
|
|
|
133
|
-
datafiles =
|
|
127
|
+
datafiles = project.get_project_files()
|
|
134
128
|
fixtures = get_project_fixtures(folder)
|
|
135
129
|
filenames = datafiles + fixtures
|
|
136
130
|
|
|
@@ -172,10 +166,10 @@ def build_client(
|
|
|
172
166
|
build_ok = asyncio.run(build_once(filenames))
|
|
173
167
|
|
|
174
168
|
if watch:
|
|
175
|
-
shell = Shell(
|
|
169
|
+
shell = Shell(project=project, client=tb_client)
|
|
176
170
|
click.echo(FeedbackManager.gray(message="\nWatching for changes..."))
|
|
177
171
|
watcher_thread = threading.Thread(
|
|
178
|
-
target=watch_files, args=(filenames, process, shell,
|
|
172
|
+
target=watch_files, args=(filenames, process, shell, project, build_ok), daemon=True
|
|
179
173
|
)
|
|
180
174
|
watcher_thread.start()
|
|
181
175
|
shell.run()
|
|
@@ -35,11 +35,7 @@ from tinybird.tb.modules.common import (
|
|
|
35
35
|
)
|
|
36
36
|
from tinybird.tb.modules.config import CLIConfig
|
|
37
37
|
from tinybird.tb.modules.datafile.build import build_graph
|
|
38
|
-
from tinybird.tb.modules.datafile.common import
|
|
39
|
-
Datafile,
|
|
40
|
-
DatafileSyntaxError,
|
|
41
|
-
get_project_filenames,
|
|
42
|
-
)
|
|
38
|
+
from tinybird.tb.modules.datafile.common import Datafile, DatafileSyntaxError
|
|
43
39
|
from tinybird.tb.modules.datafile.diff import diff_command
|
|
44
40
|
from tinybird.tb.modules.datafile.exceptions import (
|
|
45
41
|
ParseException,
|
|
@@ -50,6 +46,7 @@ from tinybird.tb.modules.datafile.pull import folder_pull
|
|
|
50
46
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
51
47
|
from tinybird.tb.modules.llm import LLM
|
|
52
48
|
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
49
|
+
from tinybird.tb.modules.project import Project
|
|
53
50
|
|
|
54
51
|
__old_click_echo = click.echo
|
|
55
52
|
__old_click_secho = click.secho
|
|
@@ -67,61 +64,17 @@ VERSION = f"{__cli__.__version__} (rev {__cli__.__revision__})"
|
|
|
67
64
|
)
|
|
68
65
|
@click.option("--token", help="Use auth token, defaults to TB_TOKEN envvar, then to the .tinyb file")
|
|
69
66
|
@click.option("--host", help="Use custom host, defaults to TB_HOST envvar, then to https://api.tinybird.co")
|
|
70
|
-
@click.option("--gcp-project-id", help="The Google Cloud project ID", hidden=True)
|
|
71
|
-
@click.option(
|
|
72
|
-
"--gcs-bucket", help="The Google Cloud Storage bucket to write temp files when using the connectors", hidden=True
|
|
73
|
-
)
|
|
74
|
-
@click.option(
|
|
75
|
-
"--google-application-credentials",
|
|
76
|
-
envvar="GOOGLE_APPLICATION_CREDENTIALS",
|
|
77
|
-
help="Set GOOGLE_APPLICATION_CREDENTIALS",
|
|
78
|
-
hidden=True,
|
|
79
|
-
)
|
|
80
|
-
@click.option("--sf-account", help="The Snowflake Account (e.g. your-domain.west-europe.azure)", hidden=True)
|
|
81
|
-
@click.option("--sf-warehouse", help="The Snowflake warehouse name", hidden=True)
|
|
82
|
-
@click.option("--sf-database", help="The Snowflake database name", hidden=True)
|
|
83
|
-
@click.option("--sf-schema", help="The Snowflake schema name", hidden=True)
|
|
84
|
-
@click.option("--sf-role", help="The Snowflake role name", hidden=True)
|
|
85
|
-
@click.option("--sf-user", help="The Snowflake user name", hidden=True)
|
|
86
|
-
@click.option("--sf-password", help="The Snowflake password", hidden=True)
|
|
87
|
-
@click.option(
|
|
88
|
-
"--sf-storage-integration",
|
|
89
|
-
help="The Snowflake GCS storage integration name (leave empty to auto-generate one)",
|
|
90
|
-
hidden=True,
|
|
91
|
-
)
|
|
92
|
-
@click.option("--sf-stage", help="The Snowflake GCS stage name (leave empty to auto-generate one)", hidden=True)
|
|
93
|
-
@click.option(
|
|
94
|
-
"--with-headers", help="Flag to enable connector to export with headers", is_flag=True, default=False, hidden=True
|
|
95
|
-
)
|
|
96
67
|
@click.option("--show-tokens", is_flag=True, default=False, help="Enable the output of tokens")
|
|
97
68
|
@click.option("--prod/--local", is_flag=True, default=False, help="Run against production or local")
|
|
69
|
+
@click.option("--folder", type=str, default=os.getcwd(), help="Folder where files will be placed")
|
|
98
70
|
@click.version_option(version=VERSION)
|
|
99
71
|
@click.pass_context
|
|
100
72
|
@coro
|
|
101
|
-
async def cli(
|
|
102
|
-
ctx: Context,
|
|
103
|
-
debug: bool,
|
|
104
|
-
token: str,
|
|
105
|
-
host: str,
|
|
106
|
-
gcp_project_id: str,
|
|
107
|
-
gcs_bucket: str,
|
|
108
|
-
google_application_credentials: str,
|
|
109
|
-
sf_account: str,
|
|
110
|
-
sf_warehouse: str,
|
|
111
|
-
sf_database: str,
|
|
112
|
-
sf_schema: str,
|
|
113
|
-
sf_role: str,
|
|
114
|
-
sf_user: str,
|
|
115
|
-
sf_password: str,
|
|
116
|
-
sf_storage_integration: str,
|
|
117
|
-
sf_stage,
|
|
118
|
-
with_headers: bool,
|
|
119
|
-
show_tokens: bool,
|
|
120
|
-
prod: bool,
|
|
121
|
-
) -> None:
|
|
73
|
+
async def cli(ctx: Context, debug: bool, token: str, host: str, show_tokens: bool, prod: bool, folder: str) -> None:
|
|
122
74
|
"""
|
|
123
75
|
Use `OBFUSCATE_REGEX_PATTERN` and `OBFUSCATE_PATTERN_SEPARATOR` environment variables to define a regex pattern and a separator (in case of a single string with multiple regex) to obfuscate secrets in the CLI output.
|
|
124
76
|
"""
|
|
77
|
+
project = Project(folder=folder)
|
|
125
78
|
# We need to unpatch for our tests not to break
|
|
126
79
|
if show_tokens or not prod or ctx.invoked_subcommand == "build":
|
|
127
80
|
__unpatch_click_output()
|
|
@@ -134,7 +87,7 @@ async def cli(
|
|
|
134
87
|
if debug:
|
|
135
88
|
logging.basicConfig(level=logging.DEBUG)
|
|
136
89
|
|
|
137
|
-
config_temp = CLIConfig.get_project_config()
|
|
90
|
+
config_temp = CLIConfig.get_project_config(project.path)
|
|
138
91
|
if token:
|
|
139
92
|
config_temp.set_token(token)
|
|
140
93
|
if host:
|
|
@@ -166,65 +119,27 @@ async def cli(
|
|
|
166
119
|
|
|
167
120
|
ctx.ensure_object(dict)["config"] = config
|
|
168
121
|
|
|
169
|
-
if ctx.invoked_subcommand == "auth":
|
|
170
|
-
return
|
|
171
|
-
|
|
172
|
-
from tinybird.connectors import create_connector
|
|
173
|
-
|
|
174
|
-
if gcp_project_id and gcs_bucket and google_application_credentials and not sf_account:
|
|
175
|
-
bq_config = {
|
|
176
|
-
"project_id": gcp_project_id,
|
|
177
|
-
"bucket_name": gcs_bucket,
|
|
178
|
-
"service_account": google_application_credentials,
|
|
179
|
-
"with_headers": with_headers,
|
|
180
|
-
}
|
|
181
|
-
ctx.ensure_object(dict)["bigquery"] = create_connector("bigquery", bq_config)
|
|
182
|
-
if (
|
|
183
|
-
sf_account
|
|
184
|
-
and sf_warehouse
|
|
185
|
-
and sf_database
|
|
186
|
-
and sf_schema
|
|
187
|
-
and sf_role
|
|
188
|
-
and sf_user
|
|
189
|
-
and sf_password
|
|
190
|
-
and gcs_bucket
|
|
191
|
-
and google_application_credentials
|
|
192
|
-
and gcp_project_id
|
|
193
|
-
):
|
|
194
|
-
sf_config = {
|
|
195
|
-
"account": sf_account,
|
|
196
|
-
"warehouse": sf_warehouse,
|
|
197
|
-
"database": sf_database,
|
|
198
|
-
"schema": sf_schema,
|
|
199
|
-
"role": sf_role,
|
|
200
|
-
"user": sf_user,
|
|
201
|
-
"password": sf_password,
|
|
202
|
-
"storage_integration": sf_storage_integration,
|
|
203
|
-
"stage": sf_stage,
|
|
204
|
-
"bucket_name": gcs_bucket,
|
|
205
|
-
"service_account": google_application_credentials,
|
|
206
|
-
"project_id": gcp_project_id,
|
|
207
|
-
"with_headers": with_headers,
|
|
208
|
-
}
|
|
209
|
-
ctx.ensure_object(dict)["snowflake"] = create_connector("snowflake", sf_config)
|
|
210
|
-
|
|
211
122
|
logging.debug("debug enabled")
|
|
212
123
|
|
|
213
|
-
skip_client = ctx.invoked_subcommand in ["login", "workspace", "local", "build"]
|
|
214
|
-
client = await create_ctx_client(config, prod, skip_client)
|
|
124
|
+
skip_client = ctx.invoked_subcommand in ["auth", "check", "login", "workspace", "local", "build"]
|
|
125
|
+
client = await create_ctx_client(config, prod, skip_client, project)
|
|
215
126
|
|
|
216
127
|
if client:
|
|
217
128
|
ctx.ensure_object(dict)["client"] = client
|
|
218
129
|
|
|
130
|
+
ctx.ensure_object(dict)["project"] = project
|
|
131
|
+
|
|
219
132
|
|
|
220
133
|
@cli.command(hidden=True)
|
|
221
134
|
@click.argument("filenames", type=click.Path(exists=True), nargs=-1, default=None)
|
|
222
135
|
@click.option("--debug", is_flag=True, default=False, help="Print internal representation")
|
|
223
|
-
|
|
136
|
+
@click.pass_context
|
|
137
|
+
def check(ctx: Context, filenames: List[str], debug: bool) -> None:
|
|
224
138
|
"""Check file syntax."""
|
|
225
139
|
|
|
226
140
|
if not filenames:
|
|
227
|
-
|
|
141
|
+
project: Project = ctx.ensure_object(dict)["project"]
|
|
142
|
+
filenames = project.get_project_files()
|
|
228
143
|
|
|
229
144
|
def process(filenames: Iterable):
|
|
230
145
|
parser_matrix = {".pipe": parse_pipe, ".datasource": parse_datasource}
|
|
@@ -232,7 +147,7 @@ def check(filenames: List[str], debug: bool) -> None:
|
|
|
232
147
|
try:
|
|
233
148
|
for filename in filenames:
|
|
234
149
|
if os.path.isdir(filename):
|
|
235
|
-
process(filenames=
|
|
150
|
+
process(filenames=filename)
|
|
236
151
|
|
|
237
152
|
click.echo(FeedbackManager.info_processing_file(filename=filename))
|
|
238
153
|
|
|
@@ -487,7 +402,7 @@ async def sql(
|
|
|
487
402
|
|
|
488
403
|
@cli.command(hidden=True)
|
|
489
404
|
@click.argument("prompt")
|
|
490
|
-
@click.option("--folder", default=
|
|
405
|
+
@click.option("--folder", default=os.getcwd(), help="The folder to use for the project")
|
|
491
406
|
@coro
|
|
492
407
|
async def ask(prompt: str, folder: str) -> None:
|
|
493
408
|
"""Ask things about your data project."""
|
|
@@ -529,8 +444,8 @@ async def ask(prompt: str, folder: str) -> None:
|
|
|
529
444
|
)
|
|
530
445
|
|
|
531
446
|
client = config.get_client()
|
|
532
|
-
llm = LLM(user_token=user_token,
|
|
533
|
-
click.echo(
|
|
447
|
+
llm = LLM(user_token=user_token, host=client.host)
|
|
448
|
+
click.echo(llm.ask(system_prompt=ask_prompt(resources_xml), prompt=prompt))
|
|
534
449
|
except Exception as e:
|
|
535
450
|
raise CLIException(FeedbackManager.error_exception(error=e))
|
|
536
451
|
|
|
@@ -572,11 +487,11 @@ def __unpatch_click_output():
|
|
|
572
487
|
click.secho = __old_click_secho
|
|
573
488
|
|
|
574
489
|
|
|
575
|
-
async def create_ctx_client(config: Dict[str, Any], prod: bool, skip_client: bool):
|
|
490
|
+
async def create_ctx_client(config: Dict[str, Any], prod: bool, skip_client: bool, project: Project):
|
|
576
491
|
if skip_client:
|
|
577
492
|
return None
|
|
578
493
|
|
|
579
494
|
if prod:
|
|
580
495
|
return _get_tb_client(config.get("token", None), config["host"])
|
|
581
496
|
|
|
582
|
-
return await get_tinybird_local_client()
|
|
497
|
+
return await get_tinybird_local_client(str(project.path))
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# This is a command file for our CLI. Please keep it clean.
|
|
2
|
+
#
|
|
3
|
+
# - If it makes sense and only when strictly necessary, you can create utility functions in this file.
|
|
4
|
+
# - But please, **do not** interleave utility functions and command definitions.
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
from click import Context
|
|
11
|
+
|
|
12
|
+
from tinybird.client import TinyB
|
|
13
|
+
from tinybird.tb.modules.cli import cli
|
|
14
|
+
from tinybird.tb.modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table
|
|
15
|
+
from tinybird.tb.modules.datafile.common import get_name_version
|
|
16
|
+
from tinybird.tb.modules.exceptions import CLIPipeException
|
|
17
|
+
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@cli.group(hidden=True)
|
|
21
|
+
@click.pass_context
|
|
22
|
+
def copy(ctx):
|
|
23
|
+
"""Copy pipe commands"""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@copy.command(name="ls")
|
|
27
|
+
@click.option("--match", default=None, help="Retrieve any resourcing matching the pattern. eg --match _test")
|
|
28
|
+
@click.option(
|
|
29
|
+
"--format",
|
|
30
|
+
"format_",
|
|
31
|
+
type=click.Choice(["json"], case_sensitive=False),
|
|
32
|
+
default=None,
|
|
33
|
+
help="Force a type of the output",
|
|
34
|
+
)
|
|
35
|
+
@click.pass_context
|
|
36
|
+
@coro
|
|
37
|
+
async def copy_ls(ctx: Context, match: str, format_: str):
|
|
38
|
+
"""List copy pipes"""
|
|
39
|
+
|
|
40
|
+
client: TinyB = ctx.ensure_object(dict)["client"]
|
|
41
|
+
pipes = await client.pipes(dependencies=False, node_attrs="name", attrs="name,updated_at")
|
|
42
|
+
copies = [p for p in pipes if p.get("type") == "copy"]
|
|
43
|
+
copies = sorted(copies, key=lambda p: p["updated_at"])
|
|
44
|
+
columns = ["name", "updated at", "nodes", "url"]
|
|
45
|
+
table_human_readable = []
|
|
46
|
+
table_machine_readable = []
|
|
47
|
+
pattern = re.compile(match) if match else None
|
|
48
|
+
for t in copies:
|
|
49
|
+
tk = get_name_version(t["name"])
|
|
50
|
+
if pattern and not pattern.search(tk["name"]):
|
|
51
|
+
continue
|
|
52
|
+
table_human_readable.append((tk["name"], t["updated_at"][:-7], len(t["nodes"])))
|
|
53
|
+
table_machine_readable.append(
|
|
54
|
+
{
|
|
55
|
+
"name": tk["name"],
|
|
56
|
+
"updated at": t["updated_at"][:-7],
|
|
57
|
+
"nodes": len(t["nodes"]),
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if not format_:
|
|
62
|
+
click.echo(FeedbackManager.info_pipes())
|
|
63
|
+
echo_safe_humanfriendly_tables_format_smart_table(table_human_readable, column_names=columns)
|
|
64
|
+
click.echo("\n")
|
|
65
|
+
elif format_ == "json":
|
|
66
|
+
click.echo(json.dumps({"pipes": table_machine_readable}, indent=2))
|
|
67
|
+
else:
|
|
68
|
+
raise CLIPipeException(FeedbackManager.error_pipe_ls_type())
|
|
@@ -103,13 +103,13 @@ async def create(
|
|
|
103
103
|
datasource_files = [f for f in os.listdir(Path(folder) / "datasources") if f.endswith(".datasource")]
|
|
104
104
|
for datasource_file in datasource_files:
|
|
105
105
|
datasource_path = Path(folder) / "datasources" / datasource_file
|
|
106
|
-
llm = LLM(user_token=user_token,
|
|
106
|
+
llm = LLM(user_token=user_token, host=tb_client.host)
|
|
107
107
|
datasource_name = datasource_path.stem
|
|
108
108
|
datasource_content = datasource_path.read_text()
|
|
109
109
|
has_json_path = "`json:" in datasource_content
|
|
110
110
|
if has_json_path:
|
|
111
111
|
prompt = f"<datasource_schema>{datasource_content}</datasource_schema>\n<user_input>{prompt}</user_input>"
|
|
112
|
-
response =
|
|
112
|
+
response = llm.ask(system_prompt=mock_prompt(rows), prompt=prompt)
|
|
113
113
|
sql = extract_xml(response, "sql")
|
|
114
114
|
sql = sql.split("FORMAT")[0]
|
|
115
115
|
result = await local_client.query(f"{sql} FORMAT JSON")
|
|
@@ -205,8 +205,8 @@ TYPE ENDPOINT
|
|
|
205
205
|
]
|
|
206
206
|
]
|
|
207
207
|
)
|
|
208
|
-
llm = LLM(user_token=user_token,
|
|
209
|
-
result =
|
|
208
|
+
llm = LLM(user_token=user_token, host=tb_client.host)
|
|
209
|
+
result = llm.ask(system_prompt=create_prompt(resources_xml), prompt=prompt)
|
|
210
210
|
result = extract_xml(result, "response")
|
|
211
211
|
resources = parse_xml(result, "resource")
|
|
212
212
|
datasources = []
|
|
@@ -44,7 +44,7 @@ from tinybird.tb.modules.datafile.exceptions import AlreadyExistsException, Incl
|
|
|
44
44
|
from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
|
|
45
45
|
from tinybird.tb.modules.datafile.parse_pipe import parse_pipe
|
|
46
46
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
47
|
-
from tinybird.tb.modules.local_common import
|
|
47
|
+
from tinybird.tb.modules.local_common import get_tinybird_local_config
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
async def folder_build(
|
|
@@ -58,7 +58,7 @@ async def folder_build(
|
|
|
58
58
|
local_ws: Optional[Dict[str, Any]] = None,
|
|
59
59
|
watch: bool = False,
|
|
60
60
|
):
|
|
61
|
-
config = await
|
|
61
|
+
config = await get_tinybird_local_config(folder)
|
|
62
62
|
build = True
|
|
63
63
|
dry_run = False
|
|
64
64
|
force = True
|