tinybird 0.0.1.dev32__tar.gz → 0.0.1.dev34__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.dev32 → tinybird-0.0.1.dev34}/PKG-INFO +1 -1
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/__cli__.py +2 -2
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/build.py +25 -2
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/build_client.py +1 -15
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/cli.py +1 -1
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/build.py +2 -2
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/common.py +63 -2
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/parse_datasource.py +7 -5
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/parse_pipe.py +7 -1
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/deploy.py +22 -19
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/local.py +15 -3
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/local_common.py +8 -2
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/mock.py +6 -1
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/test.py +3 -1
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/PKG-INFO +1 -1
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/setup.cfg +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/__cli__.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/check_pypi.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/client.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/config.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/connectors.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/context.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/datafile.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/datatypes.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/git_settings.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/prompts.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/sql.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/sql_template.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/sql_toolset.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/syncasync.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/cli.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/auth.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/common.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/config.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/create.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/exceptions.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/job.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/login.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/shell.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/table.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/tag.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/token.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/update.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tornado_template.py +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -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.dev34'
|
|
8
|
+
__revision__ = '08098c9'
|
|
@@ -11,6 +11,7 @@ import requests
|
|
|
11
11
|
|
|
12
12
|
from tinybird.client import TinyB
|
|
13
13
|
from tinybird.tb.modules.cli import cli
|
|
14
|
+
from tinybird.tb.modules.common import push_data
|
|
14
15
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
15
16
|
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
16
17
|
from tinybird.tb.modules.shell import Shell
|
|
@@ -61,6 +62,7 @@ def build_project(folder: str, tb_client: TinyB) -> None:
|
|
|
61
62
|
".pipe": "text/plain",
|
|
62
63
|
}
|
|
63
64
|
TINYBIRD_API_URL = tb_client.host + "/v1/build"
|
|
65
|
+
logging.debug(TINYBIRD_API_URL)
|
|
64
66
|
TINYBIRD_API_KEY = tb_client.token
|
|
65
67
|
try:
|
|
66
68
|
files = [
|
|
@@ -78,7 +80,12 @@ def build_project(folder: str, tb_client: TinyB) -> None:
|
|
|
78
80
|
HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
|
|
79
81
|
|
|
80
82
|
r = requests.post(TINYBIRD_API_URL, files=files, headers=HEADERS)
|
|
81
|
-
|
|
83
|
+
try:
|
|
84
|
+
result = r.json()
|
|
85
|
+
except Exception as e:
|
|
86
|
+
logging.debug(e, exc_info=True)
|
|
87
|
+
click.echo(FeedbackManager.error(message="Couldn't parse response from server"))
|
|
88
|
+
return
|
|
82
89
|
|
|
83
90
|
logging.debug(json.dumps(result, indent=2))
|
|
84
91
|
|
|
@@ -90,7 +97,7 @@ def build_project(folder: str, tb_client: TinyB) -> None:
|
|
|
90
97
|
build_errors = result.get("errors")
|
|
91
98
|
for build_error in build_errors:
|
|
92
99
|
filename_bit = f"{build_error.get('filename', '')}"
|
|
93
|
-
error_msg = (filename_bit + "\n\n") if filename_bit else "" + build_error.get("error")
|
|
100
|
+
error_msg = ((filename_bit + "\n\n") if filename_bit else "") + build_error.get("error")
|
|
94
101
|
click.echo(FeedbackManager.error(message=error_msg))
|
|
95
102
|
else:
|
|
96
103
|
click.echo(FeedbackManager.error(message=f"Unknown build result. Error: {result.get('error')}"))
|
|
@@ -99,3 +106,19 @@ def build_project(folder: str, tb_client: TinyB) -> None:
|
|
|
99
106
|
finally:
|
|
100
107
|
for fd in fds:
|
|
101
108
|
fd.close()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
async def append_fixture(
|
|
112
|
+
tb_client: TinyB,
|
|
113
|
+
datasource_name: str,
|
|
114
|
+
url: str,
|
|
115
|
+
):
|
|
116
|
+
await tb_client.datasource_truncate(datasource_name)
|
|
117
|
+
await push_data(
|
|
118
|
+
tb_client,
|
|
119
|
+
datasource_name,
|
|
120
|
+
url,
|
|
121
|
+
mode="append",
|
|
122
|
+
concurrency=1,
|
|
123
|
+
silent=True,
|
|
124
|
+
)
|
|
@@ -172,21 +172,7 @@ def build_client(
|
|
|
172
172
|
build_ok = asyncio.run(build_once(filenames))
|
|
173
173
|
|
|
174
174
|
if watch:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
datasource_paths = [f for f in paths if f.suffix == ".datasource"]
|
|
178
|
-
datasources = [f.stem for f in datasource_paths if not is_vendor(f)]
|
|
179
|
-
shared_datasources = [f"{get_vendor_workspace(f)}.{f.stem}" for f in datasource_paths if is_vendor(f)]
|
|
180
|
-
pipes = [f.stem for f in paths if is_pipe(f) and not is_endpoint(f)]
|
|
181
|
-
endpoints = [f.stem for f in paths if is_endpoint(f)]
|
|
182
|
-
shell = Shell(
|
|
183
|
-
folder=folder,
|
|
184
|
-
client=tb_client,
|
|
185
|
-
datasources=datasources,
|
|
186
|
-
shared_datasources=shared_datasources,
|
|
187
|
-
pipes=pipes,
|
|
188
|
-
endpoints=endpoints,
|
|
189
|
-
)
|
|
175
|
+
shell = Shell(folder=folder, client=tb_client)
|
|
190
176
|
click.echo(FeedbackManager.gray(message="\nWatching for changes..."))
|
|
191
177
|
watcher_thread = threading.Thread(
|
|
192
178
|
target=watch_files, args=(filenames, process, shell, folder, build_ok), daemon=True
|
|
@@ -94,7 +94,7 @@ VERSION = f"{__cli__.__version__} (rev {__cli__.__revision__})"
|
|
|
94
94
|
"--with-headers", help="Flag to enable connector to export with headers", is_flag=True, default=False, hidden=True
|
|
95
95
|
)
|
|
96
96
|
@click.option("--show-tokens", is_flag=True, default=False, help="Enable the output of tokens")
|
|
97
|
-
@click.option("--prod", is_flag=True, default=False, help="Run against production")
|
|
97
|
+
@click.option("--prod/--local", is_flag=True, default=False, help="Run against production or local")
|
|
98
98
|
@click.version_option(version=VERSION)
|
|
99
99
|
@click.pass_context
|
|
100
100
|
@coro
|
|
@@ -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_client_config_for_build
|
|
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_client_config_for_build(folder)
|
|
62
62
|
build = True
|
|
63
63
|
dry_run = False
|
|
64
64
|
force = True
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import functools
|
|
2
4
|
import glob
|
|
3
5
|
import itertools
|
|
@@ -9,8 +11,9 @@ import shlex
|
|
|
9
11
|
import string
|
|
10
12
|
import textwrap
|
|
11
13
|
import traceback
|
|
12
|
-
from collections import namedtuple
|
|
14
|
+
from collections import Counter, namedtuple
|
|
13
15
|
from dataclasses import dataclass
|
|
16
|
+
from enum import Enum
|
|
14
17
|
from io import StringIO
|
|
15
18
|
from pathlib import Path
|
|
16
19
|
from string import Template
|
|
@@ -29,6 +32,9 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
|
29
32
|
# from tinybird.sql import parse_indexes_structure, parse_table_structure, schema_to_sql_columns
|
|
30
33
|
|
|
31
34
|
|
|
35
|
+
class DatafileValidationError(Exception): ...
|
|
36
|
+
|
|
37
|
+
|
|
32
38
|
class DatafileSyntaxError(Exception):
|
|
33
39
|
def __init__(self, message: str, lineno: int, pos: int, hint: Optional[str] = None):
|
|
34
40
|
super().__init__(message)
|
|
@@ -155,6 +161,22 @@ valid_chars_name: str = string.ascii_letters + string.digits + "._`*<>+-'"
|
|
|
155
161
|
valid_chars_fn: str = valid_chars_name + "[](),=!?:/ \n\t\r"
|
|
156
162
|
|
|
157
163
|
|
|
164
|
+
class UnkownExtensionerror(Exception): ...
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class DatafileKind(Enum):
|
|
168
|
+
pipe = "pipe"
|
|
169
|
+
datasource = "datasource"
|
|
170
|
+
|
|
171
|
+
@classmethod
|
|
172
|
+
def from_extension(cls, extension: str) -> DatafileKind:
|
|
173
|
+
if extension == ".pipe":
|
|
174
|
+
return cls.pipe
|
|
175
|
+
elif extension == ".datasource":
|
|
176
|
+
return cls.datasource
|
|
177
|
+
raise UnkownExtensionerror(f"Unknown extension {extension} for data file")
|
|
178
|
+
|
|
179
|
+
|
|
158
180
|
class Datafile:
|
|
159
181
|
def __init__(self) -> None:
|
|
160
182
|
self.maintainer: Optional[str] = None
|
|
@@ -167,6 +189,7 @@ class Datafile:
|
|
|
167
189
|
self.shared_with: List[str] = []
|
|
168
190
|
self.warnings: List[str] = []
|
|
169
191
|
self.filtering_tags: Optional[List[str]] = None
|
|
192
|
+
self.kind: Optional[DatafileKind] = None
|
|
170
193
|
|
|
171
194
|
def is_equal(self, other):
|
|
172
195
|
if len(self.nodes) != len(other.nodes):
|
|
@@ -174,6 +197,40 @@ class Datafile:
|
|
|
174
197
|
|
|
175
198
|
return all(self.nodes[i] == other.nodes[i] for i, _ in enumerate(self.nodes))
|
|
176
199
|
|
|
200
|
+
def set_kind(self, kind: DatafileKind):
|
|
201
|
+
self.kind = kind
|
|
202
|
+
|
|
203
|
+
def validate(self):
|
|
204
|
+
if self.kind == DatafileKind.pipe:
|
|
205
|
+
# TODO(eclbg):
|
|
206
|
+
# [x] node names are unique
|
|
207
|
+
# [ ] ...
|
|
208
|
+
repeated_node_names = [
|
|
209
|
+
name for name, count in filter(lambda x: x[1] > 1, Counter(n["name"] for n in self.nodes).items())
|
|
210
|
+
]
|
|
211
|
+
if repeated_node_names:
|
|
212
|
+
raise DatafileValidationError(
|
|
213
|
+
f"Pipe node names must be unique. These names are repeated: {repeated_node_names}"
|
|
214
|
+
)
|
|
215
|
+
pass
|
|
216
|
+
elif self.kind == DatafileKind.datasource:
|
|
217
|
+
# TODO(eclbg):
|
|
218
|
+
# [x] Just one node
|
|
219
|
+
# [x] Engine is present
|
|
220
|
+
# [ ] ...
|
|
221
|
+
if len(self.nodes) > 1:
|
|
222
|
+
# Our users are not aware of data source data files being a single-node data file, hence this error
|
|
223
|
+
# message which might be confusing for us devs
|
|
224
|
+
raise DatafileValidationError("Datasource files cannot have nodes defined")
|
|
225
|
+
node = self.nodes[0]
|
|
226
|
+
if "schema" not in node:
|
|
227
|
+
raise DatafileValidationError("SCHEMA is mandatory")
|
|
228
|
+
if "engine" not in node:
|
|
229
|
+
raise DatafileValidationError("ENGINE is mandatory")
|
|
230
|
+
else:
|
|
231
|
+
# We cannot validate a datafile whose kind is unknown
|
|
232
|
+
pass
|
|
233
|
+
|
|
177
234
|
|
|
178
235
|
def format_filename(filename: str, hide_folders: bool = False):
|
|
179
236
|
return os.path.basename(filename) if hide_folders else filename
|
|
@@ -1016,6 +1073,7 @@ def parse(
|
|
|
1016
1073
|
basepath: str = ".",
|
|
1017
1074
|
replace_includes: bool = True,
|
|
1018
1075
|
skip_eval: bool = False,
|
|
1076
|
+
kind: Optional[DatafileKind] = None,
|
|
1019
1077
|
) -> Datafile:
|
|
1020
1078
|
"""
|
|
1021
1079
|
Parses `s` string into a document
|
|
@@ -1032,6 +1090,8 @@ def parse(
|
|
|
1032
1090
|
lines = list(StringIO(s, newline=None))
|
|
1033
1091
|
|
|
1034
1092
|
doc = Datafile()
|
|
1093
|
+
if kind is not None:
|
|
1094
|
+
doc.set_kind(kind)
|
|
1035
1095
|
doc.raw = list(StringIO(s, newline=None))
|
|
1036
1096
|
|
|
1037
1097
|
parser_state = namedtuple(
|
|
@@ -1098,7 +1158,8 @@ def parse(
|
|
|
1098
1158
|
except IndexesSyntaxError as e:
|
|
1099
1159
|
raise e
|
|
1100
1160
|
except Exception as e:
|
|
1101
|
-
# TODO(eclbg): We get here when an unidentified error happens but we still report a parsing error. We
|
|
1161
|
+
# TODO(eclbg): We get here when an unidentified error happens but we still report a parsing error. We should
|
|
1162
|
+
# rethink this.
|
|
1102
1163
|
raise ParseException(FeedbackManager.error_parsing_indices(line=kwargs["lineno"], error=e))
|
|
1103
1164
|
|
|
1104
1165
|
parser_state.current_node["indexes"] = indexes
|
{tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/parse_datasource.py
RENAMED
|
@@ -5,6 +5,7 @@ import click
|
|
|
5
5
|
|
|
6
6
|
from tinybird.tb.modules.datafile.common import (
|
|
7
7
|
Datafile,
|
|
8
|
+
DatafileKind,
|
|
8
9
|
DatafileSyntaxError,
|
|
9
10
|
format_filename,
|
|
10
11
|
parse,
|
|
@@ -31,20 +32,21 @@ def parse_datasource(
|
|
|
31
32
|
|
|
32
33
|
filename = format_filename(filename, hide_folders)
|
|
33
34
|
try:
|
|
34
|
-
doc = parse(
|
|
35
|
+
doc = parse(
|
|
36
|
+
s, "default", basepath, replace_includes=replace_includes, skip_eval=skip_eval, kind=DatafileKind.datasource
|
|
37
|
+
)
|
|
38
|
+
doc.validate()
|
|
35
39
|
except DatafileSyntaxError as e:
|
|
36
40
|
try:
|
|
37
41
|
if add_context_to_datafile_syntax_errors:
|
|
38
42
|
e.get_context_from_file_contents(s)
|
|
39
43
|
finally:
|
|
40
44
|
raise e
|
|
45
|
+
# TODO(eclbg): all these exceptions that trigger a ClickException shouldn't be here, as this code will only run in
|
|
46
|
+
# the server soon
|
|
41
47
|
except ParseException as e:
|
|
42
48
|
raise click.ClickException(
|
|
43
49
|
FeedbackManager.error_parsing_file(filename=filename, lineno=e.lineno, error=e)
|
|
44
50
|
) from None
|
|
45
51
|
|
|
46
|
-
if len(doc.nodes) > 1:
|
|
47
|
-
# TODO(eclbg): Turn this into a custom exception with a better message
|
|
48
|
-
raise ValueError(f"{filename}: datasources can't have more than one node")
|
|
49
|
-
|
|
50
52
|
return doc
|
|
@@ -6,6 +6,7 @@ import click
|
|
|
6
6
|
from tinybird.sql_template import get_template_and_variables, render_sql_template
|
|
7
7
|
from tinybird.tb.modules.datafile.common import (
|
|
8
8
|
Datafile,
|
|
9
|
+
DatafileKind,
|
|
9
10
|
DatafileSyntaxError,
|
|
10
11
|
format_filename,
|
|
11
12
|
parse,
|
|
@@ -35,7 +36,10 @@ def parse_pipe(
|
|
|
35
36
|
try:
|
|
36
37
|
sql = ""
|
|
37
38
|
try:
|
|
38
|
-
doc = parse(
|
|
39
|
+
doc = parse(
|
|
40
|
+
s, basepath=basepath, replace_includes=replace_includes, skip_eval=skip_eval, kind=DatafileKind.pipe
|
|
41
|
+
)
|
|
42
|
+
doc.validate()
|
|
39
43
|
except DatafileSyntaxError as e:
|
|
40
44
|
try:
|
|
41
45
|
if add_context_to_datafile_syntax_errors:
|
|
@@ -53,6 +57,8 @@ def parse_pipe(
|
|
|
53
57
|
from tinybird.sql_toolset import format_sql as toolset_format_sql
|
|
54
58
|
|
|
55
59
|
toolset_format_sql(sql)
|
|
60
|
+
# TODO(eclbg): all these exceptions that trigger a ClickException shouldn't be here, as this code will only run in
|
|
61
|
+
# the server soon
|
|
56
62
|
except ParseException as e:
|
|
57
63
|
raise click.ClickException(
|
|
58
64
|
FeedbackManager.error_parsing_file(
|
|
@@ -10,7 +10,6 @@ import requests
|
|
|
10
10
|
|
|
11
11
|
from tinybird.tb.modules.cli import cli
|
|
12
12
|
from tinybird.tb.modules.common import echo_safe_humanfriendly_tables_format_smart_table
|
|
13
|
-
from tinybird.tb.modules.config import CLIConfig
|
|
14
13
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
15
14
|
|
|
16
15
|
|
|
@@ -128,7 +127,8 @@ def deploy_group() -> None:
|
|
|
128
127
|
default=False,
|
|
129
128
|
help="Auto-promote the deployment. Only works if --wait is enabled. Disabled by default.",
|
|
130
129
|
)
|
|
131
|
-
|
|
130
|
+
@click.pass_context
|
|
131
|
+
def create(ctx: click.Context, project_path: Path, wait: bool, auto: bool) -> None:
|
|
132
132
|
"""
|
|
133
133
|
Validate and deploy the project server side.
|
|
134
134
|
"""
|
|
@@ -140,9 +140,9 @@ def create(project_path: Path, wait: bool, auto: bool) -> None:
|
|
|
140
140
|
".pipe": "text/plain",
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
TINYBIRD_API_URL = f"{
|
|
145
|
-
TINYBIRD_API_KEY =
|
|
143
|
+
client = ctx.ensure_object(dict)["client"]
|
|
144
|
+
TINYBIRD_API_URL = f"{client.host}/v1/deploy"
|
|
145
|
+
TINYBIRD_API_KEY = client.token
|
|
146
146
|
|
|
147
147
|
files = [
|
|
148
148
|
("context://", ("cli-version", "1.0.0", "text/plain")),
|
|
@@ -186,7 +186,7 @@ def create(project_path: Path, wait: bool, auto: bool) -> None:
|
|
|
186
186
|
if deployment and wait:
|
|
187
187
|
while deployment.get("status") != "data_ready":
|
|
188
188
|
time.sleep(5)
|
|
189
|
-
TINYBIRD_API_URL = f"{
|
|
189
|
+
TINYBIRD_API_URL = f"{client.host}/v1/deployments/{deployment.get('id')}"
|
|
190
190
|
r = requests.get(TINYBIRD_API_URL, headers=HEADERS)
|
|
191
191
|
result = r.json()
|
|
192
192
|
deployment = result.get("deployment")
|
|
@@ -197,20 +197,21 @@ def create(project_path: Path, wait: bool, auto: bool) -> None:
|
|
|
197
197
|
click.echo(FeedbackManager.success(message="Deployment is ready"))
|
|
198
198
|
|
|
199
199
|
if auto:
|
|
200
|
-
promote_deployment(
|
|
200
|
+
promote_deployment(client.host, HEADERS)
|
|
201
201
|
|
|
202
202
|
|
|
203
203
|
@deploy_group.command(name="list")
|
|
204
204
|
@click.argument("project_path", type=click.Path(exists=True), default=Path.cwd())
|
|
205
|
-
|
|
205
|
+
@click.pass_context
|
|
206
|
+
def deploy_list(ctx: click.Context, project_path: Path) -> None:
|
|
206
207
|
"""
|
|
207
208
|
List all the deployments you have in the project.
|
|
208
209
|
"""
|
|
209
|
-
|
|
210
|
+
client = ctx.ensure_object(dict)["client"]
|
|
210
211
|
|
|
211
|
-
TINYBIRD_API_KEY =
|
|
212
|
+
TINYBIRD_API_KEY = client.token
|
|
212
213
|
HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
|
|
213
|
-
TINYBIRD_API_URL = f"{
|
|
214
|
+
TINYBIRD_API_URL = f"{client.host}/v1/deployments"
|
|
214
215
|
|
|
215
216
|
r = requests.get(TINYBIRD_API_URL, headers=HEADERS)
|
|
216
217
|
result = r.json()
|
|
@@ -228,27 +229,29 @@ def deploy_list(project_path: Path) -> None:
|
|
|
228
229
|
|
|
229
230
|
@deploy_group.command(name="promote")
|
|
230
231
|
@click.argument("project_path", type=click.Path(exists=True), default=Path.cwd())
|
|
231
|
-
|
|
232
|
+
@click.pass_context
|
|
233
|
+
def deploy_promote(ctx: click.Context, project_path: Path) -> None:
|
|
232
234
|
"""
|
|
233
235
|
Promote last deploy to ready and remove old one.
|
|
234
236
|
"""
|
|
235
|
-
|
|
237
|
+
client = ctx.ensure_object(dict)["client"]
|
|
236
238
|
|
|
237
|
-
TINYBIRD_API_KEY =
|
|
239
|
+
TINYBIRD_API_KEY = client.token
|
|
238
240
|
HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
|
|
239
241
|
|
|
240
|
-
promote_deployment(
|
|
242
|
+
promote_deployment(client.host, HEADERS)
|
|
241
243
|
|
|
242
244
|
|
|
243
245
|
@deploy_group.command(name="rollback")
|
|
244
246
|
@click.argument("project_path", type=click.Path(exists=True), default=Path.cwd())
|
|
245
|
-
|
|
247
|
+
@click.pass_context
|
|
248
|
+
def deploy_rollback(ctx: click.Context, project_path: Path) -> None:
|
|
246
249
|
"""
|
|
247
250
|
Rollback to the previous deployment.
|
|
248
251
|
"""
|
|
249
|
-
|
|
252
|
+
client = ctx.ensure_object(dict)["client"]
|
|
250
253
|
|
|
251
|
-
TINYBIRD_API_KEY =
|
|
254
|
+
TINYBIRD_API_KEY = client.token
|
|
252
255
|
HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
|
|
253
256
|
|
|
254
|
-
rollback_deployment(
|
|
257
|
+
rollback_deployment(client.host, HEADERS)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
+
import subprocess
|
|
3
4
|
import time
|
|
4
5
|
|
|
5
6
|
import click
|
|
@@ -82,7 +83,9 @@ def get_docker_client():
|
|
|
82
83
|
client.ping()
|
|
83
84
|
return client
|
|
84
85
|
except Exception:
|
|
85
|
-
raise CLIException(
|
|
86
|
+
raise CLIException(
|
|
87
|
+
"No container runtime is running. Make sure a Docker-compatible runtime is installed and running."
|
|
88
|
+
)
|
|
86
89
|
|
|
87
90
|
|
|
88
91
|
def stop_tinybird_local(docker_client):
|
|
@@ -107,8 +110,17 @@ def remove_tinybird_local(docker_client):
|
|
|
107
110
|
def upgrade():
|
|
108
111
|
"""Upgrade Tinybird CLI to the latest version"""
|
|
109
112
|
click.echo(FeedbackManager.highlight(message="» Upgrading Tinybird CLI..."))
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
process = subprocess.Popen(
|
|
114
|
+
[f"{os.getenv('HOME')}/.local/bin/uv", "tool", "upgrade", "tinybird"],
|
|
115
|
+
stdout=subprocess.PIPE,
|
|
116
|
+
stderr=subprocess.PIPE,
|
|
117
|
+
text=True,
|
|
118
|
+
)
|
|
119
|
+
stdout, stderr = process.communicate()
|
|
120
|
+
if "Nothing to upgrade" not in stdout + stderr:
|
|
121
|
+
click.echo(FeedbackManager.success(message="✓ Tinybird CLI upgraded"))
|
|
122
|
+
else:
|
|
123
|
+
click.echo(FeedbackManager.info(message="✓ Tinybird CLI is already up to date"))
|
|
112
124
|
|
|
113
125
|
|
|
114
126
|
@cli.group()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import hashlib
|
|
2
|
+
import logging
|
|
2
3
|
import os
|
|
3
4
|
from typing import Optional
|
|
4
5
|
|
|
@@ -16,11 +17,15 @@ TB_LOCAL_HOST = f"http://localhost:{TB_LOCAL_PORT}"
|
|
|
16
17
|
|
|
17
18
|
async def get_tinybird_local_client(path: Optional[str] = None) -> TinyB:
|
|
18
19
|
"""Get a Tinybird client connected to the local environment."""
|
|
19
|
-
config = await
|
|
20
|
+
config = await get_client_config_for_build(path)
|
|
20
21
|
return config.get_client(host=TB_LOCAL_HOST)
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
async def
|
|
24
|
+
async def get_client_config_for_build(path: Optional[str] = None) -> CLIConfig:
|
|
25
|
+
"""Craft a client config with a workspace name based on the path of the project files
|
|
26
|
+
|
|
27
|
+
It uses the tokens from tinybird local
|
|
28
|
+
"""
|
|
24
29
|
config = CLIConfig.get_project_config(path)
|
|
25
30
|
try:
|
|
26
31
|
# ruff: noqa: ASYNC210
|
|
@@ -37,6 +42,7 @@ async def get_tinybird_local_config(path: Optional[str] = None) -> CLIConfig:
|
|
|
37
42
|
user_client = config.get_client(host=TB_LOCAL_HOST, token=user_token)
|
|
38
43
|
|
|
39
44
|
ws_name = f"Tinybird_Local_Build_{folder_hash}"
|
|
45
|
+
logging.debug(f"Workspace used for build: {ws_name}")
|
|
40
46
|
|
|
41
47
|
user_workspaces = await user_client.user_workspaces()
|
|
42
48
|
ws = next((ws for ws in user_workspaces["workspaces"] if ws["name"] == ws_name), None)
|
|
@@ -18,7 +18,12 @@ from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
|
18
18
|
@cli.command()
|
|
19
19
|
@click.argument("datasource", type=str)
|
|
20
20
|
@click.option("--rows", type=int, default=10, help="Number of events to send")
|
|
21
|
-
@click.option(
|
|
21
|
+
@click.option(
|
|
22
|
+
"--prompt",
|
|
23
|
+
type=str,
|
|
24
|
+
default="Use the datasource schema to generate sample data",
|
|
25
|
+
help="Extra context to use for data generation",
|
|
26
|
+
)
|
|
22
27
|
@click.option("--folder", type=str, default=".", help="Folder where datafiles will be placed")
|
|
23
28
|
@coro
|
|
24
29
|
async def mock(datasource: str, rows: int, prompt: str, folder: str) -> None:
|
|
@@ -68,7 +68,9 @@ def test(ctx: click.Context) -> None:
|
|
|
68
68
|
type=click.Path(exists=True, file_okay=False),
|
|
69
69
|
help="Folder where datafiles will be placed",
|
|
70
70
|
)
|
|
71
|
-
@click.option(
|
|
71
|
+
@click.option(
|
|
72
|
+
"--prompt", type=str, default="Create a test for the selected pipe", help="Prompt to be used to create the test"
|
|
73
|
+
)
|
|
72
74
|
@coro
|
|
73
75
|
async def test_create(name_or_filename: str, prompt: str, folder: str) -> None:
|
|
74
76
|
"""
|
|
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.dev32 → tinybird-0.0.1.dev34}/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
|
{tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/format_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
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/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
|