tinybird 0.0.1.dev30__tar.gz → 0.0.1.dev31__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.dev30 → tinybird-0.0.1.dev31}/PKG-INFO +1 -1
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/__cli__.py +2 -2
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/config.py +1 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/context.py +1 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/sql_template.py +21 -2
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/__cli__.py +2 -2
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/build.py +48 -21
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/cli.py +8 -7
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/create.py +2 -2
- tinybird-0.0.1.dev31/tinybird/tb/modules/llm.py +38 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/local_common.py +1 -1
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/mock.py +1 -1
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/shell.py +28 -33
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/test.py +1 -1
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/update.py +2 -2
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/watch.py +76 -1
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird.egg-info/PKG-INFO +1 -1
- tinybird-0.0.1.dev30/tinybird/tb/modules/llm.py +0 -120
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/setup.cfg +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/check_pypi.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/client.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/connectors.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/datafile.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/datatypes.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/git_settings.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/prompts.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/sql.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/sql_toolset.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/syncasync.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/cli.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/auth.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/build_client.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/common.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/config.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/common.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/exceptions.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/parse_datasource.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/parse_pipe.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/deploy.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/job.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/local.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/login.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/table.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/tag.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/token.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tornado_template.py +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
__name__ = "
|
|
1
|
+
__name__ = "tinybird_cli"
|
|
2
2
|
__description__ = "Tinybird Command Line Tool"
|
|
3
|
-
__url__ = "https://www.tinybird.co/docs/cli
|
|
3
|
+
__url__ = "https://www.tinybird.co/docs/cli"
|
|
4
4
|
__author__ = "Tinybird"
|
|
5
5
|
__author_email__ = "support@tinybird.co"
|
|
6
6
|
__version__ = "x.y.z"
|
|
@@ -29,6 +29,7 @@ LEGACY_HOSTS = {
|
|
|
29
29
|
"https://api.us-east.aws.tinybird.co": "https://app.tinybird.co/aws/us-east-1",
|
|
30
30
|
"https://api.us-west-2.aws.tinybird.co": "https://app.tinybird.co/aws/us-west-2",
|
|
31
31
|
"https://api.eu-central-1.aws.tinybird.co": "https://app.tinybird.co/aws/eu-central-1",
|
|
32
|
+
"https://api.eu-west-1.aws.tinybird.co": "https://app.tinybird.co/aws/eu-west-1",
|
|
32
33
|
"https://api.ap-east.aws.tinybird.co": "https://app.tinybird.co/aws/ap-east",
|
|
33
34
|
"https://api.wadus1.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus1",
|
|
34
35
|
"https://api.wadus2.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus2",
|
|
@@ -21,3 +21,4 @@ wait_parameter: ContextVar[bool] = ContextVar("wait_parameter")
|
|
|
21
21
|
api_host: ContextVar[str] = ContextVar("api_host")
|
|
22
22
|
ff_split_to_array_escape: ContextVar[bool] = ContextVar("ff_split_to_array_escape")
|
|
23
23
|
ff_preprocess_parameters_circuit_breaker: ContextVar[bool] = ContextVar("ff_preprocess_parameters_circuit_breaker")
|
|
24
|
+
ff_column_json_backticks_circuit_breaker: ContextVar[bool] = ContextVar("ff_column_json_backticks_circuit_breaker")
|
|
@@ -12,7 +12,11 @@ from typing import Any, Dict, List, Optional, Tuple, Union
|
|
|
12
12
|
from tornado import escape
|
|
13
13
|
from tornado.util import ObjectDict, exec_in, unicode_type
|
|
14
14
|
|
|
15
|
-
from tinybird.context import
|
|
15
|
+
from tinybird.context import (
|
|
16
|
+
ff_column_json_backticks_circuit_breaker,
|
|
17
|
+
ff_preprocess_parameters_circuit_breaker,
|
|
18
|
+
ff_split_to_array_escape,
|
|
19
|
+
)
|
|
16
20
|
|
|
17
21
|
from .datatypes import testers
|
|
18
22
|
from .tornado_template import VALID_CUSTOM_FUNCTION_NAMES, SecurityException, Template
|
|
@@ -271,6 +275,8 @@ def columns(x, default=None, fn=None):
|
|
|
271
275
|
|
|
272
276
|
|
|
273
277
|
def column(x, default=None):
|
|
278
|
+
bypass_colunn_json_backticks = ff_column_json_backticks_circuit_breaker.get(False)
|
|
279
|
+
|
|
274
280
|
if x is None or isinstance(x, Placeholder):
|
|
275
281
|
if default is None:
|
|
276
282
|
raise SQLTemplateException(
|
|
@@ -278,7 +284,18 @@ def column(x, default=None):
|
|
|
278
284
|
documentation="/cli/advanced-templates.html#column",
|
|
279
285
|
)
|
|
280
286
|
x = default
|
|
281
|
-
|
|
287
|
+
|
|
288
|
+
quote = "`"
|
|
289
|
+
if bypass_colunn_json_backticks:
|
|
290
|
+
return Symbol(quote + sqlescape(x) + quote)
|
|
291
|
+
|
|
292
|
+
try:
|
|
293
|
+
slices = x.split(".")
|
|
294
|
+
escaped_slices = [quote + sqlescape(s) + quote for s in slices]
|
|
295
|
+
escaped = ".".join(escaped_slices)
|
|
296
|
+
return Symbol(escaped)
|
|
297
|
+
except Exception: # in case there's a problem with .split
|
|
298
|
+
return Symbol(quote + sqlescape(x) + quote)
|
|
282
299
|
|
|
283
300
|
|
|
284
301
|
def symbol(x, quote="`"):
|
|
@@ -2109,6 +2126,8 @@ def render_sql_template(
|
|
|
2109
2126
|
('SELECT `foo`', {}, [])
|
|
2110
2127
|
>>> render_sql_template("SELECT {{column(agg)}}", {'agg': '"foo"'})
|
|
2111
2128
|
('SELECT `foo`', {}, [])
|
|
2129
|
+
>>> render_sql_template("SELECT {{column(agg)}}", {'agg': 'json.a'})
|
|
2130
|
+
('SELECT `json`.`a`', {}, [])
|
|
2112
2131
|
>>> render_sql_template('{% if not defined(test) %}error("This is an error"){% end %}', {})
|
|
2113
2132
|
('error("This is an error")', {}, [])
|
|
2114
2133
|
>>> render_sql_template('{% if not defined(test) %}custom_error({error: "This is an error"}){% end %}', {})
|
|
@@ -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.dev31'
|
|
8
|
+
__revision__ = '0e056e8'
|
|
@@ -2,18 +2,49 @@ import asyncio
|
|
|
2
2
|
import glob
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
|
+
import threading
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import List
|
|
7
8
|
|
|
8
9
|
import click
|
|
9
10
|
import requests
|
|
10
11
|
|
|
12
|
+
from tinybird.client import TinyB
|
|
11
13
|
from tinybird.tb.modules.cli import cli
|
|
12
14
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
13
15
|
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
16
|
+
from tinybird.tb.modules.shell import Shell
|
|
17
|
+
from tinybird.tb.modules.watch import watch_project
|
|
14
18
|
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
@cli.command()
|
|
21
|
+
@click.option("--folder", type=str, default=".")
|
|
22
|
+
@click.option("--watch", is_flag=True, default=False, help="Watch for changes and rebuild automatically")
|
|
23
|
+
def build(folder: str, watch: bool) -> None:
|
|
24
|
+
"""
|
|
25
|
+
Validate and build the project server side.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
tb_client = asyncio.run(get_tinybird_local_client(folder))
|
|
29
|
+
|
|
30
|
+
def process() -> None:
|
|
31
|
+
build_project(folder, tb_client)
|
|
32
|
+
|
|
33
|
+
process()
|
|
34
|
+
|
|
35
|
+
if watch:
|
|
36
|
+
shell = Shell(folder=folder, client=tb_client)
|
|
37
|
+
click.echo(FeedbackManager.gray(message="\nWatching for changes..."))
|
|
38
|
+
watcher_thread = threading.Thread(
|
|
39
|
+
target=watch_project,
|
|
40
|
+
args=(shell, process, folder),
|
|
41
|
+
daemon=True,
|
|
42
|
+
)
|
|
43
|
+
watcher_thread.start()
|
|
44
|
+
shell.run()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_project_files(project_path: Path) -> List[str]:
|
|
17
48
|
project_file_extensions = ("datasource", "pipe")
|
|
18
49
|
project_files = []
|
|
19
50
|
for extension in project_file_extensions:
|
|
@@ -23,38 +54,32 @@ def project_files(project_path: Path) -> List[str]:
|
|
|
23
54
|
return project_files
|
|
24
55
|
|
|
25
56
|
|
|
26
|
-
|
|
27
|
-
@click.argument("project_path", type=click.Path(exists=True), default=Path.cwd())
|
|
28
|
-
def build(project_path: Path) -> None:
|
|
29
|
-
"""
|
|
30
|
-
Validate and build the project server side.
|
|
31
|
-
"""
|
|
57
|
+
def build_project(folder: str, tb_client: TinyB) -> None:
|
|
32
58
|
MULTIPART_BOUNDARY_DATA_PROJECT = "data_project://"
|
|
33
59
|
DATAFILE_TYPE_TO_CONTENT_TYPE = {
|
|
34
60
|
".datasource": "text/plain",
|
|
35
61
|
".pipe": "text/plain",
|
|
36
62
|
}
|
|
37
|
-
|
|
38
|
-
tb_client = asyncio.run(get_tinybird_local_client(str(project_path)))
|
|
39
63
|
TINYBIRD_API_URL = tb_client.host + "/v1/build"
|
|
40
64
|
TINYBIRD_API_KEY = tb_client.token
|
|
41
|
-
|
|
42
|
-
files = [
|
|
43
|
-
("context://", ("cli-version", "1.0.0", "text/plain")),
|
|
44
|
-
]
|
|
45
|
-
fds = []
|
|
46
|
-
for file_path in project_files(project_path):
|
|
47
|
-
relative_path = str(Path(file_path).relative_to(project_path))
|
|
48
|
-
fd = open(file_path, "rb")
|
|
49
|
-
fds.append(fd)
|
|
50
|
-
content_type = DATAFILE_TYPE_TO_CONTENT_TYPE.get(Path(file_path).suffix, "application/unknown")
|
|
51
|
-
files.append((MULTIPART_BOUNDARY_DATA_PROJECT, (relative_path, fd.read().decode("utf-8"), content_type)))
|
|
52
|
-
|
|
53
65
|
try:
|
|
66
|
+
files = [
|
|
67
|
+
("context://", ("cli-version", "1.0.0", "text/plain")),
|
|
68
|
+
]
|
|
69
|
+
fds = []
|
|
70
|
+
project_path = Path(folder)
|
|
71
|
+
project_files = get_project_files(project_path)
|
|
72
|
+
for file_path in project_files:
|
|
73
|
+
relative_path = str(Path(file_path).relative_to(project_path))
|
|
74
|
+
fd = open(file_path, "rb")
|
|
75
|
+
fds.append(fd)
|
|
76
|
+
content_type = DATAFILE_TYPE_TO_CONTENT_TYPE.get(Path(file_path).suffix, "application/unknown")
|
|
77
|
+
files.append((MULTIPART_BOUNDARY_DATA_PROJECT, (relative_path, fd.read().decode("utf-8"), content_type)))
|
|
54
78
|
HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
|
|
55
79
|
|
|
56
80
|
r = requests.post(TINYBIRD_API_URL, files=files, headers=HEADERS)
|
|
57
81
|
result = r.json()
|
|
82
|
+
|
|
58
83
|
logging.debug(json.dumps(result, indent=2))
|
|
59
84
|
|
|
60
85
|
build_result = result.get("result")
|
|
@@ -69,6 +94,8 @@ def build(project_path: Path) -> None:
|
|
|
69
94
|
click.echo(FeedbackManager.error(message=error_msg))
|
|
70
95
|
else:
|
|
71
96
|
click.echo(FeedbackManager.error(message=f"Unknown build result. Error: {result.get('error')}"))
|
|
97
|
+
except Exception as e:
|
|
98
|
+
click.echo(FeedbackManager.error_exception(error="Error building project: " + str(e)))
|
|
72
99
|
finally:
|
|
73
100
|
for fd in fds:
|
|
74
101
|
fd.close()
|
|
@@ -210,7 +210,8 @@ async def cli(
|
|
|
210
210
|
|
|
211
211
|
logging.debug("debug enabled")
|
|
212
212
|
|
|
213
|
-
|
|
213
|
+
skip_client = ctx.invoked_subcommand in ["login", "workspace"]
|
|
214
|
+
client = await create_ctx_client(config, prod, skip_client)
|
|
214
215
|
|
|
215
216
|
if client:
|
|
216
217
|
ctx.ensure_object(dict)["client"] = client
|
|
@@ -529,7 +530,7 @@ async def ask(prompt: str, folder: str) -> None:
|
|
|
529
530
|
|
|
530
531
|
client = config.get_client()
|
|
531
532
|
llm = LLM(user_token=user_token, client=client)
|
|
532
|
-
click.echo(await llm.ask(
|
|
533
|
+
click.echo(await llm.ask(system_prompt=ask_prompt(resources_xml), prompt=prompt))
|
|
533
534
|
except Exception as e:
|
|
534
535
|
raise CLIException(FeedbackManager.error_exception(error=e))
|
|
535
536
|
|
|
@@ -571,11 +572,11 @@ def __unpatch_click_output():
|
|
|
571
572
|
click.secho = __old_click_secho
|
|
572
573
|
|
|
573
574
|
|
|
574
|
-
async def create_ctx_client(config: Dict[str, Any], prod: bool):
|
|
575
|
+
async def create_ctx_client(config: Dict[str, Any], prod: bool, skip_client: bool):
|
|
576
|
+
if skip_client:
|
|
577
|
+
return None
|
|
578
|
+
|
|
575
579
|
if prod:
|
|
576
580
|
return _get_tb_client(config.get("token", None), config["host"])
|
|
577
581
|
|
|
578
|
-
|
|
579
|
-
return await get_tinybird_local_client()
|
|
580
|
-
except Exception:
|
|
581
|
-
return None
|
|
582
|
+
return await get_tinybird_local_client()
|
|
@@ -109,7 +109,7 @@ async def create(
|
|
|
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 = await llm.ask(
|
|
112
|
+
response = await 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")
|
|
@@ -206,7 +206,7 @@ TYPE ENDPOINT
|
|
|
206
206
|
]
|
|
207
207
|
)
|
|
208
208
|
llm = LLM(user_token=user_token, client=tb_client)
|
|
209
|
-
result = await llm.ask(
|
|
209
|
+
result = await 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 = []
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from tinybird.client import TinyB
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LLM:
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
user_token: str,
|
|
11
|
+
client: TinyB,
|
|
12
|
+
):
|
|
13
|
+
self.user_client = deepcopy(client)
|
|
14
|
+
self.user_client.token = user_token
|
|
15
|
+
|
|
16
|
+
async def ask(self, system_prompt: str, prompt: Optional[str] = None) -> str:
|
|
17
|
+
"""
|
|
18
|
+
Calls the model with the given prompt and returns the response.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
system_prompt (str): The system prompt to send to the model.
|
|
22
|
+
prompt (str): The user prompt to send to the model.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
str: The response from the language model.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
data = {"system": system_prompt}
|
|
29
|
+
|
|
30
|
+
if prompt:
|
|
31
|
+
data["prompt"] = prompt
|
|
32
|
+
|
|
33
|
+
response = await self.user_client._req(
|
|
34
|
+
"/v0/llm",
|
|
35
|
+
method="POST",
|
|
36
|
+
data=data,
|
|
37
|
+
)
|
|
38
|
+
return response.get("result", "")
|
|
@@ -8,7 +8,7 @@ from tinybird.client import TinyB
|
|
|
8
8
|
from tinybird.tb.modules.config import CLIConfig
|
|
9
9
|
from tinybird.tb.modules.exceptions import CLIException
|
|
10
10
|
|
|
11
|
-
TB_IMAGE_NAME = "tinybirdco/tinybird-local:
|
|
11
|
+
TB_IMAGE_NAME = "tinybirdco/tinybird-local:beta"
|
|
12
12
|
TB_CONTAINER_NAME = "tinybird-local"
|
|
13
13
|
TB_LOCAL_PORT = int(os.getenv("TB_LOCAL_PORT", 80))
|
|
14
14
|
TB_LOCAL_HOST = f"http://localhost:{TB_LOCAL_PORT}"
|
|
@@ -66,7 +66,7 @@ async def mock(datasource: str, rows: int, prompt: str, folder: str) -> None:
|
|
|
66
66
|
llm = LLM(user_token=user_token, client=user_client)
|
|
67
67
|
tb_client = await get_tinybird_local_client(os.path.abspath(folder))
|
|
68
68
|
prompt = f"<datasource_schema>{datasource_content}</datasource_schema>\n<user_input>{prompt}</user_input>"
|
|
69
|
-
response = await llm.ask(
|
|
69
|
+
response = await llm.ask(system_prompt=mock_prompt(rows), prompt=prompt)
|
|
70
70
|
sql = extract_xml(response, "sql")
|
|
71
71
|
if os.environ.get("TB_DEBUG", "") != "":
|
|
72
72
|
logging.debug(sql)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import concurrent.futures
|
|
3
|
+
import glob
|
|
3
4
|
import os
|
|
4
5
|
import subprocess
|
|
5
6
|
import sys
|
|
7
|
+
from pathlib import Path
|
|
6
8
|
from typing import List
|
|
7
9
|
|
|
8
10
|
import click
|
|
@@ -21,17 +23,22 @@ from tinybird.tb.modules.table import format_table
|
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
class DynamicCompleter(Completer):
|
|
24
|
-
def __init__(self,
|
|
25
|
-
self.
|
|
26
|
-
self.shared_datasources = shared_datasources
|
|
27
|
-
self.endpoints = endpoints
|
|
28
|
-
self.pipes = pipes
|
|
26
|
+
def __init__(self, folder: str):
|
|
27
|
+
self.folder = folder
|
|
29
28
|
self.static_commands = ["create", "mock", "test", "select"]
|
|
30
29
|
self.test_commands = ["create", "run", "update"]
|
|
31
30
|
self.mock_flags = ["--prompt", "--rows"]
|
|
32
31
|
self.common_rows = ["10", "50", "100", "500", "1000"]
|
|
33
32
|
self.sql_keywords = ["select", "from", "where", "group by", "order by", "limit"]
|
|
34
33
|
|
|
34
|
+
@property
|
|
35
|
+
def datasources(self):
|
|
36
|
+
return [Path(f).stem for f in glob.glob(f"{self.folder}/**/*.datasource", recursive=True)]
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def pipes(self):
|
|
40
|
+
return [Path(f).stem for f in glob.glob(f"{self.folder}/**/*.pipe", recursive=True)]
|
|
41
|
+
|
|
35
42
|
def get_completions(self, document, complete_event):
|
|
36
43
|
text = document.text_before_cursor.strip()
|
|
37
44
|
words = text.split()
|
|
@@ -75,9 +82,9 @@ class DynamicCompleter(Completer):
|
|
|
75
82
|
if words[-1] == "from" or (
|
|
76
83
|
"from" in words and len(words) > words.index("from") + 1 and text_lower.endswith(" ")
|
|
77
84
|
):
|
|
78
|
-
for x in self.datasources
|
|
85
|
+
for x in self.datasources:
|
|
79
86
|
yield Completion(x, start_position=0, display=x, style="class:completion.datasource")
|
|
80
|
-
for x in self.
|
|
87
|
+
for x in self.pipes:
|
|
81
88
|
yield Completion(x, start_position=0, display=x, style="class:completion.pipe")
|
|
82
89
|
return
|
|
83
90
|
|
|
@@ -116,7 +123,7 @@ class DynamicCompleter(Completer):
|
|
|
116
123
|
yield Completion(cmd, start_position=0, display=cmd, style="class:completion.cmd")
|
|
117
124
|
return
|
|
118
125
|
elif len(words) == 2:
|
|
119
|
-
for cmd in self.
|
|
126
|
+
for cmd in self.pipes:
|
|
120
127
|
yield Completion(cmd, start_position=0, display=cmd, style="class:completion.pipe")
|
|
121
128
|
return
|
|
122
129
|
|
|
@@ -130,7 +137,7 @@ class DynamicCompleter(Completer):
|
|
|
130
137
|
style="class:completion.cmd",
|
|
131
138
|
)
|
|
132
139
|
|
|
133
|
-
for cmd in self.datasources
|
|
140
|
+
for cmd in self.datasources:
|
|
134
141
|
if cmd.startswith(current_word):
|
|
135
142
|
yield Completion(
|
|
136
143
|
cmd,
|
|
@@ -139,7 +146,7 @@ class DynamicCompleter(Completer):
|
|
|
139
146
|
style="class:completion.datasource",
|
|
140
147
|
)
|
|
141
148
|
|
|
142
|
-
for cmd in self.
|
|
149
|
+
for cmd in self.pipes:
|
|
143
150
|
if cmd.startswith(current_word):
|
|
144
151
|
yield Completion(
|
|
145
152
|
cmd,
|
|
@@ -176,26 +183,14 @@ def _(event):
|
|
|
176
183
|
|
|
177
184
|
|
|
178
185
|
class Shell:
|
|
179
|
-
def __init__(
|
|
180
|
-
self,
|
|
181
|
-
folder: str,
|
|
182
|
-
client: TinyB,
|
|
183
|
-
datasources: List[str],
|
|
184
|
-
shared_datasources: List[str],
|
|
185
|
-
pipes: List[str],
|
|
186
|
-
endpoints: List[str],
|
|
187
|
-
):
|
|
186
|
+
def __init__(self, folder: str, client: TinyB):
|
|
188
187
|
self.history = self.get_history()
|
|
189
188
|
self.folder = folder
|
|
190
189
|
self.client = client
|
|
191
|
-
self.datasources = datasources
|
|
192
|
-
self.shared_datasources = shared_datasources
|
|
193
|
-
self.pipes = pipes
|
|
194
|
-
self.endpoints = endpoints
|
|
195
190
|
self.prompt_message = "\ntb > "
|
|
196
191
|
self.commands = ["create", "mock", "test", "tb", "select"]
|
|
197
192
|
self.session: PromptSession = PromptSession(
|
|
198
|
-
completer=DynamicCompleter(
|
|
193
|
+
completer=DynamicCompleter(folder),
|
|
199
194
|
complete_style=CompleteStyle.COLUMN,
|
|
200
195
|
complete_while_typing=True,
|
|
201
196
|
history=self.history,
|
|
@@ -283,7 +278,7 @@ class Shell:
|
|
|
283
278
|
return
|
|
284
279
|
if arg.startswith("with") or arg.startswith("select"):
|
|
285
280
|
self.run_sql(argline)
|
|
286
|
-
elif len(arg.split()) == 1 and arg in self.
|
|
281
|
+
elif len(arg.split()) == 1 and arg in self.pipes + self.datasources:
|
|
287
282
|
self.run_sql(f"select * from {arg}")
|
|
288
283
|
else:
|
|
289
284
|
subprocess.run(f"tb {arg}", shell=True, text=True)
|
|
@@ -310,16 +305,16 @@ class Shell:
|
|
|
310
305
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
311
306
|
res = executor.submit(run_query_in_thread).result()
|
|
312
307
|
|
|
313
|
-
|
|
314
|
-
|
|
308
|
+
if isinstance(res, dict) and "error" in res:
|
|
309
|
+
click.echo(FeedbackManager.error_exception(error=res["error"]))
|
|
315
310
|
|
|
316
|
-
|
|
317
|
-
|
|
311
|
+
if isinstance(res, dict) and "data" in res and res["data"]:
|
|
312
|
+
print_table_formatted(res, "QUERY")
|
|
313
|
+
else:
|
|
314
|
+
click.echo(FeedbackManager.info_no_rows())
|
|
318
315
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
else:
|
|
322
|
-
click.echo(FeedbackManager.info_no_rows())
|
|
316
|
+
except Exception as e:
|
|
317
|
+
click.echo(FeedbackManager.error_exception(error=str(e)))
|
|
323
318
|
|
|
324
319
|
def reprint_prompt(self):
|
|
325
320
|
click.echo(f"{bcolors.OKGREEN}{self.prompt_message}{bcolors.ENDC}", nl=False)
|
|
@@ -111,7 +111,7 @@ async def test_create(name_or_filename: str, prompt: str, folder: str) -> None:
|
|
|
111
111
|
raise CLIException(FeedbackManager.error(message="No user token found"))
|
|
112
112
|
llm = LLM(user_token=user_token, client=config.get_client())
|
|
113
113
|
|
|
114
|
-
response_llm = await llm.ask(
|
|
114
|
+
response_llm = await llm.ask(system_prompt=system_prompt, prompt=prompt)
|
|
115
115
|
response_xml = extract_xml(response_llm, "response")
|
|
116
116
|
tests_content = parse_xml(response_xml, "test")
|
|
117
117
|
|
|
@@ -71,7 +71,7 @@ async def update(
|
|
|
71
71
|
has_json_path = "`json:" in datasource_content
|
|
72
72
|
if has_json_path:
|
|
73
73
|
prompt = f"<datasource_schema>{datasource_content}</datasource_schema>\n<user_input>{prompt}</user_input>"
|
|
74
|
-
response = await llm.ask(
|
|
74
|
+
response = await llm.ask(system_prompt=mock_prompt(rows=20), prompt=prompt)
|
|
75
75
|
sql = extract_xml(response, "sql")
|
|
76
76
|
sql = sql.split("FORMAT")[0]
|
|
77
77
|
result = await local_client.query(f"{sql} FORMAT JSON")
|
|
@@ -117,7 +117,7 @@ async def update_resources(
|
|
|
117
117
|
]
|
|
118
118
|
)
|
|
119
119
|
llm = LLM(user_token=user_token, client=tb_client)
|
|
120
|
-
result = await llm.ask(
|
|
120
|
+
result = await llm.ask(system_prompt=update_prompt(resources_xml), prompt=prompt)
|
|
121
121
|
result = extract_xml(result, "response")
|
|
122
122
|
resources = parse_xml(result, "resource")
|
|
123
123
|
datasources = []
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import os
|
|
3
3
|
import time
|
|
4
|
+
from pathlib import Path
|
|
4
5
|
from typing import Any, Callable, List, Optional, Union
|
|
5
6
|
|
|
6
7
|
import click
|
|
7
|
-
from watchdog.events import
|
|
8
|
+
from watchdog.events import (
|
|
9
|
+
DirDeletedEvent,
|
|
10
|
+
DirMovedEvent,
|
|
11
|
+
FileDeletedEvent,
|
|
12
|
+
FileMovedEvent,
|
|
13
|
+
FileSystemEventHandler,
|
|
14
|
+
PatternMatchingEventHandler,
|
|
15
|
+
)
|
|
8
16
|
from watchdog.observers import Observer
|
|
9
17
|
|
|
10
18
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
@@ -110,3 +118,70 @@ def watch_files(
|
|
|
110
118
|
observer.stop()
|
|
111
119
|
|
|
112
120
|
observer.join()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class WatchProjectHandler(PatternMatchingEventHandler):
|
|
124
|
+
def __init__(self, shell: Shell, folder: str, process: Callable[[List[str]], None]):
|
|
125
|
+
self.shell = shell
|
|
126
|
+
self.process = process
|
|
127
|
+
super().__init__(
|
|
128
|
+
patterns=[f"{folder}/**/*.datasource", f"{folder}/**/*.pipe"],
|
|
129
|
+
ignore_patterns=[f"{folder}/vendor/"],
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
def should_process(self, event: Any) -> Optional[str]:
|
|
133
|
+
if event.is_directory:
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
if os.path.exists(event.src_path):
|
|
137
|
+
return event.src_path
|
|
138
|
+
|
|
139
|
+
if os.path.exists(event.dest_path):
|
|
140
|
+
return event.dest_path
|
|
141
|
+
|
|
142
|
+
return event.src_path
|
|
143
|
+
|
|
144
|
+
def _process(self) -> None:
|
|
145
|
+
click.echo(FeedbackManager.highlight(message="» Rebuilding..."))
|
|
146
|
+
time_start = time.time()
|
|
147
|
+
self.process()
|
|
148
|
+
time_end = time.time()
|
|
149
|
+
elapsed_time = time_end - time_start
|
|
150
|
+
click.echo(
|
|
151
|
+
FeedbackManager.success(message="\n✓ ")
|
|
152
|
+
+ FeedbackManager.gray(message=f"Rebuild completed in {elapsed_time:.1f}s")
|
|
153
|
+
)
|
|
154
|
+
self.shell.reprint_prompt()
|
|
155
|
+
|
|
156
|
+
def on_modified(self, event: Any) -> None:
|
|
157
|
+
if path := self.should_process(event):
|
|
158
|
+
filename = Path(path).name
|
|
159
|
+
click.echo(FeedbackManager.highlight(message=f"\n\n⟲ Changes detected in {filename}\n"))
|
|
160
|
+
self._process()
|
|
161
|
+
|
|
162
|
+
def on_deleted(self, event: Union[DirDeletedEvent, FileDeletedEvent]) -> None:
|
|
163
|
+
filename = Path(event.src_path).name
|
|
164
|
+
if event.is_directory:
|
|
165
|
+
click.echo(FeedbackManager.highlight(message=f"\n\n⟲ Deleted directory: {filename}\n"))
|
|
166
|
+
else:
|
|
167
|
+
click.echo(FeedbackManager.highlight(message=f"\n\n⟲ Deleted file: {filename}\n"))
|
|
168
|
+
self._process()
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def watch_project(
|
|
172
|
+
shell: Shell,
|
|
173
|
+
process: Callable,
|
|
174
|
+
folder: str,
|
|
175
|
+
) -> None:
|
|
176
|
+
event_handler = WatchProjectHandler(shell=shell, folder=folder, process=process)
|
|
177
|
+
observer = Observer()
|
|
178
|
+
observer.schedule(event_handler, path=folder, recursive=True)
|
|
179
|
+
observer.start()
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
while True:
|
|
183
|
+
time.sleep(1)
|
|
184
|
+
except KeyboardInterrupt:
|
|
185
|
+
observer.stop()
|
|
186
|
+
|
|
187
|
+
observer.join()
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import os
|
|
3
|
-
import urllib.parse
|
|
4
|
-
from copy import deepcopy
|
|
5
|
-
from typing import Any, List
|
|
6
|
-
|
|
7
|
-
from anthropic import AnthropicVertex
|
|
8
|
-
from pydantic import BaseModel
|
|
9
|
-
|
|
10
|
-
from tinybird.client import TinyB
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class DataFile(BaseModel):
|
|
14
|
-
name: str
|
|
15
|
-
content: str
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class DataProject(BaseModel):
|
|
19
|
-
datasources: List[DataFile]
|
|
20
|
-
pipes: List[DataFile]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class TestExpectation(BaseModel):
|
|
24
|
-
name: str
|
|
25
|
-
description: str
|
|
26
|
-
parameters: str
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class TestExpectations(BaseModel):
|
|
30
|
-
tests: List[TestExpectation]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class LLM:
|
|
34
|
-
def __init__(
|
|
35
|
-
self,
|
|
36
|
-
user_token: str,
|
|
37
|
-
client: TinyB,
|
|
38
|
-
):
|
|
39
|
-
self.user_client = deepcopy(client)
|
|
40
|
-
self.user_client.token = user_token
|
|
41
|
-
|
|
42
|
-
async def ask(self, prompt: str, system_prompt: str = "") -> str:
|
|
43
|
-
"""
|
|
44
|
-
Calls the model with the given prompt and returns the response.
|
|
45
|
-
|
|
46
|
-
Args:
|
|
47
|
-
prompt (str): The user prompt to send to the model.
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
str: The response from the language model.
|
|
51
|
-
"""
|
|
52
|
-
messages: List[Any] = []
|
|
53
|
-
|
|
54
|
-
if system_prompt:
|
|
55
|
-
messages.append({"role": "user", "content": system_prompt})
|
|
56
|
-
|
|
57
|
-
if prompt:
|
|
58
|
-
messages.append({"role": "user", "content": prompt})
|
|
59
|
-
|
|
60
|
-
if gcloud_access_token := os.getenv("GCLOUD_ACCESS_TOKEN"):
|
|
61
|
-
client = AnthropicVertex(
|
|
62
|
-
region="europe-west1",
|
|
63
|
-
project_id="gen-lang-client-0705305160",
|
|
64
|
-
access_token=gcloud_access_token,
|
|
65
|
-
)
|
|
66
|
-
message = client.messages.create(
|
|
67
|
-
max_tokens=8000,
|
|
68
|
-
messages=messages,
|
|
69
|
-
model="claude-3-5-sonnet-v2@20241022",
|
|
70
|
-
)
|
|
71
|
-
return message.content[0].text or "" # type: ignore
|
|
72
|
-
|
|
73
|
-
data = {
|
|
74
|
-
"model": "o1-mini",
|
|
75
|
-
"messages": messages,
|
|
76
|
-
}
|
|
77
|
-
response = await self.user_client._req(
|
|
78
|
-
"/v0/llm",
|
|
79
|
-
method="POST",
|
|
80
|
-
data=json.dumps(data),
|
|
81
|
-
headers={"Content-Type": "application/json"},
|
|
82
|
-
)
|
|
83
|
-
return response.get("result", "")
|
|
84
|
-
|
|
85
|
-
async def create_project(self, prompt: str) -> DataProject:
|
|
86
|
-
try:
|
|
87
|
-
prompt = (
|
|
88
|
-
prompt
|
|
89
|
-
+ "\n#More extra context\n- If you add some array data type remember that the json path should be like this: `json:$.array_field[:]`"
|
|
90
|
-
)
|
|
91
|
-
response = await self.user_client._req(
|
|
92
|
-
"/v0/llm/create",
|
|
93
|
-
method="POST",
|
|
94
|
-
data=f'{{"prompt": {json.dumps(prompt)}}}',
|
|
95
|
-
headers={"Content-Type": "application/json"},
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
return DataProject.model_validate(response.get("result", {}))
|
|
99
|
-
except Exception:
|
|
100
|
-
return DataProject(datasources=[], pipes=[])
|
|
101
|
-
|
|
102
|
-
async def generate_sql_sample_data(self, schema: str, rows: int = 20, prompt: str = "") -> str:
|
|
103
|
-
response = await self.user_client._req(
|
|
104
|
-
"/v0/llm/mock",
|
|
105
|
-
method="POST",
|
|
106
|
-
data=f'{{"schema": "{urllib.parse.quote(schema)}", "rows": {rows}, "context": "{prompt}"}}',
|
|
107
|
-
headers={"Content-Type": "application/json"},
|
|
108
|
-
)
|
|
109
|
-
result = response.get("result", "")
|
|
110
|
-
return result.replace("elementAt", "arrayElement")
|
|
111
|
-
|
|
112
|
-
async def create_tests(self, pipe_content: str, pipe_params: set[str], prompt: str = "") -> TestExpectations:
|
|
113
|
-
response = await self.user_client._req(
|
|
114
|
-
"/v0/llm/create/tests",
|
|
115
|
-
method="POST",
|
|
116
|
-
data=json.dumps({"pipe_content": pipe_content, "pipe_params": list(pipe_params), "prompt": prompt}),
|
|
117
|
-
headers={"Content-Type": "application/json"},
|
|
118
|
-
)
|
|
119
|
-
result = response.get("result", "")
|
|
120
|
-
return TestExpectations.model_validate(result)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/build_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/format_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb/modules/datafile/parse_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev30 → tinybird-0.0.1.dev31}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|