tinybird 0.0.1.dev68__py3-none-any.whl → 0.0.1.dev69__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tinybird might be problematic. Click here for more details.
- tinybird/ch_utils/engine.py +2 -4
- tinybird/context.py +0 -1
- tinybird/sql_template.py +1 -3
- tinybird/sql_toolset.py +3 -3
- tinybird/tb/__cli__.py +2 -2
- tinybird/tb/modules/auth.py +1 -1
- tinybird/tb/modules/cli.py +5 -5
- tinybird/tb/modules/common.py +9 -9
- tinybird/tb/modules/datafile/build_common.py +1 -1
- tinybird/tb/modules/datafile/build_datasource.py +1 -1
- tinybird/tb/modules/datafile/common.py +18 -1
- tinybird/tb/modules/datafile/pipe_checker.py +1 -1
- tinybird/tb/modules/datasource.py +2 -2
- tinybird/tb/modules/deployment.py +13 -1
- tinybird/tb/modules/endpoint.py +1 -1
- tinybird/tb/modules/fmt.py +1 -1
- tinybird/tb/modules/materialization.py +5 -5
- tinybird/tb/modules/mock.py +0 -1
- tinybird/tb/modules/pipe.py +1 -1
- tinybird/tb/modules/project.py +3 -3
- tinybird/tb/modules/shell.py +13 -21
- tinybird/tb/modules/test.py +1 -1
- tinybird/tb/modules/token.py +4 -4
- tinybird/tb/modules/workspace.py +6 -6
- tinybird/tb/modules/workspace_members.py +6 -6
- tinybird/tb_cli_modules/common.py +2 -2
- tinybird/tornado_template.py +2 -1
- tinybird-0.0.1.dev69.dist-info/METADATA +73 -0
- {tinybird-0.0.1.dev68.dist-info → tinybird-0.0.1.dev69.dist-info}/RECORD +32 -32
- {tinybird-0.0.1.dev68.dist-info → tinybird-0.0.1.dev69.dist-info}/WHEEL +1 -1
- tinybird-0.0.1.dev68.dist-info/METADATA +0 -64
- {tinybird-0.0.1.dev68.dist-info → tinybird-0.0.1.dev69.dist-info}/entry_points.txt +0 -0
- {tinybird-0.0.1.dev68.dist-info → tinybird-0.0.1.dev69.dist-info}/top_level.txt +0 -0
tinybird/ch_utils/engine.py
CHANGED
|
@@ -456,7 +456,7 @@ ENABLED_ENGINES = [
|
|
|
456
456
|
MERGETREE_OPTIONS,
|
|
457
457
|
),
|
|
458
458
|
# AggregatingMergeTree()
|
|
459
|
-
engine_config("AggregatingMergeTree", options=
|
|
459
|
+
engine_config("AggregatingMergeTree", options=MERGETREE_OPTIONS),
|
|
460
460
|
# CollapsingMergeTree(sign)
|
|
461
461
|
engine_config(
|
|
462
462
|
"CollapsingMergeTree",
|
|
@@ -631,9 +631,7 @@ def engine_full_from_dict(
|
|
|
631
631
|
|
|
632
632
|
>>> schema = 'sign_column Int8'
|
|
633
633
|
>>> engine_full_from_dict('AggregatingMergeTree', {}, schema=schema)
|
|
634
|
-
|
|
635
|
-
...
|
|
636
|
-
ValueError: Missing required option 'sorting_key'
|
|
634
|
+
'AggregatingMergeTree() ORDER BY (tuple())'
|
|
637
635
|
|
|
638
636
|
>>> columns=[]
|
|
639
637
|
>>> columns.append({'name': 'key_column', 'type': 'Int8', 'codec': None, 'default_value': None, 'nullable': False, 'normalized_name': 'key_column'})
|
tinybird/context.py
CHANGED
|
@@ -20,5 +20,4 @@ engine: ContextVar[str] = ContextVar("engine")
|
|
|
20
20
|
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
|
-
ff_preprocess_parameters_circuit_breaker: ContextVar[bool] = ContextVar("ff_preprocess_parameters_circuit_breaker")
|
|
24
23
|
ff_column_json_backticks_circuit_breaker: ContextVar[bool] = ContextVar("ff_column_json_backticks_circuit_breaker")
|
tinybird/sql_template.py
CHANGED
|
@@ -14,7 +14,6 @@ from tornado.util import ObjectDict, exec_in, unicode_type
|
|
|
14
14
|
|
|
15
15
|
from tinybird.context import (
|
|
16
16
|
ff_column_json_backticks_circuit_breaker,
|
|
17
|
-
ff_preprocess_parameters_circuit_breaker,
|
|
18
17
|
ff_split_to_array_escape,
|
|
19
18
|
)
|
|
20
19
|
|
|
@@ -2244,14 +2243,13 @@ def render_sql_template(
|
|
|
2244
2243
|
tinybird.sql_template.SQLTemplateException: Template Syntax Error: Required parameter is not defined. Check the parameters test. Please provide a value or set a default value in the pipe code.
|
|
2245
2244
|
"""
|
|
2246
2245
|
escape_split_to_array = ff_split_to_array_escape.get(False)
|
|
2247
|
-
bypass_preprocess_variables = ff_preprocess_parameters_circuit_breaker.get(False)
|
|
2248
2246
|
|
|
2249
2247
|
t, template_variables, variable_warnings = get_template_and_variables(
|
|
2250
2248
|
sql, name, escape_arrays=escape_split_to_array
|
|
2251
2249
|
)
|
|
2252
2250
|
template_variables_with_types = get_var_names_and_types_cached(t)
|
|
2253
2251
|
|
|
2254
|
-
if
|
|
2252
|
+
if variables is not None:
|
|
2255
2253
|
processed_variables = preprocess_variables(variables, template_variables_with_types)
|
|
2256
2254
|
variables.update(processed_variables)
|
|
2257
2255
|
|
tinybird/sql_toolset.py
CHANGED
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from functools import lru_cache
|
|
6
|
-
from typing import FrozenSet, List, Optional, Set, Tuple
|
|
6
|
+
from typing import FrozenSet, List, Optional, Set, Tuple, Union
|
|
7
7
|
|
|
8
8
|
from chtoolset import query as chquery
|
|
9
9
|
from toposort import toposort
|
|
@@ -172,7 +172,7 @@ def tables_or_sql(replacement: dict, table_functions=False) -> set:
|
|
|
172
172
|
return {replacement}
|
|
173
173
|
|
|
174
174
|
|
|
175
|
-
def _separate_as_tuple_if_contains_database_and_table(definition: str) -> str
|
|
175
|
+
def _separate_as_tuple_if_contains_database_and_table(definition: str) -> Union[str, Tuple[str, str]]:
|
|
176
176
|
if "." in definition:
|
|
177
177
|
database_and_table_separated = definition.split(".")
|
|
178
178
|
return database_and_table_separated[0], database_and_table_separated[1]
|
|
@@ -255,7 +255,7 @@ def replace_tables(
|
|
|
255
255
|
function_allow_list=function_allow_list,
|
|
256
256
|
)
|
|
257
257
|
seen_tables = set()
|
|
258
|
-
table: Tuple[str, str]
|
|
258
|
+
table: Union[Tuple[str, str], Tuple[str, str, str]]
|
|
259
259
|
if function_allow_list is None:
|
|
260
260
|
_enabled_table_functions = ENABLED_TABLE_FUNCTIONS
|
|
261
261
|
else:
|
tinybird/tb/__cli__.py
CHANGED
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/cli/introduction.html'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '0.0.1.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '0.0.1.dev69'
|
|
8
|
+
__revision__ = 'f90d907'
|
tinybird/tb/modules/auth.py
CHANGED
|
@@ -30,7 +30,7 @@ from tinybird.tb.modules.regions import Region
|
|
|
30
30
|
@click.option("--token", help="Use auth token, defaults to TB_TOKEN envvar, then to the .tinyb file")
|
|
31
31
|
@click.option(
|
|
32
32
|
"--host",
|
|
33
|
-
help="Set custom host if it's different than https://api.tinybird.co. Check https://www.tinybird.co/docs/api-reference
|
|
33
|
+
help="Set custom host if it's different than https://api.tinybird.co. Check https://www.tinybird.co/docs/api-reference#regions-and-endpoints for the available list of regions",
|
|
34
34
|
)
|
|
35
35
|
@click.option(
|
|
36
36
|
"--region", envvar="TB_REGION", help="Set region. Run 'tb auth ls' to show available regions. Overrides host."
|
tinybird/tb/modules/cli.py
CHANGED
|
@@ -147,12 +147,12 @@ async def pull(ctx: Context, force: bool, fmt: bool) -> None:
|
|
|
147
147
|
@click.option("--no-deps", is_flag=True, default=False, help="Print only data sources with no pipes using them")
|
|
148
148
|
@click.option("--match", default=None, help="Retrieve any resource matching the pattern")
|
|
149
149
|
@click.option("--pipe", default=None, help="Retrieve any resource used by pipe")
|
|
150
|
-
@click.option("--datasource", default=None, help="Retrieve resources depending on this
|
|
150
|
+
@click.option("--datasource", default=None, help="Retrieve resources depending on this data source")
|
|
151
151
|
@click.option(
|
|
152
152
|
"--check-for-partial-replace",
|
|
153
153
|
is_flag=True,
|
|
154
154
|
default=False,
|
|
155
|
-
help="Retrieve dependant
|
|
155
|
+
help="Retrieve dependant data sources that will have their data replaced if a partial replace is executed in the data source selected",
|
|
156
156
|
)
|
|
157
157
|
@click.option("--recursive", is_flag=True, default=False, help="Calculate recursive dependencies")
|
|
158
158
|
@click.pass_context
|
|
@@ -186,7 +186,7 @@ async def dependencies(
|
|
|
186
186
|
|
|
187
187
|
@cli.command(
|
|
188
188
|
name="diff",
|
|
189
|
-
short_help="
|
|
189
|
+
short_help="Diff local datafiles to the corresponding remote files in the workspace. For the case of .datasource files it just diffs VERSION and SCHEMA, since ENGINE, KAFKA or other metadata is considered immutable.",
|
|
190
190
|
)
|
|
191
191
|
@click.argument("filename", type=click.Path(exists=True), nargs=-1, required=False)
|
|
192
192
|
@click.option(
|
|
@@ -203,7 +203,7 @@ async def dependencies(
|
|
|
203
203
|
"--main",
|
|
204
204
|
is_flag=True,
|
|
205
205
|
default=False,
|
|
206
|
-
help="
|
|
206
|
+
help="Diff local datafiles to the corresponding remote files in the main workspace. Only works when authenticated on a Branch.",
|
|
207
207
|
hidden=True,
|
|
208
208
|
)
|
|
209
209
|
@click.pass_context
|
|
@@ -255,7 +255,7 @@ async def diff(
|
|
|
255
255
|
@cli.command()
|
|
256
256
|
@click.argument("query", required=False)
|
|
257
257
|
@click.option("--rows_limit", default=100, help="Max number of rows retrieved")
|
|
258
|
-
@click.option("--pipeline", default=None, help="The name of the
|
|
258
|
+
@click.option("--pipeline", default=None, help="The name of the pipe to run the SQL Query")
|
|
259
259
|
@click.option("--pipe", default=None, help="The path to the .pipe file to run the SQL Query of a specific NODE")
|
|
260
260
|
@click.option("--node", default=None, help="The NODE name")
|
|
261
261
|
@click.option(
|
tinybird/tb/modules/common.py
CHANGED
|
@@ -571,7 +571,7 @@ def region_from_host(region_name_or_host, regions):
|
|
|
571
571
|
|
|
572
572
|
def ask_for_user_token(action: str, ui_host: str) -> str:
|
|
573
573
|
return click.prompt(
|
|
574
|
-
f'\nUse the token called "user token"
|
|
574
|
+
f'\nUse the token called "user token" to {action}. Copy it from {ui_host}/tokens and paste it here',
|
|
575
575
|
hide_input=True,
|
|
576
576
|
show_default=False,
|
|
577
577
|
default=None,
|
|
@@ -591,13 +591,13 @@ async def check_user_token(ctx: Context, token: str):
|
|
|
591
591
|
if not is_authenticated.get("is_valid", False):
|
|
592
592
|
raise CLIWorkspaceException(
|
|
593
593
|
FeedbackManager.error_exception(
|
|
594
|
-
error='Invalid token.
|
|
594
|
+
error='Invalid token. Make sure you are using the "user token" instead of the "admin your@email" token.'
|
|
595
595
|
)
|
|
596
596
|
)
|
|
597
597
|
if is_authenticated.get("is_valid") and not is_authenticated.get("is_user", False):
|
|
598
598
|
raise CLIWorkspaceException(
|
|
599
599
|
FeedbackManager.error_exception(
|
|
600
|
-
error='Invalid user authentication.
|
|
600
|
+
error='Invalid user authentication. Make sure you are using the "user token" instead of the "admin your@email" token.'
|
|
601
601
|
)
|
|
602
602
|
)
|
|
603
603
|
|
|
@@ -614,13 +614,13 @@ async def check_user_token_with_client(client: TinyB, token: str):
|
|
|
614
614
|
if not is_authenticated.get("is_valid", False):
|
|
615
615
|
raise CLIWorkspaceException(
|
|
616
616
|
FeedbackManager.error_exception(
|
|
617
|
-
error='Invalid token.
|
|
617
|
+
error='Invalid token. Make sure you are using the "user token" instead of the "admin your@email" token.'
|
|
618
618
|
)
|
|
619
619
|
)
|
|
620
620
|
if is_authenticated.get("is_valid") and not is_authenticated.get("is_user", False):
|
|
621
621
|
raise CLIWorkspaceException(
|
|
622
622
|
FeedbackManager.error_exception(
|
|
623
|
-
error='Invalid user authentication.
|
|
623
|
+
error='Invalid user authentication. Make sure you are using the "user token" instead of the "admin your@email" token.'
|
|
624
624
|
)
|
|
625
625
|
)
|
|
626
626
|
|
|
@@ -1153,17 +1153,17 @@ def validate_kafka_bootstrap_servers(host_and_port):
|
|
|
1153
1153
|
|
|
1154
1154
|
def validate_kafka_key(s):
|
|
1155
1155
|
if not isinstance(s, str):
|
|
1156
|
-
raise CLIException("Key format is not correct, it
|
|
1156
|
+
raise CLIException("Key format is not correct, it must be a string")
|
|
1157
1157
|
|
|
1158
1158
|
|
|
1159
1159
|
def validate_kafka_secret(s):
|
|
1160
1160
|
if not isinstance(s, str):
|
|
1161
|
-
raise CLIException("Password format is not correct, it
|
|
1161
|
+
raise CLIException("Password format is not correct, it must be a string")
|
|
1162
1162
|
|
|
1163
1163
|
|
|
1164
1164
|
def validate_string_connector_param(param, s):
|
|
1165
1165
|
if not isinstance(s, str):
|
|
1166
|
-
raise CLIConnectionException(param + " format is not correct, it
|
|
1166
|
+
raise CLIConnectionException(param + " format is not correct, it must be a string")
|
|
1167
1167
|
|
|
1168
1168
|
|
|
1169
1169
|
async def validate_connection_name(client, connection_name, service):
|
|
@@ -1434,7 +1434,7 @@ async def try_update_config_with_remote(
|
|
|
1434
1434
|
def ask_for_admin_token_interactively(ui_host: str, default_token: Optional[str]) -> str:
|
|
1435
1435
|
return (
|
|
1436
1436
|
click.prompt(
|
|
1437
|
-
f'\nCopy the "admin your@email" token from {ui_host}/tokens and paste it here {"OR press enter to use the token from .tinyb file" if default_token else ""}',
|
|
1437
|
+
f'\nCopy the "admin your@email" token from {ui_host}/tokens and paste it here {"OR press enter to use the token from the .tinyb file" if default_token else ""}',
|
|
1438
1438
|
hide_input=True,
|
|
1439
1439
|
show_default=False,
|
|
1440
1440
|
default=default_token,
|
|
@@ -94,7 +94,7 @@ async def update_tags_in_resource(rs: Dict[str, Any], resource_type: str, client
|
|
|
94
94
|
resource_name = persisted_ds.get("name", "")
|
|
95
95
|
except DoesNotExistException:
|
|
96
96
|
click.echo(
|
|
97
|
-
FeedbackManager.error_tag_generic("Could not get the latest
|
|
97
|
+
FeedbackManager.error_tag_generic("Could not get the latest data source info for updating its tags.")
|
|
98
98
|
)
|
|
99
99
|
elif resource_type == "pipe":
|
|
100
100
|
pipe_name = rs["name"]
|
|
@@ -60,7 +60,7 @@ async def new_ds(
|
|
|
60
60
|
|
|
61
61
|
if engine_param.lower() == "join":
|
|
62
62
|
deprecation_notice = FeedbackManager.warning_deprecated(
|
|
63
|
-
warning="Data
|
|
63
|
+
warning="Data sources with Join engine are deprecated and will be removed in the next major release of tinybird-cli. Use MergeTree instead."
|
|
64
64
|
)
|
|
65
65
|
click.echo(deprecation_notice)
|
|
66
66
|
|
|
@@ -20,6 +20,7 @@ from string import Template
|
|
|
20
20
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, cast
|
|
21
21
|
|
|
22
22
|
import click
|
|
23
|
+
from croniter import croniter
|
|
23
24
|
from mypy_extensions import KwArg, VarArg
|
|
24
25
|
|
|
25
26
|
from tinybird.ch_utils.engine import ENABLED_ENGINES
|
|
@@ -200,6 +201,20 @@ class Datafile:
|
|
|
200
201
|
def set_kind(self, kind: DatafileKind):
|
|
201
202
|
self.kind = kind
|
|
202
203
|
|
|
204
|
+
def validate_copy_node(self, node: Dict[str, Any]):
|
|
205
|
+
if "target_datasource" not in node:
|
|
206
|
+
raise DatafileValidationError("COPY node missing target datasource")
|
|
207
|
+
# copy mode must be append or replace
|
|
208
|
+
if node.get("mode") and node["mode"] not in ["append", "replace"]:
|
|
209
|
+
raise DatafileValidationError("COPY node mode must be append or replace")
|
|
210
|
+
# copy schedule must be @on-demand or a cron-expression
|
|
211
|
+
if (
|
|
212
|
+
node.get("copy_schedule")
|
|
213
|
+
and node["copy_schedule"] != ON_DEMAND
|
|
214
|
+
and not croniter.is_valid(node["copy_schedule"])
|
|
215
|
+
):
|
|
216
|
+
raise DatafileValidationError("COPY node schedule must be @on-demand or a valid cron expression.")
|
|
217
|
+
|
|
203
218
|
def validate(self):
|
|
204
219
|
if self.kind == DatafileKind.pipe:
|
|
205
220
|
# TODO(eclbg):
|
|
@@ -208,7 +223,7 @@ class Datafile:
|
|
|
208
223
|
# [x] Materialized nodes have target datasource
|
|
209
224
|
# [x] Only one materialized node
|
|
210
225
|
# [x] Only one node of any specific type
|
|
211
|
-
#
|
|
226
|
+
# (rbarbadillo): there's a HUGE amount of validations in api_pipes.py, we should somehow merge them
|
|
212
227
|
for node in self.nodes:
|
|
213
228
|
if "sql" not in node:
|
|
214
229
|
raise DatafileValidationError(f"SQL missing for node {repr(node['name'])}")
|
|
@@ -220,6 +235,8 @@ class Datafile:
|
|
|
220
235
|
raise DatafileValidationError("Multiple non-standard nodes in pipe. There can only be one")
|
|
221
236
|
if node.get("type", "").lower() == PipeNodeTypes.MATERIALIZED and "datasource" not in node:
|
|
222
237
|
raise DatafileValidationError(f"Materialized node {repr(node['name'])} missing target datasource")
|
|
238
|
+
if node.get("type", "").lower() == PipeNodeTypes.COPY:
|
|
239
|
+
self.validate_copy_node(node)
|
|
223
240
|
elif self.kind == DatafileKind.datasource:
|
|
224
241
|
# TODO(eclbg):
|
|
225
242
|
# [x] Just one node
|
|
@@ -412,7 +412,7 @@ class PipeCheckerRunner:
|
|
|
412
412
|
)
|
|
413
413
|
|
|
414
414
|
result = PipeCheckerTextTestResult(
|
|
415
|
-
self.checker_stream_result_class(sys.stdout),
|
|
415
|
+
self.checker_stream_result_class(sys.stdout),
|
|
416
416
|
descriptions=True,
|
|
417
417
|
verbosity=2,
|
|
418
418
|
custom_output=custom_output,
|
|
@@ -34,7 +34,7 @@ def datasource(ctx):
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
@datasource.command(name="ls")
|
|
37
|
-
@click.option("--match", default=None, help="Retrieve any resources matching the pattern.
|
|
37
|
+
@click.option("--match", default=None, help="Retrieve any resources matching the pattern. For example, --match _test")
|
|
38
38
|
@click.option(
|
|
39
39
|
"--format",
|
|
40
40
|
"format_",
|
|
@@ -116,7 +116,7 @@ async def datasource_append(
|
|
|
116
116
|
concurrency: int,
|
|
117
117
|
):
|
|
118
118
|
"""
|
|
119
|
-
Appends data to an existing
|
|
119
|
+
Appends data to an existing data source from URL, local file or a connector
|
|
120
120
|
|
|
121
121
|
- Load from URL `tb datasource append [datasource_name] https://url_to_csv`
|
|
122
122
|
|
|
@@ -44,12 +44,15 @@ def promote_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
44
44
|
if candidate_deployment.get("live"):
|
|
45
45
|
click.echo(FeedbackManager.error(message="Candidate deployment is already live"))
|
|
46
46
|
else:
|
|
47
|
-
click.echo(FeedbackManager.success(message="
|
|
47
|
+
click.echo(FeedbackManager.success(message="Setting candidate deployment as live"))
|
|
48
48
|
|
|
49
49
|
TINYBIRD_API_URL = f"{host}/v1/deployments/{candidate_deployment.get('id')}/set-live"
|
|
50
50
|
r = requests.post(TINYBIRD_API_URL, headers=headers)
|
|
51
51
|
result = r.json()
|
|
52
52
|
logging.debug(json.dumps(result, indent=2))
|
|
53
|
+
if result.get("error"):
|
|
54
|
+
click.echo(FeedbackManager.error(message=result.get("error")))
|
|
55
|
+
sys.exit(1)
|
|
53
56
|
|
|
54
57
|
click.echo(FeedbackManager.success(message="Removing old deployment"))
|
|
55
58
|
|
|
@@ -57,6 +60,9 @@ def promote_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
57
60
|
r = requests.delete(TINYBIRD_API_URL, headers=headers)
|
|
58
61
|
result = r.json()
|
|
59
62
|
logging.debug(json.dumps(result, indent=2))
|
|
63
|
+
if result.get("error"):
|
|
64
|
+
click.echo(FeedbackManager.error(message=result.get("error")))
|
|
65
|
+
sys.exit(1)
|
|
60
66
|
|
|
61
67
|
click.echo(FeedbackManager.success(message="Deployment promotion successfully started"))
|
|
62
68
|
|
|
@@ -110,6 +116,9 @@ def rollback_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
110
116
|
r = requests.post(TINYBIRD_API_URL, headers=headers)
|
|
111
117
|
result = r.json()
|
|
112
118
|
logging.debug(json.dumps(result, indent=2))
|
|
119
|
+
if result.get("error"):
|
|
120
|
+
click.echo(FeedbackManager.error(message=result.get("error")))
|
|
121
|
+
sys.exit(1)
|
|
113
122
|
|
|
114
123
|
click.echo(FeedbackManager.success(message="Removing current deployment"))
|
|
115
124
|
|
|
@@ -117,6 +126,9 @@ def rollback_deployment(host: Optional[str], headers: dict, wait: bool) -> None:
|
|
|
117
126
|
r = requests.delete(TINYBIRD_API_URL, headers=headers)
|
|
118
127
|
result = r.json()
|
|
119
128
|
logging.debug(json.dumps(result, indent=2))
|
|
129
|
+
if result.get("error"):
|
|
130
|
+
click.echo(FeedbackManager.error(message=result.get("error")))
|
|
131
|
+
sys.exit(1)
|
|
120
132
|
|
|
121
133
|
click.echo(FeedbackManager.success(message="Deployment rollback successfully started"))
|
|
122
134
|
|
tinybird/tb/modules/endpoint.py
CHANGED
|
@@ -29,7 +29,7 @@ def endpoint(ctx):
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
@endpoint.command(name="ls")
|
|
32
|
-
@click.option("--match", default=None, help="Retrieve any
|
|
32
|
+
@click.option("--match", default=None, help="Retrieve any resource matching the pattern. For example, --match _test")
|
|
33
33
|
@click.option(
|
|
34
34
|
"--format",
|
|
35
35
|
"format_",
|
tinybird/tb/modules/fmt.py
CHANGED
|
@@ -58,7 +58,7 @@ async def fmt(
|
|
|
58
58
|
elif (".pipe" in extensions) or (".incl" in extensions):
|
|
59
59
|
result = await format_pipe(filename, line_length, skip_eval=True)
|
|
60
60
|
else:
|
|
61
|
-
click.echo("Unsupported file type. Supported files types are: .pipe
|
|
61
|
+
click.echo("Unsupported file type. Supported files types are: .pipe and .datasource")
|
|
62
62
|
return None
|
|
63
63
|
|
|
64
64
|
if diff:
|
|
@@ -23,7 +23,7 @@ def materialization(ctx):
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
@materialization.command(name="ls")
|
|
26
|
-
@click.option("--match", default=None, help="Retrieve any resourcing matching the pattern.
|
|
26
|
+
@click.option("--match", default=None, help="Retrieve any resourcing matching the pattern. For example, --match _test")
|
|
27
27
|
@click.option(
|
|
28
28
|
"--format",
|
|
29
29
|
"format_",
|
|
@@ -79,16 +79,16 @@ async def materialization_ls(ctx: click.Context, match: str, format_: str):
|
|
|
79
79
|
"--sql-condition",
|
|
80
80
|
type=str,
|
|
81
81
|
default=None,
|
|
82
|
-
help="Populate with a SQL condition to be applied to the trigger
|
|
82
|
+
help="Populate with a SQL condition to be applied to the trigger data source of the materialized view. For instance, `--sql-condition='date == toYYYYMM(now())'` it'll populate taking all the rows from the trigger data source which `date` is the current month. Use it together with --populate. --sql-condition is not taken into account if the --subset param is present. Including in the ``sql_condition`` any column present in the data source ``engine_sorting_key`` will make the populate job process less data.",
|
|
83
83
|
)
|
|
84
84
|
@click.option(
|
|
85
|
-
"--truncate", is_flag=True, default=False, help="Truncates the materialized
|
|
85
|
+
"--truncate", is_flag=True, default=False, help="Truncates the materialized data source before populating it."
|
|
86
86
|
)
|
|
87
87
|
@click.option(
|
|
88
88
|
"--unlink-on-populate-error",
|
|
89
89
|
is_flag=True,
|
|
90
90
|
default=False,
|
|
91
|
-
help="If the populate job fails the
|
|
91
|
+
help="If the populate job fails the materialized view is unlinked and new data won't be ingested in the materialized view. First time a populate job fails, the materialized view is always unlinked.",
|
|
92
92
|
)
|
|
93
93
|
@click.option(
|
|
94
94
|
"--wait",
|
|
@@ -107,7 +107,7 @@ async def pipe_populate(
|
|
|
107
107
|
unlink_on_populate_error: bool,
|
|
108
108
|
wait: bool,
|
|
109
109
|
):
|
|
110
|
-
"""Populate the result of a Materialized Node into the target
|
|
110
|
+
"""Populate the result of a Materialized Node into the target materialized view"""
|
|
111
111
|
cl = create_tb_client(ctx)
|
|
112
112
|
|
|
113
113
|
pipe = await cl.pipe(pipe_name)
|
tinybird/tb/modules/mock.py
CHANGED
|
@@ -80,7 +80,6 @@ async def mock(ctx: click.Context, datasource: str, rows: int, prompt: str) -> N
|
|
|
80
80
|
prompt = f"<datasource_schema>{datasource_content}</datasource_schema>\n<user_input>{prompt}</user_input>"
|
|
81
81
|
sql = ""
|
|
82
82
|
|
|
83
|
-
click.echo(FeedbackManager.highlight(message=f"\n» Creating fixture for {datasource_name}..."))
|
|
84
83
|
response = llm.ask(system_prompt=mock_prompt(rows), prompt=prompt)
|
|
85
84
|
sql = extract_xml(response, "sql")
|
|
86
85
|
result = await tb_client.query(f"{sql} FORMAT JSON")
|
tinybird/tb/modules/pipe.py
CHANGED
|
@@ -27,7 +27,7 @@ def pipe(ctx):
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@pipe.command(name="ls")
|
|
30
|
-
@click.option("--match", default=None, help="Retrieve any resourcing matching the pattern.
|
|
30
|
+
@click.option("--match", default=None, help="Retrieve any resourcing matching the pattern. For example, --match _test")
|
|
31
31
|
@click.option(
|
|
32
32
|
"--format",
|
|
33
33
|
"format_",
|
tinybird/tb/modules/project.py
CHANGED
|
@@ -40,17 +40,17 @@ class Project:
|
|
|
40
40
|
|
|
41
41
|
def get_vendor_files(self) -> List[str]:
|
|
42
42
|
vendor_files: List[str] = []
|
|
43
|
-
for project_file in glob.glob(f"{self.vendor_path}/**/*.datasource", recursive=
|
|
43
|
+
for project_file in glob.glob(f"{self.vendor_path}/**/*.datasource", recursive=False):
|
|
44
44
|
vendor_files.append(project_file)
|
|
45
45
|
return vendor_files
|
|
46
46
|
|
|
47
47
|
@property
|
|
48
48
|
def datasources(self) -> List[str]:
|
|
49
|
-
return sorted([Path(f).stem for f in glob.glob(f"{self.path}/**/*.datasource", recursive=
|
|
49
|
+
return sorted([Path(f).stem for f in glob.glob(f"{self.path}/**/*.datasource", recursive=False)])
|
|
50
50
|
|
|
51
51
|
@property
|
|
52
52
|
def pipes(self) -> List[str]:
|
|
53
|
-
return sorted([Path(f).stem for f in glob.glob(f"{self.path}/**/*.pipe", recursive=
|
|
53
|
+
return sorted([Path(f).stem for f in glob.glob(f"{self.path}/**/*.pipe", recursive=False)])
|
|
54
54
|
|
|
55
55
|
def get_pipe_datafile(self, filename: str) -> Optional[Datafile]:
|
|
56
56
|
try:
|
tinybird/tb/modules/shell.py
CHANGED
|
@@ -24,10 +24,17 @@ from tinybird.tb.modules.table import format_table
|
|
|
24
24
|
class DynamicCompleter(Completer):
|
|
25
25
|
def __init__(self, project: Project):
|
|
26
26
|
self.project = project
|
|
27
|
-
self.static_commands = [
|
|
27
|
+
self.static_commands = [
|
|
28
|
+
"create",
|
|
29
|
+
"mock",
|
|
30
|
+
"test",
|
|
31
|
+
"select",
|
|
32
|
+
"datasource",
|
|
33
|
+
"pipe",
|
|
34
|
+
"endpoint",
|
|
35
|
+
"copy",
|
|
36
|
+
]
|
|
28
37
|
self.test_commands = ["create", "run", "update"]
|
|
29
|
-
self.mock_flags = ["--prompt", "--rows"]
|
|
30
|
-
self.common_rows = ["10", "50", "100", "500", "1000"]
|
|
31
38
|
self.sql_keywords = ["select", "from", "where", "group by", "order by", "limit"]
|
|
32
39
|
|
|
33
40
|
def get_completions(self, document, complete_event):
|
|
@@ -114,20 +121,6 @@ class DynamicCompleter(Completer):
|
|
|
114
121
|
)
|
|
115
122
|
return
|
|
116
123
|
|
|
117
|
-
if len(words) == 3 or len(words) == 4:
|
|
118
|
-
# After datasource or after a flag value, show available flags
|
|
119
|
-
available_flags = [f for f in self.mock_flags if f not in words]
|
|
120
|
-
for flag in available_flags:
|
|
121
|
-
yield Completion(flag, start_position=0, display=flag, style="class:completion.cmd")
|
|
122
|
-
return
|
|
123
|
-
|
|
124
|
-
last_word = words[-1]
|
|
125
|
-
if last_word == "--prompt":
|
|
126
|
-
yield Completion('""', start_position=0, display='"Enter your prompt..."', style="class:completion.cmd")
|
|
127
|
-
elif last_word == "--rows":
|
|
128
|
-
for rows in self.common_rows:
|
|
129
|
-
yield Completion(rows, start_position=0, display=rows, style="class:completion.cmd")
|
|
130
|
-
|
|
131
124
|
def _handle_test_completions(self, words: List[str]):
|
|
132
125
|
if len(words) == 1:
|
|
133
126
|
for cmd in self.test_commands:
|
|
@@ -206,7 +199,6 @@ class Shell:
|
|
|
206
199
|
self.project = project
|
|
207
200
|
self.tb_client = tb_client
|
|
208
201
|
self.prompt_message = "\ntb > "
|
|
209
|
-
self.commands = ["create", "mock", "test", "tb", "select"]
|
|
210
202
|
self.session: PromptSession = PromptSession(
|
|
211
203
|
completer=DynamicCompleter(project),
|
|
212
204
|
complete_style=CompleteStyle.COLUMN,
|
|
@@ -274,7 +266,7 @@ class Shell:
|
|
|
274
266
|
def handle_mock(self, arg):
|
|
275
267
|
if "mock" in arg.strip().lower():
|
|
276
268
|
arg = arg.replace("mock", "")
|
|
277
|
-
subprocess.run(f"tb --build mock {arg}
|
|
269
|
+
subprocess.run(f"tb --build mock {arg}", shell=True, text=True)
|
|
278
270
|
|
|
279
271
|
def handle_tb(self, argline):
|
|
280
272
|
click.echo("")
|
|
@@ -290,7 +282,7 @@ class Shell:
|
|
|
290
282
|
else:
|
|
291
283
|
need_skip = ("mock", "test create", "create")
|
|
292
284
|
if any(arg.startswith(cmd) for cmd in need_skip):
|
|
293
|
-
argline = f"{argline}
|
|
285
|
+
argline = f"{argline}"
|
|
294
286
|
subprocess.run(f"tb --build {argline}", shell=True, text=True)
|
|
295
287
|
|
|
296
288
|
def default(self, argline):
|
|
@@ -305,7 +297,7 @@ class Shell:
|
|
|
305
297
|
else:
|
|
306
298
|
need_skip = ("mock", "test create", "create")
|
|
307
299
|
if any(arg.startswith(cmd) for cmd in need_skip):
|
|
308
|
-
argline = f"{argline}
|
|
300
|
+
argline = f"{argline}"
|
|
309
301
|
subprocess.run(f"tb --build {argline}", shell=True, text=True)
|
|
310
302
|
|
|
311
303
|
def run_sql(self, query, rows_limit=20):
|
tinybird/tb/modules/test.py
CHANGED
|
@@ -207,7 +207,7 @@ async def test_update(ctx: click.Context, pipe: str) -> None:
|
|
|
207
207
|
|
|
208
208
|
@test.command(
|
|
209
209
|
name="run",
|
|
210
|
-
help="Run the test suite, a file, or a test
|
|
210
|
+
help="Run the test suite, a file, or a test",
|
|
211
211
|
)
|
|
212
212
|
@click.argument("name", nargs=-1)
|
|
213
213
|
@click.pass_context
|
tinybird/tb/modules/token.py
CHANGED
|
@@ -24,7 +24,7 @@ def token(ctx: Context) -> None:
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
@token.command(name="ls")
|
|
27
|
-
@click.option("--match", default=None, help="Retrieve any token matching the pattern.
|
|
27
|
+
@click.option("--match", default=None, help="Retrieve any token matching the pattern. For example, --match _test")
|
|
28
28
|
@click.pass_context
|
|
29
29
|
@coro
|
|
30
30
|
async def token_ls(
|
|
@@ -52,7 +52,7 @@ async def token_ls(
|
|
|
52
52
|
|
|
53
53
|
@token.command(name="rm")
|
|
54
54
|
@click.argument("token_id")
|
|
55
|
-
@click.option("--yes", is_flag=True, default=False, help="
|
|
55
|
+
@click.option("--yes", is_flag=True, default=False, help="Don't ask for confirmation")
|
|
56
56
|
@click.pass_context
|
|
57
57
|
@coro
|
|
58
58
|
async def token_rm(ctx: Context, token_id: str, yes: bool) -> None:
|
|
@@ -74,7 +74,7 @@ async def token_rm(ctx: Context, token_id: str, yes: bool) -> None:
|
|
|
74
74
|
|
|
75
75
|
@token.command(name="refresh")
|
|
76
76
|
@click.argument("token_id")
|
|
77
|
-
@click.option("--yes", is_flag=True, default=False, help="
|
|
77
|
+
@click.option("--yes", is_flag=True, default=False, help="Don't ask for confirmation")
|
|
78
78
|
@click.pass_context
|
|
79
79
|
@coro
|
|
80
80
|
async def token_refresh(ctx: Context, token_id: str, yes: bool) -> None:
|
|
@@ -347,4 +347,4 @@ async def create_static_token(ctx, name: str):
|
|
|
347
347
|
except Exception as e:
|
|
348
348
|
raise CLITokenException(FeedbackManager.error_exception(error=e))
|
|
349
349
|
|
|
350
|
-
click.echo("
|
|
350
|
+
click.echo("Token has been generated successfully.")
|
tinybird/tb/modules/workspace.py
CHANGED
|
@@ -91,12 +91,12 @@ async def workspace_current():
|
|
|
91
91
|
@click.argument("workspace_name", required=False)
|
|
92
92
|
@click.option("--starter_kit", "starter_kit", type=str, required=False, help="Use a Tinybird starter kit as a template")
|
|
93
93
|
@click.option("--starter-kit", "starter_kit", hidden=True)
|
|
94
|
-
@click.option("--user_token", is_flag=False, default=None, help="When passed,
|
|
94
|
+
@click.option("--user_token", is_flag=False, default=None, help="When passed, tb won't prompt asking for the token")
|
|
95
95
|
@click.option(
|
|
96
96
|
"--fork",
|
|
97
97
|
is_flag=True,
|
|
98
98
|
default=False,
|
|
99
|
-
help="When enabled,
|
|
99
|
+
help="When enabled, tb will share all data sources from the current workspace with the new one",
|
|
100
100
|
)
|
|
101
101
|
@click.pass_context
|
|
102
102
|
@coro
|
|
@@ -123,16 +123,16 @@ async def create_workspace(
|
|
|
123
123
|
await create_workspace_interactive(ctx, workspace_name, starter_kit, user_token, fork)
|
|
124
124
|
|
|
125
125
|
|
|
126
|
-
@workspace.command(name="delete", short_help="Delete a
|
|
126
|
+
@workspace.command(name="delete", short_help="Delete a workspace for your Tinybird user")
|
|
127
127
|
@click.argument("workspace_name_or_id")
|
|
128
|
-
@click.option("--user_token", is_flag=False, default=None, help="When passed,
|
|
128
|
+
@click.option("--user_token", is_flag=False, default=None, help="When passed, tb won't prompt asking for the token")
|
|
129
129
|
@click.option(
|
|
130
130
|
"--confirm_hard_delete",
|
|
131
131
|
default=None,
|
|
132
|
-
help="
|
|
132
|
+
help="Enter the name of the workspace to confirm you want to run a hard delete over the workspace",
|
|
133
133
|
hidden=True,
|
|
134
134
|
)
|
|
135
|
-
@click.option("--yes", is_flag=True, default=False, help="
|
|
135
|
+
@click.option("--yes", is_flag=True, default=False, help="Don't ask for confirmation")
|
|
136
136
|
@click.pass_context
|
|
137
137
|
@coro
|
|
138
138
|
async def delete_workspace(
|
|
@@ -60,10 +60,10 @@ def members(ctx: Context) -> None:
|
|
|
60
60
|
"""Workspace members management commands."""
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
@members.command(name="add", short_help="Adds members to the current
|
|
63
|
+
@members.command(name="add", short_help="Adds members to the current workspace")
|
|
64
64
|
@click.argument("members_emails")
|
|
65
65
|
@click.option("--role", is_flag=False, default=None, help="Role for the members being added", type=click.Choice(ROLES))
|
|
66
|
-
@click.option("--user_token", is_flag=False, default=None, help="When passed,
|
|
66
|
+
@click.option("--user_token", is_flag=False, default=None, help="When passed, tb won't prompt asking for it")
|
|
67
67
|
@click.pass_context
|
|
68
68
|
@coro
|
|
69
69
|
async def add_members_to_workspace(
|
|
@@ -111,13 +111,13 @@ async def list_members_in_workspace(ctx: Context) -> None:
|
|
|
111
111
|
echo_safe_humanfriendly_tables_format_smart_table(users, column_names=["email"])
|
|
112
112
|
|
|
113
113
|
|
|
114
|
-
@members.command(name="rm", short_help="Removes members from the current
|
|
114
|
+
@members.command(name="rm", short_help="Removes members from the current workspace")
|
|
115
115
|
@click.argument("members_emails")
|
|
116
|
-
@click.option("--user_token", is_flag=False, default=None, help="When passed,
|
|
116
|
+
@click.option("--user_token", is_flag=False, default=None, help="When passed, tb won't prompt asking for it")
|
|
117
117
|
@click.pass_context
|
|
118
118
|
@coro
|
|
119
119
|
async def remove_members_from_workspace(ctx: Context, members_emails: str, user_token: Optional[str]) -> None:
|
|
120
|
-
"""Removes members from the current
|
|
120
|
+
"""Removes members from the current workspace."""
|
|
121
121
|
|
|
122
122
|
cmd_ctx = await get_command_context(ctx)
|
|
123
123
|
|
|
@@ -163,7 +163,7 @@ async def remove_members_from_workspace(ctx: Context, members_emails: str, user_
|
|
|
163
163
|
@members.command(name="set-role", short_help="Sets the role for existing workspace members")
|
|
164
164
|
@click.argument("role", required=True, type=click.Choice(ROLES))
|
|
165
165
|
@click.argument("members_emails", required=True, type=str)
|
|
166
|
-
@click.option("--user_token", is_flag=False, default=None, help="When passed,
|
|
166
|
+
@click.option("--user_token", is_flag=False, default=None, help="When passed, tb won't prompt asking for it")
|
|
167
167
|
@click.pass_context
|
|
168
168
|
@coro
|
|
169
169
|
async def set_workspace_member_role(ctx: Context, role: str, members_emails: str, user_token: Optional[str]) -> None:
|
|
@@ -637,7 +637,7 @@ async def check_user_token(ctx: Context, token: str):
|
|
|
637
637
|
if not is_authenticated.get("is_valid", False):
|
|
638
638
|
raise CLIWorkspaceException(
|
|
639
639
|
FeedbackManager.error_exception(
|
|
640
|
-
error='Invalid token.
|
|
640
|
+
error='Invalid token. Make sure you are using the "user token" instead of the "admin your@email" token.'
|
|
641
641
|
)
|
|
642
642
|
)
|
|
643
643
|
if is_authenticated.get("is_valid") and not is_authenticated.get("is_user", False):
|
|
@@ -1183,7 +1183,7 @@ async def sync_data(ctx, datasource_name: str, yes: bool):
|
|
|
1183
1183
|
client: TinyB = ctx.obj["client"]
|
|
1184
1184
|
datasource = await client.get_datasource(datasource_name)
|
|
1185
1185
|
|
|
1186
|
-
VALID_DATASOURCES = ["bigquery", "snowflake", "s3", "gcs"]
|
|
1186
|
+
VALID_DATASOURCES = ["bigquery", "snowflake", "s3", "s3_iamrole", "gcs"]
|
|
1187
1187
|
if datasource["type"] not in VALID_DATASOURCES:
|
|
1188
1188
|
raise CLIException(FeedbackManager.error_sync_not_supported(valid_datasources=VALID_DATASOURCES))
|
|
1189
1189
|
|
tinybird/tornado_template.py
CHANGED
|
@@ -1161,7 +1161,8 @@ def check_valid_expr(expr):
|
|
|
1161
1161
|
elif isinstance(expr, ast.Subscript):
|
|
1162
1162
|
check_valid_expr(expr.value)
|
|
1163
1163
|
if isinstance(expr.slice, ast.Index):
|
|
1164
|
-
|
|
1164
|
+
# TODO: Slice does not seems to have a value attribute
|
|
1165
|
+
check_valid_expr(expr.slice.value) # type: ignore[attr-defined]
|
|
1165
1166
|
elif isinstance(expr.slice, ast.Slice):
|
|
1166
1167
|
if expr.slice.lower is not None:
|
|
1167
1168
|
check_valid_expr(expr.slice.lower)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: tinybird
|
|
3
|
+
Version: 0.0.1.dev69
|
|
4
|
+
Summary: Tinybird Command Line Tool
|
|
5
|
+
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
|
+
Author: Tinybird
|
|
7
|
+
Author-email: support@tinybird.co
|
|
8
|
+
Requires-Python: >=3.9, <3.13
|
|
9
|
+
Description-Content-Type: text/x-rst
|
|
10
|
+
Requires-Dist: aiofiles==24.1.0
|
|
11
|
+
Requires-Dist: anthropic==0.42.0
|
|
12
|
+
Requires-Dist: click<8.2,>=8.1.6
|
|
13
|
+
Requires-Dist: clickhouse-toolset==0.33.dev0
|
|
14
|
+
Requires-Dist: colorama==0.4.6
|
|
15
|
+
Requires-Dist: cryptography~=41.0.0
|
|
16
|
+
Requires-Dist: croniter==1.3.8
|
|
17
|
+
Requires-Dist: docker==7.1.0
|
|
18
|
+
Requires-Dist: GitPython~=3.1.32
|
|
19
|
+
Requires-Dist: humanfriendly~=8.2
|
|
20
|
+
Requires-Dist: prompt_toolkit==3.0.48
|
|
21
|
+
Requires-Dist: pydantic~=2.8.0
|
|
22
|
+
Requires-Dist: pyperclip==1.8.2
|
|
23
|
+
Requires-Dist: pyyaml<6.1,>=6.0
|
|
24
|
+
Requires-Dist: requests<3,>=2.28.1
|
|
25
|
+
Requires-Dist: shandy-sqlfmt==0.11.1
|
|
26
|
+
Requires-Dist: shandy-sqlfmt[jinjafmt]==0.11.1
|
|
27
|
+
Requires-Dist: toposort==1.10
|
|
28
|
+
Requires-Dist: tornado~=6.0.0
|
|
29
|
+
Requires-Dist: urllib3<2,>=1.26.14
|
|
30
|
+
Requires-Dist: watchdog==6.0.0
|
|
31
|
+
Requires-Dist: wheel
|
|
32
|
+
Requires-Dist: packaging<24,>=23.1
|
|
33
|
+
Requires-Dist: llm>=0.19
|
|
34
|
+
Requires-Dist: thefuzz==0.22.1
|
|
35
|
+
Provides-Extra: bigquery
|
|
36
|
+
Requires-Dist: gsutil==4.58; extra == "bigquery"
|
|
37
|
+
Requires-Dist: google-api-python-client==2.0.2; extra == "bigquery"
|
|
38
|
+
Requires-Dist: google-auth==1.27.1; extra == "bigquery"
|
|
39
|
+
Requires-Dist: google-auth-httplib2==0.1.0; extra == "bigquery"
|
|
40
|
+
Requires-Dist: google-cloud-storage==2.4.0; extra == "bigquery"
|
|
41
|
+
Requires-Dist: google-cloud-bigquery==2.11.0; extra == "bigquery"
|
|
42
|
+
Provides-Extra: snowflake
|
|
43
|
+
Requires-Dist: snowflake-connector-python~=3.12.3; extra == "snowflake"
|
|
44
|
+
Requires-Dist: gsutil==4.58; extra == "snowflake"
|
|
45
|
+
Requires-Dist: google-api-python-client==2.0.2; extra == "snowflake"
|
|
46
|
+
Requires-Dist: google-auth==1.27.1; extra == "snowflake"
|
|
47
|
+
Requires-Dist: google-auth-httplib2==0.1.0; extra == "snowflake"
|
|
48
|
+
Requires-Dist: google-cloud-storage==2.4.0; extra == "snowflake"
|
|
49
|
+
Requires-Dist: oauth2client==3.0.0; extra == "snowflake"
|
|
50
|
+
Requires-Dist: chardet<4,>=3.0.2; extra == "snowflake"
|
|
51
|
+
Requires-Dist: pyOpenSSL<20.0.0,>=16.2.0; extra == "snowflake"
|
|
52
|
+
Dynamic: author
|
|
53
|
+
Dynamic: author-email
|
|
54
|
+
Dynamic: description
|
|
55
|
+
Dynamic: description-content-type
|
|
56
|
+
Dynamic: home-page
|
|
57
|
+
Dynamic: provides-extra
|
|
58
|
+
Dynamic: requires-dist
|
|
59
|
+
Dynamic: requires-python
|
|
60
|
+
Dynamic: summary
|
|
61
|
+
|
|
62
|
+
Tinybird CLI
|
|
63
|
+
=============
|
|
64
|
+
|
|
65
|
+
The Tinybird command-line tool allows you to use all the Tinybird functionality directly from the command line. Additionally, it includes several functions to create and manage data projects easily.
|
|
66
|
+
|
|
67
|
+
Changelog
|
|
68
|
+
----------
|
|
69
|
+
|
|
70
|
+
0.0.1dev1
|
|
71
|
+
***********
|
|
72
|
+
|
|
73
|
+
* Initial release of the Tinybird CLI
|
|
@@ -2,60 +2,60 @@ tinybird/__cli__.py,sha256=esPl5QDTzuQgHe5FuxWLm-fURFigGGwjnYLh9GuWUw4,232
|
|
|
2
2
|
tinybird/client.py,sha256=W5Xttnz0bzwqqVGNJJs-4Ca2AbtCMh3URuQYPJ5APsE,52013
|
|
3
3
|
tinybird/config.py,sha256=cd_RH7ZjqGjpWwu0efPkhS8VxD9K6Jix4QY2W3w1Pvs,5811
|
|
4
4
|
tinybird/connectors.py,sha256=7Gjms7b5MAaBFGi3xytsJurCylprONpFcYrzp4Fw2Rc,15241
|
|
5
|
-
tinybird/context.py,sha256=
|
|
5
|
+
tinybird/context.py,sha256=VaMhyHruH-uyMypPDfxtuo4scS18b7rxCCdeUVm6ysg,1301
|
|
6
6
|
tinybird/datatypes.py,sha256=XNypumfqNjsvLJ5iNXnbVHRvAJe0aQwI3lS6Cxox-e0,10979
|
|
7
7
|
tinybird/feedback_manager.py,sha256=ADuy1yC3fCFM_ii_Haphg8Gdzapa5pX9dlRTVbuUqxs,67990
|
|
8
8
|
tinybird/git_settings.py,sha256=Sw_8rGmribEFJ4Z_6idrVytxpFYk7ez8ei0qHULzs3E,3934
|
|
9
9
|
tinybird/prompts.py,sha256=LQfE0ruY9A7z1iqtt6xTkW-1NlHbXl7LbKqzfdOsPxA,30612
|
|
10
10
|
tinybird/sql.py,sha256=LBi74GxhNAYTb6m2-KNGpAkguSKh7rcvBbERbE7nalA,46195
|
|
11
|
-
tinybird/sql_template.py,sha256=
|
|
11
|
+
tinybird/sql_template.py,sha256=zUK-fsrvKISNsTquEFL40iD6-fMoL0RF3vxHn4PZYvw,93500
|
|
12
12
|
tinybird/sql_template_fmt.py,sha256=KUHdj5rYCYm_rKKdXYSJAE9vIyXUQLB0YSZnUXHeBlY,10196
|
|
13
|
-
tinybird/sql_toolset.py,sha256=
|
|
13
|
+
tinybird/sql_toolset.py,sha256=32SNvxRFKQYWTvYPMJ_u3ukcd1hKZyEqx8T2cv2412w,14697
|
|
14
14
|
tinybird/syncasync.py,sha256=IPnOx6lMbf9SNddN1eBtssg8vCLHMt76SuZ6YNYm-Yk,27761
|
|
15
|
-
tinybird/tornado_template.py,sha256=
|
|
15
|
+
tinybird/tornado_template.py,sha256=fUKIFrZLe0WyMFmV-mkjIdCSeFcZMBL3Uet4eHcids0,41960
|
|
16
16
|
tinybird/ch_utils/constants.py,sha256=aYvg2C_WxYWsnqPdZB1ZFoIr8ZY-XjUXYyHKE9Ansj0,3890
|
|
17
|
-
tinybird/ch_utils/engine.py,sha256=
|
|
18
|
-
tinybird/tb/__cli__.py,sha256=
|
|
17
|
+
tinybird/ch_utils/engine.py,sha256=AUAww-KjGOZg9h0IBlKA3FeacJYB4rOtqcTGJhFM-g8,40392
|
|
18
|
+
tinybird/tb/__cli__.py,sha256=oDKDPPvR2NMgaawv4tiYkQ17clB9vn1VDY4J4rqpHxI,251
|
|
19
19
|
tinybird/tb/cli.py,sha256=FD1pfbzu9YHJHEG6Vtn_EwPLTYhwqw-I6AxXeTaRHU8,926
|
|
20
|
-
tinybird/tb/modules/auth.py,sha256=
|
|
20
|
+
tinybird/tb/modules/auth.py,sha256=vBA-KsrjAp77kFunGSM-4o7AFdfO7ac4dnrHKrx0alI,9020
|
|
21
21
|
tinybird/tb/modules/build.py,sha256=UN1d7EZ93VOlPCrtsay-KLgZnzxn2NCBDY3wvrUSP1Q,9198
|
|
22
22
|
tinybird/tb/modules/cicd.py,sha256=xxXwy-QekJcG14kkJeGNl7LkHduhZXfvBZE8WrU6-t4,5351
|
|
23
|
-
tinybird/tb/modules/cli.py,sha256=
|
|
24
|
-
tinybird/tb/modules/common.py,sha256=
|
|
23
|
+
tinybird/tb/modules/cli.py,sha256=AvqH7x3wiLShaXWxIsMRidPCmJs03ZYwuFzQZz-nMyU,15919
|
|
24
|
+
tinybird/tb/modules/common.py,sha256=XZY0nWkK68vgh2Vml5JzyQuEWIyf2igq7IrAu0n94Lo,73203
|
|
25
25
|
tinybird/tb/modules/config.py,sha256=mie3oMVTf5YOUFEiLs88P16U4LkJafJjSpjwyAkFHog,10979
|
|
26
26
|
tinybird/tb/modules/copy.py,sha256=Aq6wh_wjRiyLQtEOKF9pKLPgJhSvbGTFWIw_LJB0t0U,5801
|
|
27
27
|
tinybird/tb/modules/create.py,sha256=I01JDENOyGKK0Umd2_1Om_nFGP8Uk9vxaOw7PygK02o,12302
|
|
28
|
-
tinybird/tb/modules/datasource.py,sha256=
|
|
29
|
-
tinybird/tb/modules/deployment.py,sha256=
|
|
30
|
-
tinybird/tb/modules/endpoint.py,sha256=
|
|
28
|
+
tinybird/tb/modules/datasource.py,sha256=9NxmicauGwLwfcKAe3Vyiu5JHmYDl6iYmBJweu4Hl2s,14735
|
|
29
|
+
tinybird/tb/modules/deployment.py,sha256=Xtaty4vPoSFk189cuupei3h3ze1FpPvi_dA7koPvjoI,16222
|
|
30
|
+
tinybird/tb/modules/endpoint.py,sha256=zQJgJXTzMB3hPO-3Xnppi0Pv8byZunBNhbbmMgKtijE,11915
|
|
31
31
|
tinybird/tb/modules/exceptions.py,sha256=4A2sSjCEqKUMqpP3WI00zouCWW4uLaghXXLZBSw04mY,3363
|
|
32
32
|
tinybird/tb/modules/feedback_manager.py,sha256=mrw5tdYycfvg6WLXlM0KIjfJardm_aNpnJkUg2vH0cA,68463
|
|
33
|
-
tinybird/tb/modules/fmt.py,sha256=
|
|
33
|
+
tinybird/tb/modules/fmt.py,sha256=j6W0X_h88oxfFppakJgZ8ubAUwwrCGsfVjKw4gg8e5s,3551
|
|
34
34
|
tinybird/tb/modules/job.py,sha256=956Pj8BEEsiD2GZsV9RKKVM3I_CveOLgS82lykO5ukk,2963
|
|
35
35
|
tinybird/tb/modules/llm.py,sha256=AC0VSphTOM2t-v1_3NLvNN_FIbgMo4dTyMqIv5nniPo,835
|
|
36
36
|
tinybird/tb/modules/llm_utils.py,sha256=nS9r4FAElJw8yXtmdYrx-rtI2zXR8qXfi1QqUDCfxvg,3469
|
|
37
37
|
tinybird/tb/modules/local.py,sha256=_PIa-1M-72bv9rhLwqaNthJM1ZhvcjWXFChZAfEPXRs,5658
|
|
38
38
|
tinybird/tb/modules/local_common.py,sha256=W1fEnB1vBQ4YC5U1PdA0w0g3cTV78bQ5R-lRxdDj5-Y,2868
|
|
39
39
|
tinybird/tb/modules/login.py,sha256=EGxwVRmMX1Y7ZeCRyA8fqaCWpYYk7NvnZ3x_1g0NlYA,6063
|
|
40
|
-
tinybird/tb/modules/materialization.py,sha256=
|
|
41
|
-
tinybird/tb/modules/mock.py,sha256=
|
|
42
|
-
tinybird/tb/modules/pipe.py,sha256=
|
|
43
|
-
tinybird/tb/modules/project.py,sha256=
|
|
40
|
+
tinybird/tb/modules/materialization.py,sha256=dESybok66Fn7XLzQQr-fBCDNf5xQL8wkRiD2QBr5lOg,5748
|
|
41
|
+
tinybird/tb/modules/mock.py,sha256=DVZjPv9p8k5fntHcLHnIsWS7KBa1jF02BYA_Ey4XWf4,3824
|
|
42
|
+
tinybird/tb/modules/pipe.py,sha256=PbCM31q9lVB9xPWvPBhlpW53MGFGvzVv81trxC06kDY,2428
|
|
43
|
+
tinybird/tb/modules/project.py,sha256=QdOG65Hcc6r_eQ938CfZeIXyp38RkiTYNPupgqy2gP0,2948
|
|
44
44
|
tinybird/tb/modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
|
|
45
|
-
tinybird/tb/modules/shell.py,sha256=
|
|
45
|
+
tinybird/tb/modules/shell.py,sha256=qWpZ9TwDSDq3YsBxueNtezsslp3N7pwUPRF8HIlTjOo,13828
|
|
46
46
|
tinybird/tb/modules/table.py,sha256=4XrtjM-N0zfNtxVkbvLDQQazno1EPXnxTyo7llivfXk,11035
|
|
47
47
|
tinybird/tb/modules/tag.py,sha256=anPmMUBc-TbFovlpFi8GPkKA18y7Y0GczMsMms5TZsU,3502
|
|
48
48
|
tinybird/tb/modules/telemetry.py,sha256=iEGnMuCuNhvF6ln__j6X9MSTwL_0Hm-GgFHHHvhfknk,10466
|
|
49
|
-
tinybird/tb/modules/test.py,sha256=
|
|
50
|
-
tinybird/tb/modules/token.py,sha256=
|
|
49
|
+
tinybird/tb/modules/test.py,sha256=tY7_FJRSL6EdztypWlvDJi5QpXDLS5dpO0i_dpGuzkI,11528
|
|
50
|
+
tinybird/tb/modules/token.py,sha256=WEB2xqRgOierJ_S7TrZLEpLpQ9mkXcYLH2-xipjoGDc,12814
|
|
51
51
|
tinybird/tb/modules/watch.py,sha256=90FUrSD6cYfOi7GsEHfq_oTI6kap7uc8CbG0t3j_Tus,4953
|
|
52
|
-
tinybird/tb/modules/workspace.py,sha256=
|
|
53
|
-
tinybird/tb/modules/workspace_members.py,sha256=
|
|
52
|
+
tinybird/tb/modules/workspace.py,sha256=7gOgt10j9emleqQ43BA6jU0CZjJxw7L5gDZhCxGafI4,6400
|
|
53
|
+
tinybird/tb/modules/workspace_members.py,sha256=Vb5XEaKmkfONyfg2MS5EcpwolMvv7GLwFS5m2EuobT8,8726
|
|
54
54
|
tinybird/tb/modules/datafile/build.py,sha256=seGFSvmgyRrAM1-icsKBkuog3WccfGUYFTPT-xoA5W8,50940
|
|
55
|
-
tinybird/tb/modules/datafile/build_common.py,sha256=
|
|
56
|
-
tinybird/tb/modules/datafile/build_datasource.py,sha256=
|
|
55
|
+
tinybird/tb/modules/datafile/build_common.py,sha256=rT7VJ5mnQ68R_8US91DAtkusfvjWuG_NObOzNgtN_ko,4562
|
|
56
|
+
tinybird/tb/modules/datafile/build_datasource.py,sha256=VjxaKKLZhPYt3XHOyMmfoqEAWAPI5D78T-8FOaN77MY,17355
|
|
57
57
|
tinybird/tb/modules/datafile/build_pipe.py,sha256=Jgv3YKIvMfjPiSIdw1k2mpaoDdAWMiMRaSHwRgyI97E,28258
|
|
58
|
-
tinybird/tb/modules/datafile/common.py,sha256=
|
|
58
|
+
tinybird/tb/modules/datafile/common.py,sha256=1sKkQnyKOaFARQzORncpL6cRVpV9GDOD4oC36daX-Hk,79343
|
|
59
59
|
tinybird/tb/modules/datafile/diff.py,sha256=-0J7PsBO64T7LOZSkZ4ZFHHCPvT7cKItnJkbz2PkndU,6754
|
|
60
60
|
tinybird/tb/modules/datafile/exceptions.py,sha256=8rw2umdZjtby85QbuRKFO5ETz_eRHwUY5l7eHsy1wnI,556
|
|
61
61
|
tinybird/tb/modules/datafile/fixture.py,sha256=XQpbppUQ4cow7dMzHs7OZBYBXA2PI5AOCmNdMDClbKo,833
|
|
@@ -64,18 +64,18 @@ tinybird/tb/modules/datafile/format_datasource.py,sha256=gpRsGnDEMxEo0pIlEHXKvyu
|
|
|
64
64
|
tinybird/tb/modules/datafile/format_pipe.py,sha256=58iSTrJ5lg-IsbpX8TQumQTuZ6UIotMsCIkNJd1M-pM,7418
|
|
65
65
|
tinybird/tb/modules/datafile/parse_datasource.py,sha256=kk35PzesoJOd0LKjYp4kOyCwq4Qo4TiZnoI9qcXjB4k,1519
|
|
66
66
|
tinybird/tb/modules/datafile/parse_pipe.py,sha256=snoy8Ac_Sat7LIXLAKzxjJSl2-TKg9FaZTooxrx6muE,3420
|
|
67
|
-
tinybird/tb/modules/datafile/pipe_checker.py,sha256=
|
|
67
|
+
tinybird/tb/modules/datafile/pipe_checker.py,sha256=LnDLGIHLJ3N7qHb2ptEbPr8CoczNfGwpjOY8EMdxfHQ,24649
|
|
68
68
|
tinybird/tb/modules/datafile/pull.py,sha256=vcjMUbjnZ9XQMGmL33J3ElpbXBTat8Yzp-haeDggZd4,5967
|
|
69
69
|
tinybird/tb/modules/tinyunit/tinyunit.py,sha256=LZGrsvIAUy5O2bZtGbi9O80QGIfXe_Du8c0PDNxeQcc,11727
|
|
70
70
|
tinybird/tb/modules/tinyunit/tinyunit_lib.py,sha256=hGh1ZaXC1af7rKnX7222urkj0QJMhMWclqMy59dOqwE,1922
|
|
71
71
|
tinybird/tb_cli_modules/cicd.py,sha256=0lMkb6CVOFZl5HOwgY8mK4T4mgI7O8335UngLXtCc-c,13851
|
|
72
|
-
tinybird/tb_cli_modules/common.py,sha256=
|
|
72
|
+
tinybird/tb_cli_modules/common.py,sha256=NpR56fwwj6u--gLdTIZodvMe4LsWAtnphX-kw4hoKGs,78726
|
|
73
73
|
tinybird/tb_cli_modules/config.py,sha256=6u6B5QCdiQLbJkCkwtnKGs9H3nP-KXXhC75mF7B-1DQ,11464
|
|
74
74
|
tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
|
|
75
75
|
tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
|
|
76
76
|
tinybird/tb_cli_modules/telemetry.py,sha256=iEGnMuCuNhvF6ln__j6X9MSTwL_0Hm-GgFHHHvhfknk,10466
|
|
77
|
-
tinybird-0.0.1.
|
|
78
|
-
tinybird-0.0.1.
|
|
79
|
-
tinybird-0.0.1.
|
|
80
|
-
tinybird-0.0.1.
|
|
81
|
-
tinybird-0.0.1.
|
|
77
|
+
tinybird-0.0.1.dev69.dist-info/METADATA,sha256=Qy1Ob_W4u71B64I99GYQSlFunPcsP6kz7ie9WBl1I5I,2585
|
|
78
|
+
tinybird-0.0.1.dev69.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
79
|
+
tinybird-0.0.1.dev69.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
|
|
80
|
+
tinybird-0.0.1.dev69.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
|
|
81
|
+
tinybird-0.0.1.dev69.dist-info/RECORD,,
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: tinybird
|
|
3
|
-
Version: 0.0.1.dev68
|
|
4
|
-
Summary: Tinybird Command Line Tool
|
|
5
|
-
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
|
-
Author: Tinybird
|
|
7
|
-
Author-email: support@tinybird.co
|
|
8
|
-
Requires-Python: >=3.9, <3.13
|
|
9
|
-
Description-Content-Type: text/x-rst
|
|
10
|
-
Requires-Dist: aiofiles (==24.1.0)
|
|
11
|
-
Requires-Dist: anthropic (==0.42.0)
|
|
12
|
-
Requires-Dist: click (<8.2,>=8.1.6)
|
|
13
|
-
Requires-Dist: clickhouse-toolset (==0.33.dev0)
|
|
14
|
-
Requires-Dist: colorama (==0.4.6)
|
|
15
|
-
Requires-Dist: cryptography (~=41.0.0)
|
|
16
|
-
Requires-Dist: croniter (==1.3.8)
|
|
17
|
-
Requires-Dist: docker (==7.1.0)
|
|
18
|
-
Requires-Dist: GitPython (~=3.1.32)
|
|
19
|
-
Requires-Dist: humanfriendly (~=8.2)
|
|
20
|
-
Requires-Dist: prompt-toolkit (==3.0.48)
|
|
21
|
-
Requires-Dist: pydantic (~=2.8.0)
|
|
22
|
-
Requires-Dist: pyperclip (==1.8.2)
|
|
23
|
-
Requires-Dist: pyyaml (<6.1,>=6.0)
|
|
24
|
-
Requires-Dist: requests (<3,>=2.28.1)
|
|
25
|
-
Requires-Dist: shandy-sqlfmt (==0.11.1)
|
|
26
|
-
Requires-Dist: shandy-sqlfmt[jinjafmt] (==0.11.1)
|
|
27
|
-
Requires-Dist: toposort (==1.10)
|
|
28
|
-
Requires-Dist: tornado (~=6.0.0)
|
|
29
|
-
Requires-Dist: urllib3 (<2,>=1.26.14)
|
|
30
|
-
Requires-Dist: watchdog (==6.0.0)
|
|
31
|
-
Requires-Dist: wheel
|
|
32
|
-
Requires-Dist: packaging (<24,>=23.1)
|
|
33
|
-
Requires-Dist: llm (>=0.19)
|
|
34
|
-
Requires-Dist: thefuzz (==0.22.1)
|
|
35
|
-
Provides-Extra: bigquery
|
|
36
|
-
Requires-Dist: gsutil (==4.58) ; extra == 'bigquery'
|
|
37
|
-
Requires-Dist: google-api-python-client (==2.0.2) ; extra == 'bigquery'
|
|
38
|
-
Requires-Dist: google-auth (==1.27.1) ; extra == 'bigquery'
|
|
39
|
-
Requires-Dist: google-auth-httplib2 (==0.1.0) ; extra == 'bigquery'
|
|
40
|
-
Requires-Dist: google-cloud-storage (==2.4.0) ; extra == 'bigquery'
|
|
41
|
-
Requires-Dist: google-cloud-bigquery (==2.11.0) ; extra == 'bigquery'
|
|
42
|
-
Provides-Extra: snowflake
|
|
43
|
-
Requires-Dist: snowflake-connector-python (~=3.12.3) ; extra == 'snowflake'
|
|
44
|
-
Requires-Dist: gsutil (==4.58) ; extra == 'snowflake'
|
|
45
|
-
Requires-Dist: google-api-python-client (==2.0.2) ; extra == 'snowflake'
|
|
46
|
-
Requires-Dist: google-auth (==1.27.1) ; extra == 'snowflake'
|
|
47
|
-
Requires-Dist: google-auth-httplib2 (==0.1.0) ; extra == 'snowflake'
|
|
48
|
-
Requires-Dist: google-cloud-storage (==2.4.0) ; extra == 'snowflake'
|
|
49
|
-
Requires-Dist: oauth2client (==3.0.0) ; extra == 'snowflake'
|
|
50
|
-
Requires-Dist: chardet (<4,>=3.0.2) ; extra == 'snowflake'
|
|
51
|
-
Requires-Dist: pyOpenSSL (<20.0.0,>=16.2.0) ; extra == 'snowflake'
|
|
52
|
-
|
|
53
|
-
Tinybird CLI
|
|
54
|
-
=============
|
|
55
|
-
|
|
56
|
-
The Tinybird command-line tool allows you to use all the Tinybird functionality directly from the command line. Additionally, it includes several functions to create and manage data projects easily.
|
|
57
|
-
|
|
58
|
-
Changelog
|
|
59
|
-
----------
|
|
60
|
-
|
|
61
|
-
0.0.1dev1
|
|
62
|
-
***********
|
|
63
|
-
|
|
64
|
-
* Initial release of the Tinybird CLI
|
|
File without changes
|
|
File without changes
|