tinybird-cli 6.4.0__py3-none-any.whl → 6.4.2.dev0__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.
- tinybird/__cli__.py +2 -2
- tinybird/config.py +0 -2
- tinybird/datafile_common.py +9 -7
- tinybird/git_settings.py +1 -1
- tinybird/sql.py +14 -8
- tinybird/sql_template.py +5 -4
- tinybird/sql_toolset.py +0 -18
- tinybird/tb_cli_modules/auth.py +1 -1
- tinybird/tb_cli_modules/branch.py +8 -9
- tinybird/tb_cli_modules/cli.py +10 -10
- tinybird/tb_cli_modules/common.py +11 -12
- tinybird/tb_cli_modules/datasource.py +4 -4
- tinybird/tb_cli_modules/workspace.py +2 -2
- {tinybird_cli-6.4.0.dist-info → tinybird_cli-6.4.2.dev0.dist-info}/METADATA +8 -2
- {tinybird_cli-6.4.0.dist-info → tinybird_cli-6.4.2.dev0.dist-info}/RECORD +18 -18
- {tinybird_cli-6.4.0.dist-info → tinybird_cli-6.4.2.dev0.dist-info}/WHEEL +0 -0
- {tinybird_cli-6.4.0.dist-info → tinybird_cli-6.4.2.dev0.dist-info}/entry_points.txt +0 -0
- {tinybird_cli-6.4.0.dist-info → tinybird_cli-6.4.2.dev0.dist-info}/top_level.txt +0 -0
tinybird/__cli__.py
CHANGED
tinybird/config.py
CHANGED
|
@@ -37,7 +37,6 @@ LEGACY_HOSTS = {
|
|
|
37
37
|
"https://api.wadus2.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus2",
|
|
38
38
|
"https://api.wadus3.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus3",
|
|
39
39
|
"https://api.wadus4.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus4",
|
|
40
|
-
"https://api.wadus5.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus5",
|
|
41
40
|
"https://api.wadus1.aws.tinybird.co": "https://app.wadus.tinybird.co/aws/wadus1",
|
|
42
41
|
"https://api.wadus2.aws.tinybird.co": "https://app.wadus.tinybird.co/aws/wadus2",
|
|
43
42
|
"https://api.wadus3.aws.tinybird.co": "https://app.wadus.tinybird.co/aws/wadus3",
|
|
@@ -59,7 +58,6 @@ LEGACY_HOSTS = {
|
|
|
59
58
|
"https://ui.wadus2.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus2",
|
|
60
59
|
"https://ui.wadus3.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus3",
|
|
61
60
|
"https://ui.wadus4.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus4",
|
|
62
|
-
"https://ui.wadus5.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus5",
|
|
63
61
|
"https://ui.wadus1.aws.tinybird.co": "https://app.wadus.tinybird.co/aws/wadus1",
|
|
64
62
|
"https://ui.wadus2.aws.tinybird.co": "https://app.wadus.tinybird.co/aws/wadus2",
|
|
65
63
|
"https://ui.wadus3.aws.tinybird.co": "https://app.wadus.tinybird.co/aws/wadus3",
|
tinybird/datafile_common.py
CHANGED
|
@@ -594,7 +594,9 @@ class Deployment:
|
|
|
594
594
|
):
|
|
595
595
|
if self.is_git_release:
|
|
596
596
|
if not self.current_release:
|
|
597
|
-
raise CLIGitReleaseException(
|
|
597
|
+
raise CLIGitReleaseException(
|
|
598
|
+
FeedbackManager.error_init_release(workspace=self.current_ws["name"], cli="tb")
|
|
599
|
+
)
|
|
598
600
|
self.cli_git_release = CLIGitRelease()
|
|
599
601
|
if not use_main:
|
|
600
602
|
self.cli_git_release.validate_local_for_release(self.current_release, check_outdated=check_outdated)
|
|
@@ -613,7 +615,7 @@ class Deployment:
|
|
|
613
615
|
# error until we support it https://gitlab.com/tinybird/analytics/-/issues/9655
|
|
614
616
|
for d in diffs:
|
|
615
617
|
if self.cli_git_release.ChangeType(d.change_type) == self.cli_git_release.ChangeType.RENAMED:
|
|
616
|
-
raise CLIGitReleaseException(FeedbackManager.error_unsupported_diff())
|
|
618
|
+
raise CLIGitReleaseException(FeedbackManager.error_unsupported_diff(cli="tb"))
|
|
617
619
|
if not diffs:
|
|
618
620
|
click.echo(FeedbackManager.info_git_release_no_diffs())
|
|
619
621
|
changed = self.cli_git_release.get_changes_from_diffs(diffs, filenames)
|
|
@@ -701,10 +703,10 @@ class Deployment:
|
|
|
701
703
|
release = await self.cli_git_release.update_release(self.tb_client, self.current_ws, commit)
|
|
702
704
|
click.echo(FeedbackManager.success_git_release(release_commit=release["commit"]))
|
|
703
705
|
else:
|
|
704
|
-
click.echo(FeedbackManager.warning_no_release())
|
|
706
|
+
click.echo(FeedbackManager.warning_no_release(cli="tb"))
|
|
705
707
|
except Exception as e:
|
|
706
708
|
if self.only_changes:
|
|
707
|
-
click.echo(FeedbackManager.warning_no_release())
|
|
709
|
+
click.echo(FeedbackManager.warning_no_release(cli="tb"))
|
|
708
710
|
else:
|
|
709
711
|
raise e
|
|
710
712
|
|
|
@@ -3383,7 +3385,7 @@ async def new_ds(
|
|
|
3383
3385
|
|
|
3384
3386
|
if alter_response:
|
|
3385
3387
|
if git_release and not skip_confirmation:
|
|
3386
|
-
click.echo(FeedbackManager.info_custom_deployment())
|
|
3388
|
+
click.echo(FeedbackManager.info_custom_deployment(cli="tb"))
|
|
3387
3389
|
click.echo("***************************************")
|
|
3388
3390
|
click.echo("***************************************")
|
|
3389
3391
|
click.echo(FeedbackManager.info_datasource_doesnt_match(datasource=ds_name))
|
|
@@ -4270,13 +4272,13 @@ async def folder_push(
|
|
|
4270
4272
|
existing_resources: List[str] = [x["name"] for x in datasources] + [x["name"] for x in pipes]
|
|
4271
4273
|
# replace workspace mapping names
|
|
4272
4274
|
for old_ws, new_ws in workspace_map.items():
|
|
4273
|
-
existing_resources = [re.sub(f"^{old_ws}
|
|
4275
|
+
existing_resources = [re.sub(f"^{old_ws}\\.", f"{new_ws}.", x) for x in existing_resources]
|
|
4274
4276
|
|
|
4275
4277
|
remote_resource_names = [get_remote_resource_name_without_version(x) for x in existing_resources]
|
|
4276
4278
|
|
|
4277
4279
|
# replace workspace mapping names
|
|
4278
4280
|
for old_ws, new_ws in workspace_map.items():
|
|
4279
|
-
remote_resource_names = [re.sub(f"^{old_ws}
|
|
4281
|
+
remote_resource_names = [re.sub(f"^{old_ws}\\.", f"{new_ws}.", x) for x in remote_resource_names]
|
|
4280
4282
|
|
|
4281
4283
|
if not filenames:
|
|
4282
4284
|
filenames = get_project_filenames(folder)
|
tinybird/git_settings.py
CHANGED
|
@@ -71,7 +71,7 @@ VERSION=0.0.0
|
|
|
71
71
|
# TB_SKIP_REGRESSION=0
|
|
72
72
|
|
|
73
73
|
# Use `OBFUSCATE_REGEX_PATTERN` and `OBFUSCATE_PATTERN_SEPARATOR` environment variables to define a regex pattern and a separator (in case of a single string with multiple regex) to obfuscate secrets in the CLI output.
|
|
74
|
-
# OBFUSCATE_REGEX_PATTERN="https://(www
|
|
74
|
+
# OBFUSCATE_REGEX_PATTERN="https://(www\\.)?[^/]+||^Follow these instructions =>"
|
|
75
75
|
# OBFUSCATE_PATTERN_SEPARATOR=||
|
|
76
76
|
##########
|
|
77
77
|
"""
|
tinybird/sql.py
CHANGED
|
@@ -6,7 +6,7 @@ from dataclasses import dataclass
|
|
|
6
6
|
from typing import Any, Dict, Iterable, List, Optional
|
|
7
7
|
|
|
8
8
|
valid_chars_name: str = string.ascii_letters + string.digits + "._`*<>+-'"
|
|
9
|
-
valid_chars_fn: str = valid_chars_name + "[]()
|
|
9
|
+
valid_chars_fn: str = valid_chars_name + "[](),=!?:/% \n\t\r"
|
|
10
10
|
# Use sets for O(1) membership checks in hot loops
|
|
11
11
|
_VALID_CHARS_NAME_SET = set(valid_chars_name)
|
|
12
12
|
_VALID_CHARS_FN_SET = set(valid_chars_fn)
|
|
@@ -233,10 +233,21 @@ def try_to_fix_nullable_in_simple_aggregating_function(t: str) -> Optional[str]:
|
|
|
233
233
|
if match := _RE_TRY_FIX_NULLABLE_SAF.search(t):
|
|
234
234
|
fn = match.group(1)
|
|
235
235
|
inner_type = match.group(2)
|
|
236
|
-
|
|
236
|
+
if "Nullable(" not in inner_type:
|
|
237
|
+
result = f"SimpleAggregateFunction({fn}, Nullable({inner_type}))"
|
|
237
238
|
return result
|
|
238
239
|
|
|
239
240
|
|
|
241
|
+
def wrap_nullable(col: dict[str, Any]):
|
|
242
|
+
if col["nullable"]:
|
|
243
|
+
if (col_type := try_to_fix_nullable_in_simple_aggregating_function(col["type"])) is None:
|
|
244
|
+
# Skip wrapping if Nullable already present, e.g. LowCardinality(Nullable(String))
|
|
245
|
+
col_type = col["type"] if "Nullable(" in col["type"] else "Nullable(%s)" % col["type"]
|
|
246
|
+
else:
|
|
247
|
+
col_type = col["type"]
|
|
248
|
+
return col_type
|
|
249
|
+
|
|
250
|
+
|
|
240
251
|
def schema_to_sql_columns(schema: List[Dict[str, Any]], skip_jsonpaths: bool = False) -> List[str]:
|
|
241
252
|
"""return an array with each column in SQL
|
|
242
253
|
>>> schema_to_sql_columns([{'name': 'temperature', 'type': 'Float32', 'codec': None, 'default_value': None, 'nullable': False, 'normalized_name': 'temperature'}, {'name': 'temperature_delta', 'type': 'Float32', 'codec': 'CODEC(Delta(4), LZ4))', 'default_value': 'MATERIALIZED temperature', 'nullable': False, 'normalized_name': 'temperature_delta'}])
|
|
@@ -255,12 +266,7 @@ def schema_to_sql_columns(schema: List[Dict[str, Any]], skip_jsonpaths: bool = F
|
|
|
255
266
|
columns: List[str] = []
|
|
256
267
|
for x in schema:
|
|
257
268
|
name = x["normalized_name"] if "normalized_name" in x else x["name"]
|
|
258
|
-
|
|
259
|
-
if (_type := try_to_fix_nullable_in_simple_aggregating_function(x["type"])) is None:
|
|
260
|
-
# Skip wrapping if Nullable already present, e.g. LowCardinality(Nullable(String))
|
|
261
|
-
_type = x["type"] if "Nullable(" in x["type"] else "Nullable(%s)" % x["type"]
|
|
262
|
-
else:
|
|
263
|
-
_type = x["type"]
|
|
269
|
+
_type = wrap_nullable(x)
|
|
264
270
|
parts = [col_name(name, backquotes=True), _type]
|
|
265
271
|
if x.get("jsonpath", None) and not skip_jsonpaths:
|
|
266
272
|
parts.append(f"`json:{x['jsonpath']}`")
|
tinybird/sql_template.py
CHANGED
|
@@ -20,6 +20,8 @@ from tinybird.context import (
|
|
|
20
20
|
from .datatypes import testers
|
|
21
21
|
from .tornado_template import VALID_CUSTOM_FUNCTION_NAMES, SecurityException, Template
|
|
22
22
|
|
|
23
|
+
VALID_ACTIVATE_FEATURES = frozenset(["analyzer", "parallel_replicas", "optimize_aggregation_in_order"])
|
|
24
|
+
|
|
23
25
|
TB_SECRET_IN_TEST_MODE = "tb_secret_dont_raise"
|
|
24
26
|
TB_SECRET_PREFIX = "tb_secret_"
|
|
25
27
|
CH_PARAM_PREFIX = "param_"
|
|
@@ -1463,10 +1465,9 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1463
1465
|
return Expression(f"-- cache_ttl {ttl_expression}\n")
|
|
1464
1466
|
|
|
1465
1467
|
def set_activate(feature):
|
|
1466
|
-
|
|
1467
|
-
if feature not in valid_features:
|
|
1468
|
+
if feature not in VALID_ACTIVATE_FEATURES:
|
|
1468
1469
|
raise SQLTemplateException(f"'{feature}' is not a valid 'activate' argument")
|
|
1469
|
-
template_execution_results
|
|
1470
|
+
template_execution_results.setdefault("activate", set()).add(feature)
|
|
1470
1471
|
return Expression(f"-- activate {feature}\n")
|
|
1471
1472
|
|
|
1472
1473
|
def set_disable_feature(feature):
|
|
@@ -2143,7 +2144,7 @@ def get_var_data(content, node_id=None):
|
|
|
2143
2144
|
return [dict(name=k, **v) for k, v in vars.items()]
|
|
2144
2145
|
|
|
2145
2146
|
|
|
2146
|
-
def get_var_names_and_types(t, node_id=None):
|
|
2147
|
+
def get_var_names_and_types(t: Template, node_id: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
2147
2148
|
"""
|
|
2148
2149
|
>>> get_var_names_and_types(Template("SELECT * FROM filter_value WHERE description = {{Float32(with_value, 0.0)}}"))
|
|
2149
2150
|
[{'name': 'with_value', 'type': 'Float32', 'default': 0.0}]
|
tinybird/sql_toolset.py
CHANGED
|
@@ -75,19 +75,6 @@ def explain_plan(sql: str) -> str:
|
|
|
75
75
|
return chquery.explain_ast(sql)
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
@dataclass(frozen=True)
|
|
79
|
-
class ColumnInfo:
|
|
80
|
-
name: str
|
|
81
|
-
type: str
|
|
82
|
-
nullable: bool
|
|
83
|
-
default_specifier: str = ""
|
|
84
|
-
default_expression: str | None = None
|
|
85
|
-
codec: str | None = None
|
|
86
|
-
comment: str | None = None
|
|
87
|
-
ttl: str | None = None
|
|
88
|
-
is_primary_key: bool = False
|
|
89
|
-
|
|
90
|
-
|
|
91
78
|
@dataclass
|
|
92
79
|
class MaterializedViewTarget:
|
|
93
80
|
database: Optional[str]
|
|
@@ -118,11 +105,6 @@ def parse_materialized_view_target(create_table_query: str) -> Optional[Material
|
|
|
118
105
|
)
|
|
119
106
|
|
|
120
107
|
|
|
121
|
-
def get_columns_from_create_query(sql_schema: str) -> list[ColumnInfo]:
|
|
122
|
-
columns = chquery.get_columns_from_create_query(sql_schema)
|
|
123
|
-
return [ColumnInfo(**col) for col in columns]
|
|
124
|
-
|
|
125
|
-
|
|
126
108
|
def has_join(sql: str) -> bool:
|
|
127
109
|
return any(line.rstrip().startswith("TableJoin") for line in explain_plan(sql).split())
|
|
128
110
|
|
tinybird/tb_cli_modules/auth.py
CHANGED
|
@@ -234,7 +234,7 @@ async def auth_use(region_name_or_host_or_id: str) -> None:
|
|
|
234
234
|
config.set_host(host)
|
|
235
235
|
|
|
236
236
|
if not await try_authenticate(config, regions):
|
|
237
|
-
msg = FeedbackManager.error_wrong_config_file(config_file=config._path)
|
|
237
|
+
msg = FeedbackManager.error_wrong_config_file(config_file=config._path, cli="tb")
|
|
238
238
|
raise CLIAuthException(msg)
|
|
239
239
|
|
|
240
240
|
config.persist_to_file()
|
|
@@ -79,7 +79,7 @@ async def print_releases(config: CLIConfig):
|
|
|
79
79
|
)
|
|
80
80
|
@coro
|
|
81
81
|
async def release_generate(semver: str) -> None:
|
|
82
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
82
|
+
click.echo(FeedbackManager.warning_deprecated_releases(cli="tb"))
|
|
83
83
|
if os.path.exists(".tinyenv"):
|
|
84
84
|
async with aiofiles.open(".tinyenv", "r") as env_file:
|
|
85
85
|
lines = await env_file.readlines()
|
|
@@ -147,7 +147,7 @@ set -euxo pipefail
|
|
|
147
147
|
)
|
|
148
148
|
@coro
|
|
149
149
|
async def release_create(semver: str, commit: Optional[str]) -> None:
|
|
150
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
150
|
+
click.echo(FeedbackManager.warning_deprecated_releases(cli="tb"))
|
|
151
151
|
config = CLIConfig.get_project_config()
|
|
152
152
|
_ = await try_update_config_with_remote(config, only_if_needed=True)
|
|
153
153
|
|
|
@@ -165,7 +165,7 @@ async def release_promote(semver: str) -> None:
|
|
|
165
165
|
"""
|
|
166
166
|
The oldest rollback Release will be automatically removed if no usage, otherwise export TB_FORCE_REMOVE_OLDEST_ROLLBACK="1" to force deletion
|
|
167
167
|
"""
|
|
168
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
168
|
+
click.echo(FeedbackManager.warning_deprecated_releases(cli="tb"))
|
|
169
169
|
config = CLIConfig.get_project_config()
|
|
170
170
|
_ = await try_update_config_with_remote(config, only_if_needed=True)
|
|
171
171
|
|
|
@@ -191,7 +191,7 @@ async def release_promote(semver: str) -> None:
|
|
|
191
191
|
)
|
|
192
192
|
@coro
|
|
193
193
|
async def release_preview(semver: str) -> None:
|
|
194
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
194
|
+
click.echo(FeedbackManager.warning_deprecated_releases(cli="tb"))
|
|
195
195
|
config = CLIConfig.get_project_config()
|
|
196
196
|
_ = await try_update_config_with_remote(config, only_if_needed=True)
|
|
197
197
|
|
|
@@ -208,7 +208,7 @@ async def release_preview(semver: str) -> None:
|
|
|
208
208
|
@click.option("--yes", is_flag=True, default=False, help="Do not ask for confirmation")
|
|
209
209
|
@coro
|
|
210
210
|
async def release_rollback(yes: bool) -> None:
|
|
211
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
211
|
+
click.echo(FeedbackManager.warning_deprecated_releases(cli="tb"))
|
|
212
212
|
config = CLIConfig.get_project_config()
|
|
213
213
|
_ = await try_update_config_with_remote(config, only_if_needed=False)
|
|
214
214
|
|
|
@@ -252,7 +252,7 @@ async def release_rollback(yes: bool) -> None:
|
|
|
252
252
|
)
|
|
253
253
|
@coro
|
|
254
254
|
async def release_rm(semver: str, oldest_rollback: bool, force: bool, yes: bool, dry_run: bool) -> None:
|
|
255
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
255
|
+
click.echo(FeedbackManager.warning_deprecated_releases(cli="tb"))
|
|
256
256
|
if (not semver and not oldest_rollback) or (semver and oldest_rollback):
|
|
257
257
|
raise CLIException(FeedbackManager.error_release_rm_param())
|
|
258
258
|
|
|
@@ -278,7 +278,6 @@ async def release_rm(semver: str, oldest_rollback: bool, force: bool, yes: bool,
|
|
|
278
278
|
@cli.group()
|
|
279
279
|
def branch() -> None:
|
|
280
280
|
"""Branch commands. Branches are an experimental feature only available in beta. Running branch commands without activation will return an error"""
|
|
281
|
-
pass
|
|
282
281
|
|
|
283
282
|
|
|
284
283
|
@branch.command(name="ls")
|
|
@@ -427,7 +426,7 @@ async def delete_branch(branch_name_or_id: str, yes: bool) -> None:
|
|
|
427
426
|
raise CLIBranchException(FeedbackManager.error_exception(error=str(e)))
|
|
428
427
|
|
|
429
428
|
if not workspace_to_delete:
|
|
430
|
-
raise CLIBranchException(FeedbackManager.error_branch(branch=branch_name_or_id))
|
|
429
|
+
raise CLIBranchException(FeedbackManager.error_branch(branch=branch_name_or_id, cli="tb"))
|
|
431
430
|
|
|
432
431
|
if yes or click.confirm(FeedbackManager.warning_confirm_delete_branch(branch=workspace_to_delete["name"])):
|
|
433
432
|
need_to_switch_to_main = workspace_to_delete.get("main") and config["id"] == workspace_to_delete["id"]
|
|
@@ -450,7 +449,7 @@ async def delete_branch(branch_name_or_id: str, yes: bool) -> None:
|
|
|
450
449
|
if workspace_main:
|
|
451
450
|
await switch_to_workspace_by_user_workspace_data(config, workspace_main)
|
|
452
451
|
else:
|
|
453
|
-
raise CLIException(FeedbackManager.error_switching_to_main())
|
|
452
|
+
raise CLIException(FeedbackManager.error_switching_to_main(cli="tb"))
|
|
454
453
|
|
|
455
454
|
|
|
456
455
|
@branch.command(
|
tinybird/tb_cli_modules/cli.py
CHANGED
|
@@ -127,7 +127,7 @@ async def cli(
|
|
|
127
127
|
click.echo(FeedbackManager.warning_development_cli())
|
|
128
128
|
|
|
129
129
|
if "x.y.z" not in CURRENT_VERSION and latest_version != CURRENT_VERSION:
|
|
130
|
-
click.echo(FeedbackManager.warning_update_version(latest_version=latest_version))
|
|
130
|
+
click.echo(FeedbackManager.warning_update_version(latest_version=latest_version, cli="tb"))
|
|
131
131
|
click.echo(FeedbackManager.warning_current_version(current_version=CURRENT_VERSION))
|
|
132
132
|
|
|
133
133
|
if debug:
|
|
@@ -237,7 +237,7 @@ async def init(
|
|
|
237
237
|
)
|
|
238
238
|
|
|
239
239
|
if current_ws.get("is_branch"):
|
|
240
|
-
raise CLIException(FeedbackManager.error_not_allowed_in_branch())
|
|
240
|
+
raise CLIException(FeedbackManager.error_not_allowed_in_branch(cli="tb"))
|
|
241
241
|
|
|
242
242
|
await folder_init(client, folder, generate_datasources, generate_releases=True, force=force)
|
|
243
243
|
|
|
@@ -255,7 +255,7 @@ async def init(
|
|
|
255
255
|
|
|
256
256
|
if sync_git:
|
|
257
257
|
if not cli_git_release.is_main_branch() and not override_commit:
|
|
258
|
-
raise CLIGitReleaseException(FeedbackManager.error_no_git_main_branch())
|
|
258
|
+
raise CLIGitReleaseException(FeedbackManager.error_no_git_main_branch(cli="tb"))
|
|
259
259
|
|
|
260
260
|
if not cli_git_release.is_dottinyb_ignored():
|
|
261
261
|
raise CLIGitReleaseException(
|
|
@@ -316,7 +316,7 @@ async def init(
|
|
|
316
316
|
|
|
317
317
|
else:
|
|
318
318
|
click.echo(FeedbackManager.info_no_git_release_yet(workspace=current_ws["name"]))
|
|
319
|
-
click.echo(FeedbackManager.info_diff_resources_for_git_init())
|
|
319
|
+
click.echo(FeedbackManager.info_diff_resources_for_git_init(cli="tb"))
|
|
320
320
|
changed = await diff_command(
|
|
321
321
|
[], True, client, with_print=False, verbose=False, clean_up=True, progress_bar=True
|
|
322
322
|
)
|
|
@@ -342,7 +342,7 @@ async def init(
|
|
|
342
342
|
if cli_git_release.is_dirty_to_init():
|
|
343
343
|
raise CLIGitReleaseException(
|
|
344
344
|
FeedbackManager.error_commit_changes_to_init_release(
|
|
345
|
-
path=cli_git_release.path, git_output=cli_git_release.status()
|
|
345
|
+
path=cli_git_release.path, git_output=cli_git_release.status(), cli="tb"
|
|
346
346
|
)
|
|
347
347
|
)
|
|
348
348
|
try:
|
|
@@ -732,19 +732,19 @@ async def diff(
|
|
|
732
732
|
for workspace in response["workspaces"]:
|
|
733
733
|
if config["id"] == workspace["id"]:
|
|
734
734
|
if not workspace.get("is_branch"):
|
|
735
|
-
raise CLIException(FeedbackManager.error_not_a_branch())
|
|
735
|
+
raise CLIException(FeedbackManager.error_not_a_branch(cli="tb"))
|
|
736
736
|
|
|
737
737
|
origin = workspace["main"]
|
|
738
738
|
workspace = await get_current_main_workspace(config)
|
|
739
739
|
|
|
740
740
|
if not workspace:
|
|
741
|
-
raise CLIException(FeedbackManager.error_workspace(workspace=origin))
|
|
741
|
+
raise CLIException(FeedbackManager.error_workspace(workspace=origin, cli="tb"))
|
|
742
742
|
|
|
743
743
|
ws_client = _get_tb_client(workspace["token"], config["host"])
|
|
744
744
|
break
|
|
745
745
|
|
|
746
746
|
if not ws_client:
|
|
747
|
-
raise CLIException(FeedbackManager.error_workspace(workspace=origin))
|
|
747
|
+
raise CLIException(FeedbackManager.error_workspace(workspace=origin, cli="tb"))
|
|
748
748
|
changed = await diff_command(
|
|
749
749
|
list(filename) if filename else None, fmt, ws_client, no_color, with_print=not only_resources_changed
|
|
750
750
|
)
|
|
@@ -1347,7 +1347,7 @@ async def deploy(
|
|
|
1347
1347
|
current_semver = release.get("semver")
|
|
1348
1348
|
|
|
1349
1349
|
if not current_semver:
|
|
1350
|
-
click.echo(FeedbackManager.error_init_release(workspace=current_ws.get("name")))
|
|
1350
|
+
click.echo(FeedbackManager.error_init_release(workspace=current_ws.get("name"), cli="tb"))
|
|
1351
1351
|
sys.exit(1)
|
|
1352
1352
|
|
|
1353
1353
|
release_created = False
|
|
@@ -1358,7 +1358,7 @@ async def deploy(
|
|
|
1358
1358
|
if not semver:
|
|
1359
1359
|
semver = current_semver
|
|
1360
1360
|
else:
|
|
1361
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
1361
|
+
click.echo(FeedbackManager.warning_deprecated_releases(cli="tb"))
|
|
1362
1362
|
|
|
1363
1363
|
if semver and current_semver:
|
|
1364
1364
|
new_version = version.parse(semver.split("-snapshot")[0])
|
|
@@ -234,7 +234,7 @@ variable to '1' or 'true'."""
|
|
|
234
234
|
try:
|
|
235
235
|
self.main(*args, **kwargs)
|
|
236
236
|
except AuthNoTokenException:
|
|
237
|
-
error_msg = FeedbackManager.error_notoken()
|
|
237
|
+
error_msg = FeedbackManager.error_notoken(cli="tb")
|
|
238
238
|
error_event = "auth_error"
|
|
239
239
|
exit_code = 1
|
|
240
240
|
except AuthException as ex:
|
|
@@ -315,7 +315,6 @@ async def folder_init(
|
|
|
315
315
|
except FileExistsError:
|
|
316
316
|
if not force:
|
|
317
317
|
click.echo(FeedbackManager.info_path_already_exists(path=x))
|
|
318
|
-
pass
|
|
319
318
|
|
|
320
319
|
if generate_datasources:
|
|
321
320
|
for format in SUPPORTED_FORMATS:
|
|
@@ -690,7 +689,7 @@ async def create_workspace_branch(
|
|
|
690
689
|
try:
|
|
691
690
|
workspace = await get_current_workspace(config)
|
|
692
691
|
if not workspace:
|
|
693
|
-
raise CLIWorkspaceException(FeedbackManager.error_workspace())
|
|
692
|
+
raise CLIWorkspaceException(FeedbackManager.error_workspace(cli="tb"))
|
|
694
693
|
|
|
695
694
|
if not branch_name:
|
|
696
695
|
click.echo(FeedbackManager.info_workspace_branch_create_greeting())
|
|
@@ -1195,7 +1194,7 @@ def validate_string_connector_param(param, s):
|
|
|
1195
1194
|
|
|
1196
1195
|
async def validate_connection_name(client, connection_name, service):
|
|
1197
1196
|
if await client.get_connector(connection_name, service) is not None:
|
|
1198
|
-
raise CLIConnectionException(FeedbackManager.error_connection_already_exists(name=connection_name))
|
|
1197
|
+
raise CLIConnectionException(FeedbackManager.error_connection_already_exists(name=connection_name, cli="tb"))
|
|
1199
1198
|
|
|
1200
1199
|
|
|
1201
1200
|
def _get_setting_value(connection, setting, sensitive_settings):
|
|
@@ -1223,9 +1222,9 @@ async def switch_workspace(config: CLIConfig, workspace_name_or_id: str, only_en
|
|
|
1223
1222
|
|
|
1224
1223
|
if not workspace:
|
|
1225
1224
|
if only_environments:
|
|
1226
|
-
raise CLIException(FeedbackManager.error_branch(branch=workspace_name_or_id))
|
|
1225
|
+
raise CLIException(FeedbackManager.error_branch(branch=workspace_name_or_id, cli="tb"))
|
|
1227
1226
|
else:
|
|
1228
|
-
raise CLIException(FeedbackManager.error_workspace(workspace=workspace_name_or_id))
|
|
1227
|
+
raise CLIException(FeedbackManager.error_workspace(workspace=workspace_name_or_id, cli="tb"))
|
|
1229
1228
|
|
|
1230
1229
|
config.set_token(workspace["token"])
|
|
1231
1230
|
config.set_token_for_host(workspace["token"], config.get_host())
|
|
@@ -1391,17 +1390,17 @@ async def get_host_from_region(
|
|
|
1391
1390
|
try:
|
|
1392
1391
|
host = regions[index - 1]["api_host"]
|
|
1393
1392
|
except Exception:
|
|
1394
|
-
raise CLIException(FeedbackManager.error_getting_region_by_index())
|
|
1393
|
+
raise CLIException(FeedbackManager.error_getting_region_by_index(cli="tb"))
|
|
1395
1394
|
except ValueError:
|
|
1396
1395
|
region_name = region_name_or_host_or_id.lower()
|
|
1397
1396
|
try:
|
|
1398
1397
|
region = get_region_from_host(region_name, regions)
|
|
1399
1398
|
host = region["api_host"] if region else None
|
|
1400
1399
|
except Exception:
|
|
1401
|
-
raise CLIException(FeedbackManager.error_getting_region_by_name_or_url())
|
|
1400
|
+
raise CLIException(FeedbackManager.error_getting_region_by_name_or_url(cli="tb"))
|
|
1402
1401
|
|
|
1403
1402
|
if not host:
|
|
1404
|
-
raise CLIException(FeedbackManager.error_getting_region_by_name_or_url())
|
|
1403
|
+
raise CLIException(FeedbackManager.error_getting_region_by_name_or_url(cli="tb"))
|
|
1405
1404
|
|
|
1406
1405
|
return regions, host
|
|
1407
1406
|
|
|
@@ -1562,7 +1561,7 @@ async def try_authenticate(
|
|
|
1562
1561
|
break
|
|
1563
1562
|
|
|
1564
1563
|
if not authenticated:
|
|
1565
|
-
raise CLIAuthException(FeedbackManager.error_invalid_token())
|
|
1564
|
+
raise CLIAuthException(FeedbackManager.error_invalid_token(cli="tb"))
|
|
1566
1565
|
|
|
1567
1566
|
config.persist_to_file()
|
|
1568
1567
|
|
|
@@ -1899,14 +1898,14 @@ async def validate_aws_iamrole_connection_name(
|
|
|
1899
1898
|
) -> str:
|
|
1900
1899
|
if connection_name and no_validate is False:
|
|
1901
1900
|
if await client.get_connector(connection_name) is not None:
|
|
1902
|
-
raise CLIConnectionException(FeedbackManager.info_connection_already_exists(name=connection_name))
|
|
1901
|
+
raise CLIConnectionException(FeedbackManager.info_connection_already_exists(name=connection_name, cli="tb"))
|
|
1903
1902
|
else:
|
|
1904
1903
|
while not connection_name:
|
|
1905
1904
|
connection_name = click.prompt("Enter the name for this connection", default=None, show_default=False)
|
|
1906
1905
|
assert isinstance(connection_name, str)
|
|
1907
1906
|
|
|
1908
1907
|
if no_validate is False and await client.get_connector(connection_name) is not None:
|
|
1909
|
-
click.echo(FeedbackManager.info_connection_already_exists(name=connection_name))
|
|
1908
|
+
click.echo(FeedbackManager.info_connection_already_exists(name=connection_name, cli="tb"))
|
|
1910
1909
|
connection_name = None
|
|
1911
1910
|
assert isinstance(connection_name, str)
|
|
1912
1911
|
return connection_name
|
|
@@ -556,10 +556,10 @@ async def datasource_share(ctx: Context, datasource_name: str, workspace_name_or
|
|
|
556
556
|
current_workspace = next((workspace for workspace in workspaces if workspace["id"] == config["id"]), None)
|
|
557
557
|
|
|
558
558
|
if not destination_workspace:
|
|
559
|
-
raise CLIDatasourceException(FeedbackManager.error_workspace(workspace=workspace_name_or_id))
|
|
559
|
+
raise CLIDatasourceException(FeedbackManager.error_workspace(workspace=workspace_name_or_id, cli="tb"))
|
|
560
560
|
|
|
561
561
|
if not current_workspace:
|
|
562
|
-
raise CLIDatasourceException(FeedbackManager.error_not_authenticated())
|
|
562
|
+
raise CLIDatasourceException(FeedbackManager.error_not_authenticated(cli="tb"))
|
|
563
563
|
|
|
564
564
|
if not user_token:
|
|
565
565
|
user_token = ask_for_user_token("share a Data Source", ui_host)
|
|
@@ -626,10 +626,10 @@ async def datasource_unshare(ctx: Context, datasource_name: str, workspace_name_
|
|
|
626
626
|
current_workspace = next((workspace for workspace in workspaces if workspace["id"] == config["id"]), None)
|
|
627
627
|
|
|
628
628
|
if not destination_workspace:
|
|
629
|
-
raise CLIDatasourceException(FeedbackManager.error_workspace(workspace=workspace_name_or_id))
|
|
629
|
+
raise CLIDatasourceException(FeedbackManager.error_workspace(workspace=workspace_name_or_id, cli="tb"))
|
|
630
630
|
|
|
631
631
|
if not current_workspace:
|
|
632
|
-
raise CLIDatasourceException(FeedbackManager.error_not_authenticated())
|
|
632
|
+
raise CLIDatasourceException(FeedbackManager.error_not_authenticated(cli="tb"))
|
|
633
633
|
|
|
634
634
|
if not user_token:
|
|
635
635
|
user_token = ask_for_user_token("unshare a Data Source", ui_host)
|
|
@@ -114,7 +114,7 @@ async def clear_workspace(ctx: Context, yes: bool, dry_run: bool) -> None:
|
|
|
114
114
|
for workspace in response["workspaces"]:
|
|
115
115
|
if config["id"] == workspace["id"]:
|
|
116
116
|
if workspace.get("is_branch"):
|
|
117
|
-
raise CLIWorkspaceException(FeedbackManager.error_not_allowed_in_branch())
|
|
117
|
+
raise CLIWorkspaceException(FeedbackManager.error_not_allowed_in_branch(cli="tb"))
|
|
118
118
|
return
|
|
119
119
|
else:
|
|
120
120
|
click.echo(FeedbackManager.info_current_workspace())
|
|
@@ -297,7 +297,7 @@ async def delete_workspace(
|
|
|
297
297
|
)
|
|
298
298
|
|
|
299
299
|
if not workspace_to_delete:
|
|
300
|
-
raise CLIWorkspaceException(FeedbackManager.error_workspace(workspace=workspace_name_or_id))
|
|
300
|
+
raise CLIWorkspaceException(FeedbackManager.error_workspace(workspace=workspace_name_or_id, cli="tb"))
|
|
301
301
|
|
|
302
302
|
if yes or click.confirm(
|
|
303
303
|
FeedbackManager.warning_confirm_delete_workspace(workspace_name=workspace_to_delete.get("name"))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird_cli
|
|
3
|
-
Version: 6.4.
|
|
3
|
+
Version: 6.4.2.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli
|
|
6
6
|
Author: Tinybird
|
|
@@ -12,7 +12,7 @@ Requires-Dist: clickhouse-toolset==0.34.dev0
|
|
|
12
12
|
Requires-Dist: click<8.2,>=8.1.8
|
|
13
13
|
Requires-Dist: colorama==0.4.6
|
|
14
14
|
Requires-Dist: cryptography~=41.0.0
|
|
15
|
-
Requires-Dist: croniter==
|
|
15
|
+
Requires-Dist: croniter==6.2.2
|
|
16
16
|
Requires-Dist: GitPython~=3.1.32
|
|
17
17
|
Requires-Dist: humanfriendly~=8.2
|
|
18
18
|
Requires-Dist: pydantic~=2.8.0
|
|
@@ -43,6 +43,12 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
43
43
|
Changelog
|
|
44
44
|
----------
|
|
45
45
|
|
|
46
|
+
6.4.1
|
|
47
|
+
***********
|
|
48
|
+
|
|
49
|
+
- `Improved` feedback messages when suggesting other cli commands.
|
|
50
|
+
- `Fixed` `tb push` rejecting the `%` operator in column DEFAULT/MATERIALIZED expressions, causing failures after `tb pull` on schemas using modulo arithmetic.
|
|
51
|
+
|
|
46
52
|
6.4.0
|
|
47
53
|
***********
|
|
48
54
|
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
tinybird/__cli__.py,sha256=
|
|
1
|
+
tinybird/__cli__.py,sha256=MTnPp_CJDk5yO8LKw-WUauu2RR-e5GX1XFuvzYUrOKI,236
|
|
2
2
|
tinybird/check_pypi.py,sha256=_4NkharLyR_ELrAdit-ftqIWvOf7jZNPt3i76frlo9g,975
|
|
3
3
|
tinybird/client.py,sha256=xzogEol-GJTpDCm5MQ_9Tj_GBiBuOZfIw_O3OQTUOvY,50615
|
|
4
|
-
tinybird/config.py,sha256=
|
|
4
|
+
tinybird/config.py,sha256=g74rE9jbVcyFj1bms5T3VEITLr21_WFy79Uj5ovvj90,7413
|
|
5
5
|
tinybird/context.py,sha256=o4yvlXPkMLmdh-XJl3wpmqPAMeRRz5ScKzKlHHKn_I8,1201
|
|
6
|
-
tinybird/datafile_common.py,sha256=
|
|
6
|
+
tinybird/datafile_common.py,sha256=BNoZqWVr7Nvn6GKb1mEvtqQieOquWW9eGBN3YhCTfFM,233244
|
|
7
7
|
tinybird/datatypes.py,sha256=Ud_IphoDOMtTMzEsYIf2lO467EVWw_ctbsOnrEzDHvU,11359
|
|
8
8
|
tinybird/feedback_manager.py,sha256=OehfKVruCHwUNN1bHIbDICvOaIovc3hb6RjGHTyIkBc,67667
|
|
9
|
-
tinybird/git_settings.py,sha256=
|
|
10
|
-
tinybird/sql.py,sha256=
|
|
11
|
-
tinybird/sql_template.py,sha256=
|
|
9
|
+
tinybird/git_settings.py,sha256=mqWgeboOlOFsSo97qyv595UCR2R1QCAqT4GTawBNPBg,3935
|
|
10
|
+
tinybird/sql.py,sha256=8pvjlKwdJ-PuJkCo57W8e1gj5z0RzUP7vOnum6Pi134,48901
|
|
11
|
+
tinybird/sql_template.py,sha256=65wtfKygqkYjU57MOlOTtbUk3EKc-Px7GeEfk65s0WM,128636
|
|
12
12
|
tinybird/sql_template_fmt.py,sha256=Ma4qcs-2r8ZXQC4GUmrCqYz34DsnGF8k5lE2Jwnr314,10638
|
|
13
|
-
tinybird/sql_toolset.py,sha256=
|
|
13
|
+
tinybird/sql_toolset.py,sha256=FhSBvHUlr5NoSdZO86v1EDPRNf4V_MWP3wX6v3kmqTA,27222
|
|
14
14
|
tinybird/syncasync.py,sha256=rIPmCvygWSFqfnlVqhZH4N9gVVTvD6DEPsfoxGizYrI,27776
|
|
15
15
|
tinybird/tb_cli.py,sha256=q1LGAsBVVMJsjR2HK62Pu6vpVtLzNmH8wHrEVUUdVkU,744
|
|
16
16
|
tinybird/tornado_template.py,sha256=1_0nYFk_xJh_TMHh6AKkJILvnNY6xYmaM-uJ3Ofv7e8,42085
|
|
17
17
|
tinybird/ch_utils/constants.py,sha256=yTNizMzgYNBzUc2EV3moBfdrDIggOe9hiuAgWF7sv2c,4333
|
|
18
18
|
tinybird/ch_utils/engine.py,sha256=NzYUnmXsrJQimwXfCqdtIMyuS_Ad0OSdEnqNXzzStvY,37489
|
|
19
|
-
tinybird/tb_cli_modules/auth.py,sha256=
|
|
20
|
-
tinybird/tb_cli_modules/branch.py,sha256
|
|
19
|
+
tinybird/tb_cli_modules/auth.py,sha256=3xu8STgouOgLkqlBf9LWFg9Oto_NyuDKsUWF95-zGwI,8741
|
|
20
|
+
tinybird/tb_cli_modules/branch.py,sha256=-2OB-zNc4_bQfaPQWsbD-lR1CSKsdxAe2qKXBYHsFWo,39382
|
|
21
21
|
tinybird/tb_cli_modules/cicd.py,sha256=i2Mw8AbmEVNBcEPYdio7liy3PGqh1ezVFZ0OmJ9ww5o,13809
|
|
22
|
-
tinybird/tb_cli_modules/cli.py,sha256=
|
|
23
|
-
tinybird/tb_cli_modules/common.py,sha256=
|
|
22
|
+
tinybird/tb_cli_modules/cli.py,sha256=2l-J4NblKBRF4XxCA6HqShk3nwhLGsncdG7itLmvOto,60283
|
|
23
|
+
tinybird/tb_cli_modules/common.py,sha256=9jAFQXOEiS5oomC5Im4ALcqgRld7A6mnOWDfoWI4OKc,77242
|
|
24
24
|
tinybird/tb_cli_modules/config.py,sha256=0kFDmsDcjKon32rgFGMHHKSbv4j5dOrXtVOlyuAyEkk,11510
|
|
25
25
|
tinybird/tb_cli_modules/connection.py,sha256=yoYUQo-Fl36LTHeGI3HpFOCLiP0wKhWsoP9P9G26NZ8,21305
|
|
26
|
-
tinybird/tb_cli_modules/datasource.py,sha256=
|
|
26
|
+
tinybird/tb_cli_modules/datasource.py,sha256=b12ClLFISGHqK7zrLZBX5OT-8Nxd2oW734-Xon0dTE8,32541
|
|
27
27
|
tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
|
|
28
28
|
tinybird/tb_cli_modules/fmt.py,sha256=edQap4tAqWMWogSIx5zriT75naLi73XTB3NwatmcrFw,3518
|
|
29
29
|
tinybird/tb_cli_modules/job.py,sha256=AG69LPb9MbobA1awwJFZJvxqarDKfRlsBjw2V1zvYqc,2964
|
|
@@ -33,12 +33,12 @@ tinybird/tb_cli_modules/tag.py,sha256=9YHnruPnUNp1IJUe4qcSEMg9EbquIRo--Nxcsbvkvq
|
|
|
33
33
|
tinybird/tb_cli_modules/telemetry.py,sha256=W098H6jmS4kpE7hN3tadaREBTf7oMocel-lkKWN0pU8,10466
|
|
34
34
|
tinybird/tb_cli_modules/test.py,sha256=Vf8oK96V81HdKGsT79y6MUz6oz_VrYIwTbRnzzJs4rQ,4350
|
|
35
35
|
tinybird/tb_cli_modules/token.py,sha256=JXATKTlbXohP9ZDZjlz8E4VYG6zrknKZhuz_wh1zBBc,13793
|
|
36
|
-
tinybird/tb_cli_modules/workspace.py,sha256=
|
|
36
|
+
tinybird/tb_cli_modules/workspace.py,sha256=JljGmM2LFJIHx_lL-xXCx8TNqhWD0yFS4kKUDh0RiaY,12473
|
|
37
37
|
tinybird/tb_cli_modules/workspace_members.py,sha256=ksXsjd233y9-sNlz4Qb-meZbX4zn1B84e_bSm2i8rhg,8731
|
|
38
38
|
tinybird/tb_cli_modules/tinyunit/tinyunit.py,sha256=50uqMgJD2BqSVONtCm55nuGRWhBNZWRc2GP1Qb8URdg,11246
|
|
39
39
|
tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py,sha256=NHoXcCHPDcKWYLzgP3NViho3Ey-6RV-ynPDzySPrTPE,1817
|
|
40
|
-
tinybird_cli-6.4.
|
|
41
|
-
tinybird_cli-6.4.
|
|
42
|
-
tinybird_cli-6.4.
|
|
43
|
-
tinybird_cli-6.4.
|
|
44
|
-
tinybird_cli-6.4.
|
|
40
|
+
tinybird_cli-6.4.2.dev0.dist-info/METADATA,sha256=NdxXrmkVZwO1TtVTM4IeEOVb05DZJZ2qqegCWu6kFwE,81596
|
|
41
|
+
tinybird_cli-6.4.2.dev0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
|
42
|
+
tinybird_cli-6.4.2.dev0.dist-info/entry_points.txt,sha256=PKPKuPmA4IfJYnCFHHUiw-aAWZuBomFvwCklv1OyCjE,43
|
|
43
|
+
tinybird_cli-6.4.2.dev0.dist-info/top_level.txt,sha256=ZIQJTPCzMqnfDzM_hEGZrJqDSEcKnIK_49T86DGWpyQ,78
|
|
44
|
+
tinybird_cli-6.4.2.dev0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|