tinybird-cli 5.8.1.dev1__tar.gz → 5.8.2.dev0__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.
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/PKG-INFO +3 -2
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/__cli__.py +2 -2
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/client.py +7 -12
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/datafile.py +7 -12
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/git_settings.py +0 -13
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/auth.py +5 -5
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/branch.py +9 -9
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/cicd.py +0 -2
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/cli.py +11 -9
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/common.py +15 -294
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/datasource.py +10 -5
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/tag.py +5 -21
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/test.py +6 -2
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/workspace.py +13 -19
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/workspace_members.py +9 -5
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird_cli.egg-info/PKG-INFO +3 -2
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/setup.cfg +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/check_pypi.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/config.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/connectors.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/context.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/datatypes.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/feedback_manager.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/sql.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/sql_template.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/sql_toolset.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/syncasync.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/token.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tornado_template.py +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird_cli.egg-info/SOURCES.txt +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird_cli.egg-info/dependency_links.txt +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird_cli.egg-info/entry_points.txt +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird_cli.egg-info/requires.txt +0 -0
- {tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tinybird-cli
|
|
3
|
-
Version: 5.8.
|
|
3
|
+
Version: 5.8.2.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
@@ -17,7 +17,8 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
17
17
|
|
|
18
18
|
Changelog
|
|
19
19
|
----------
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
5.8.1
|
|
21
22
|
***********
|
|
22
23
|
|
|
23
24
|
- `Improved` error message of `tb push` when pushing .datasource files
|
|
@@ -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__ = '5.8.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '5.8.2.dev0'
|
|
8
|
+
__revision__ = 'c7a6831'
|
|
@@ -1237,12 +1237,10 @@ class TinyB(object):
|
|
|
1237
1237
|
async def check_auth_login(self) -> Dict[str, Any]:
|
|
1238
1238
|
return await self._req("/v0/auth")
|
|
1239
1239
|
|
|
1240
|
-
async def get_all_tags(self
|
|
1241
|
-
return await self._req("/v0/tags"
|
|
1240
|
+
async def get_all_tags(self) -> Dict[str, Any]:
|
|
1241
|
+
return await self._req("/v0/tags")
|
|
1242
1242
|
|
|
1243
|
-
async def create_tag_with_resource(
|
|
1244
|
-
self, name: str, resource_id: str, resource_name: str, resource_type: str, token: Optional[str] = None
|
|
1245
|
-
):
|
|
1243
|
+
async def create_tag_with_resource(self, name: str, resource_id: str, resource_name: str, resource_type: str):
|
|
1246
1244
|
return await self._req(
|
|
1247
1245
|
"/v0/tags",
|
|
1248
1246
|
method="POST",
|
|
@@ -1253,19 +1251,17 @@ class TinyB(object):
|
|
|
1253
1251
|
"resources": [{"id": resource_id, "name": resource_name, "type": resource_type}],
|
|
1254
1252
|
}
|
|
1255
1253
|
),
|
|
1256
|
-
use_token=token,
|
|
1257
1254
|
)
|
|
1258
1255
|
|
|
1259
|
-
async def create_tag(self, name: str
|
|
1256
|
+
async def create_tag(self, name: str):
|
|
1260
1257
|
return await self._req(
|
|
1261
1258
|
"/v0/tags",
|
|
1262
1259
|
method="POST",
|
|
1263
1260
|
headers={"Content-Type": "application/json"},
|
|
1264
1261
|
data=json.dumps({"name": name}),
|
|
1265
|
-
use_token=token,
|
|
1266
1262
|
)
|
|
1267
1263
|
|
|
1268
|
-
async def update_tag(self, name: str, resources: List[Dict[str, Any]]
|
|
1264
|
+
async def update_tag(self, name: str, resources: List[Dict[str, Any]]):
|
|
1269
1265
|
await self._req(
|
|
1270
1266
|
f"/v0/tags/{name}",
|
|
1271
1267
|
method="PUT",
|
|
@@ -1275,8 +1271,7 @@ class TinyB(object):
|
|
|
1275
1271
|
"resources": resources,
|
|
1276
1272
|
}
|
|
1277
1273
|
),
|
|
1278
|
-
use_token=token,
|
|
1279
1274
|
)
|
|
1280
1275
|
|
|
1281
|
-
async def delete_tag(self, name: str
|
|
1282
|
-
await self._req(f"/v0/tags/{name}", method="DELETE"
|
|
1276
|
+
async def delete_tag(self, name: str):
|
|
1277
|
+
await self._req(f"/v0/tags/{name}", method="DELETE")
|
|
@@ -568,7 +568,7 @@ class Deployment:
|
|
|
568
568
|
self,
|
|
569
569
|
filenames: List[str],
|
|
570
570
|
only_changes: bool = False,
|
|
571
|
-
config: Optional[
|
|
571
|
+
config: Optional[CLIConfig] = None,
|
|
572
572
|
use_main: bool = False,
|
|
573
573
|
check_outdated: bool = True,
|
|
574
574
|
):
|
|
@@ -2714,10 +2714,8 @@ async def update_tags(resource_id: str, resource_name: str, resource_type: str,
|
|
|
2714
2714
|
tags_to_remove = list(set(current_tags) - set(new_tags))
|
|
2715
2715
|
return tags_to_add, tags_to_remove
|
|
2716
2716
|
|
|
2717
|
-
token_from_main = await get_token_from_main_branch(tb_client)
|
|
2718
|
-
|
|
2719
2717
|
try:
|
|
2720
|
-
all_tags = await tb_client.get_all_tags(
|
|
2718
|
+
all_tags = await tb_client.get_all_tags()
|
|
2721
2719
|
except Exception as e:
|
|
2722
2720
|
raise Exception(FeedbackManager.error_getting_tags(error=str(e)))
|
|
2723
2721
|
|
|
@@ -2739,7 +2737,6 @@ async def update_tags(resource_id: str, resource_name: str, resource_type: str,
|
|
|
2739
2737
|
resource_id=resource_id,
|
|
2740
2738
|
resource_name=resource_name,
|
|
2741
2739
|
resource_type=resource_type,
|
|
2742
|
-
token=token_from_main,
|
|
2743
2740
|
)
|
|
2744
2741
|
except Exception as e:
|
|
2745
2742
|
raise Exception(FeedbackManager.error_creating_tag(error=str(e)))
|
|
@@ -2748,7 +2745,7 @@ async def update_tags(resource_id: str, resource_name: str, resource_type: str,
|
|
|
2748
2745
|
resources = tag.get("resources", [])
|
|
2749
2746
|
resources.append({"id": resource_id, "name": resource_name, "type": resource_type})
|
|
2750
2747
|
try:
|
|
2751
|
-
await tb_client.update_tag(tag.get("name", tag_name), resources
|
|
2748
|
+
await tb_client.update_tag(tag.get("name", tag_name), resources)
|
|
2752
2749
|
except Exception as e:
|
|
2753
2750
|
raise Exception(FeedbackManager.error_updating_tag(error=str(e)))
|
|
2754
2751
|
|
|
@@ -2760,7 +2757,7 @@ async def update_tags(resource_id: str, resource_name: str, resource_type: str,
|
|
|
2760
2757
|
resources = tag.get("resources", [])
|
|
2761
2758
|
resources = [resource for resource in resources if resource.get("name") != resource_name]
|
|
2762
2759
|
try:
|
|
2763
|
-
await tb_client.update_tag(tag.get("name", tag_name), resources
|
|
2760
|
+
await tb_client.update_tag(tag.get("name", tag_name), resources)
|
|
2764
2761
|
except Exception as e:
|
|
2765
2762
|
raise Exception(FeedbackManager.error_updating_tag(error=str(e)))
|
|
2766
2763
|
|
|
@@ -3501,7 +3498,6 @@ async def new_token(token: Dict[str, Any], client: TinyB, force: bool = False):
|
|
|
3501
3498
|
|
|
3502
3499
|
|
|
3503
3500
|
async def exec_file(
|
|
3504
|
-
config: Optional[Dict[str, Any]],
|
|
3505
3501
|
r: Dict[str, Any],
|
|
3506
3502
|
tb_client: TinyB,
|
|
3507
3503
|
force: bool,
|
|
@@ -4053,7 +4049,7 @@ async def build_graph(
|
|
|
4053
4049
|
async def get_changes_from_main(
|
|
4054
4050
|
only_changes: bool,
|
|
4055
4051
|
client: TinyB,
|
|
4056
|
-
config: Optional[
|
|
4052
|
+
config: Optional[CLIConfig] = None,
|
|
4057
4053
|
current_ws: Optional[Dict[str, Any]] = None,
|
|
4058
4054
|
filenames: Optional[List[str]] = None,
|
|
4059
4055
|
):
|
|
@@ -4064,7 +4060,7 @@ async def get_changes_from_main(
|
|
|
4064
4060
|
if current_ws and not current_ws.get("is_branch"):
|
|
4065
4061
|
changed = await diff_command(filenames, True, client, no_color=True, with_print=False)
|
|
4066
4062
|
elif config and config.get("host"):
|
|
4067
|
-
workspace = await get_current_main_workspace(
|
|
4063
|
+
workspace = await get_current_main_workspace(config)
|
|
4068
4064
|
|
|
4069
4065
|
if workspace:
|
|
4070
4066
|
ws_client = _get_tb_client(workspace["token"], config["host"])
|
|
@@ -4159,7 +4155,7 @@ async def folder_push(
|
|
|
4159
4155
|
tests_ignore_order: bool = False,
|
|
4160
4156
|
tests_validate_processed_bytes: bool = False,
|
|
4161
4157
|
tests_check_requests_from_branch: bool = False,
|
|
4162
|
-
config: Optional[
|
|
4158
|
+
config: Optional[CLIConfig] = None,
|
|
4163
4159
|
user_token: Optional[str] = None,
|
|
4164
4160
|
fork_downstream: Optional[bool] = False,
|
|
4165
4161
|
fork: Optional[bool] = False,
|
|
@@ -4324,7 +4320,6 @@ async def folder_push(
|
|
|
4324
4320
|
)
|
|
4325
4321
|
try:
|
|
4326
4322
|
await exec_file(
|
|
4327
|
-
config,
|
|
4328
4323
|
to_run[name],
|
|
4329
4324
|
tb_client,
|
|
4330
4325
|
force,
|
|
@@ -57,25 +57,12 @@ DEFAULT_BRANCH = "main"
|
|
|
57
57
|
CI_WORKFLOW_VERSION = WORKFLOW_VERSION
|
|
58
58
|
|
|
59
59
|
DEFAULT_TINYENV_FILE = """
|
|
60
|
-
# VERSION format is major.minor.patch-post where major, minor, patch and post are integer numbers
|
|
61
|
-
# bump post to deploy to the current live Release, rollback to previous post version is not available
|
|
62
|
-
# bump patch or minor to deploy a new Release and auto-promote it to live. Add TB_AUTO_PROMOTE=0 to create the Release in preview status
|
|
63
|
-
# bump major to deploy a new Release in preview status
|
|
64
60
|
VERSION=0.0.0
|
|
65
61
|
|
|
66
62
|
|
|
67
63
|
|
|
68
64
|
##########
|
|
69
65
|
# OPTIONAL env vars
|
|
70
|
-
# Deploy a new Release in preview status (default is 1)
|
|
71
|
-
# TB_AUTO_PROMOTE=0
|
|
72
|
-
|
|
73
|
-
# Check if deploy requires backfilling on preview (default is 1)
|
|
74
|
-
# TB_CHECK_BACKFILL_REQUIRED=0
|
|
75
|
-
|
|
76
|
-
# Force old Releases deletion on promote (default is 0)
|
|
77
|
-
# Setting it to 1 will remove oldest rollback Releases even when some resource is still in use
|
|
78
|
-
# TB_FORCE_REMOVE_OLDEST_ROLLBACK=0
|
|
79
66
|
|
|
80
67
|
# Don't print CLI version warning message if there's a new available version
|
|
81
68
|
# TB_VERSION_WARNING=0
|
|
@@ -16,8 +16,8 @@ from tinybird.tb_cli_modules.common import (
|
|
|
16
16
|
configure_connector,
|
|
17
17
|
coro,
|
|
18
18
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
get_host_from_region,
|
|
20
|
+
get_regions,
|
|
21
21
|
try_authenticate,
|
|
22
22
|
try_update_config_with_remote,
|
|
23
23
|
)
|
|
@@ -80,7 +80,7 @@ async def auth(ctx: click.Context, token: str, host: str, region: str, connector
|
|
|
80
80
|
try_all_regions = True
|
|
81
81
|
|
|
82
82
|
if region:
|
|
83
|
-
regions, host = await
|
|
83
|
+
regions, host = await get_host_from_region(config, region, config.get_host())
|
|
84
84
|
config.set_host(host)
|
|
85
85
|
if token:
|
|
86
86
|
config.set_token_for_host(token, host)
|
|
@@ -194,7 +194,7 @@ async def auth_ls() -> None:
|
|
|
194
194
|
_ = await try_update_config_with_remote(config, raise_on_errors=False)
|
|
195
195
|
|
|
196
196
|
table: List[List[Any]] = []
|
|
197
|
-
regions: List[Region] = await
|
|
197
|
+
regions: List[Region] = await get_regions(config)
|
|
198
198
|
if regions:
|
|
199
199
|
|
|
200
200
|
def is_current(region: Region) -> bool:
|
|
@@ -237,7 +237,7 @@ async def auth_use(region_name_or_host_or_id: str) -> None:
|
|
|
237
237
|
config = CLIConfig.get_project_config()
|
|
238
238
|
_ = await try_update_config_with_remote(config, raise_on_errors=False)
|
|
239
239
|
|
|
240
|
-
regions, host = await
|
|
240
|
+
regions, host = await get_host_from_region(config, region_name_or_host_or_id, config.get_host())
|
|
241
241
|
config.set_host(host)
|
|
242
242
|
|
|
243
243
|
if not await try_authenticate(config, regions):
|
|
@@ -19,9 +19,9 @@ from tinybird.tb_cli_modules.common import (
|
|
|
19
19
|
coro,
|
|
20
20
|
create_workspace_branch,
|
|
21
21
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
22
|
-
|
|
22
|
+
get_current_main_workspace,
|
|
23
|
+
get_current_workspace,
|
|
23
24
|
get_current_workspace_branches,
|
|
24
|
-
get_current_workspace_temp,
|
|
25
25
|
get_oldest_rollback,
|
|
26
26
|
getenv_bool,
|
|
27
27
|
print_branch_regression_tests_summary,
|
|
@@ -283,7 +283,7 @@ async def branch_ls(sort: bool) -> None:
|
|
|
283
283
|
|
|
284
284
|
client = config.get_client()
|
|
285
285
|
|
|
286
|
-
current_main_workspace = await
|
|
286
|
+
current_main_workspace = await get_current_main_workspace(config)
|
|
287
287
|
assert isinstance(current_main_workspace, dict)
|
|
288
288
|
|
|
289
289
|
if current_main_workspace["id"] != config["id"]:
|
|
@@ -323,7 +323,7 @@ async def branch_use(branch_name_or_id: str) -> None:
|
|
|
323
323
|
_ = await try_update_config_with_remote(config, only_if_needed=True)
|
|
324
324
|
|
|
325
325
|
if branch_name_or_id == MAIN_BRANCH:
|
|
326
|
-
current_main_workspace = await
|
|
326
|
+
current_main_workspace = await get_current_main_workspace(config)
|
|
327
327
|
assert isinstance(current_main_workspace, dict)
|
|
328
328
|
await switch_to_workspace_by_user_workspace_data(config, current_main_workspace)
|
|
329
329
|
else:
|
|
@@ -473,7 +473,7 @@ async def data_branch(last_partition: bool, all: bool, ignore_datasources: List[
|
|
|
473
473
|
config = CLIConfig.get_project_config()
|
|
474
474
|
client = config.get_client()
|
|
475
475
|
|
|
476
|
-
current_main_workspace = await
|
|
476
|
+
current_main_workspace = await get_current_main_workspace(config)
|
|
477
477
|
assert isinstance(current_main_workspace, dict)
|
|
478
478
|
|
|
479
479
|
if current_main_workspace["id"] == config["id"]:
|
|
@@ -563,7 +563,7 @@ async def regression_tests(
|
|
|
563
563
|
config = CLIConfig.get_project_config()
|
|
564
564
|
client = config.get_client()
|
|
565
565
|
|
|
566
|
-
current_main_workspace = await
|
|
566
|
+
current_main_workspace = await get_current_main_workspace(config)
|
|
567
567
|
assert isinstance(current_main_workspace, dict)
|
|
568
568
|
|
|
569
569
|
if current_main_workspace["id"] == config["id"]:
|
|
@@ -611,7 +611,7 @@ async def _run_regression(
|
|
|
611
611
|
config = CLIConfig.get_project_config()
|
|
612
612
|
client = config.get_client()
|
|
613
613
|
|
|
614
|
-
current_main_workspace = await
|
|
614
|
+
current_main_workspace = await get_current_main_workspace(config)
|
|
615
615
|
assert isinstance(current_main_workspace, dict)
|
|
616
616
|
|
|
617
617
|
if current_main_workspace["id"] == config["id"]:
|
|
@@ -985,7 +985,7 @@ async def datasource_copy_from_main(datasource_name: str, sql: str, sql_from_mai
|
|
|
985
985
|
|
|
986
986
|
config = CLIConfig.get_project_config()
|
|
987
987
|
|
|
988
|
-
current_main_workspace = await
|
|
988
|
+
current_main_workspace = await get_current_main_workspace(config)
|
|
989
989
|
assert isinstance(current_main_workspace, dict)
|
|
990
990
|
|
|
991
991
|
if current_main_workspace["id"] == config["id"] and sql_from_main:
|
|
@@ -1014,7 +1014,7 @@ async def warn_if_in_live(semver: str) -> None:
|
|
|
1014
1014
|
return
|
|
1015
1015
|
|
|
1016
1016
|
config = CLIConfig.get_project_config()
|
|
1017
|
-
current_workspace = await
|
|
1017
|
+
current_workspace = await get_current_workspace(config)
|
|
1018
1018
|
assert isinstance(current_workspace, dict)
|
|
1019
1019
|
|
|
1020
1020
|
is_branch = current_workspace.get("is_branch", False)
|
|
@@ -58,13 +58,13 @@ from tinybird.tb_cli_modules.common import (
|
|
|
58
58
|
create_tb_client,
|
|
59
59
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
60
60
|
folder_init,
|
|
61
|
-
get_config_and_hosts,
|
|
62
61
|
get_current_main_workspace,
|
|
63
62
|
getenv_bool,
|
|
64
63
|
is_major_semver,
|
|
65
64
|
is_post_semver,
|
|
66
65
|
load_connector_config,
|
|
67
66
|
remove_release,
|
|
67
|
+
try_update_config_with_remote,
|
|
68
68
|
)
|
|
69
69
|
from tinybird.tb_cli_modules.config import CLIConfig
|
|
70
70
|
from tinybird.tb_cli_modules.telemetry import add_telemetry_event
|
|
@@ -180,6 +180,8 @@ async def cli(
|
|
|
180
180
|
config_temp.set_host(host)
|
|
181
181
|
if semver:
|
|
182
182
|
config_temp.set_semver(semver)
|
|
183
|
+
if token or host or semver:
|
|
184
|
+
await try_update_config_with_remote(config_temp, auto_persist=False, raise_on_errors=False)
|
|
183
185
|
|
|
184
186
|
# Overwrite token and host with env vars manually, without resorting to click.
|
|
185
187
|
#
|
|
@@ -306,7 +308,9 @@ async def init(
|
|
|
306
308
|
) -> None:
|
|
307
309
|
"""Initialize folder layout."""
|
|
308
310
|
client: TinyB = ctx.ensure_object(dict)["client"]
|
|
309
|
-
config
|
|
311
|
+
config = CLIConfig.get_project_config()
|
|
312
|
+
if config.get("token") is None:
|
|
313
|
+
raise AuthNoTokenException
|
|
310
314
|
folder = folder if folder else getcwd()
|
|
311
315
|
|
|
312
316
|
workspaces: List[Dict[str, Any]] = (await client.user_workspaces_and_branches()).get("workspaces", [])
|
|
@@ -430,9 +434,7 @@ async def init(
|
|
|
430
434
|
else:
|
|
431
435
|
if cicd:
|
|
432
436
|
data_project_dir = os.path.relpath(folder, cli_git_release.working_dir())
|
|
433
|
-
await init_cicd(
|
|
434
|
-
client, current_ws, config, path=cli_git_release.working_dir(), data_project_dir=data_project_dir
|
|
435
|
-
)
|
|
437
|
+
await init_cicd(client, path=cli_git_release.working_dir(), data_project_dir=data_project_dir)
|
|
436
438
|
|
|
437
439
|
if final_response:
|
|
438
440
|
if error:
|
|
@@ -670,7 +672,7 @@ async def push(
|
|
|
670
672
|
tests_validate_processed_bytes=validate_processed_bytes,
|
|
671
673
|
tests_check_requests_from_branch=check_requests_from_main,
|
|
672
674
|
folder=folder,
|
|
673
|
-
config=
|
|
675
|
+
config=CLIConfig.get_project_config(),
|
|
674
676
|
user_token=user_token,
|
|
675
677
|
is_internal=is_internal,
|
|
676
678
|
)
|
|
@@ -782,7 +784,7 @@ async def diff(
|
|
|
782
784
|
list(filename) if filename else None, fmt, client, no_color, with_print=not only_resources_changed
|
|
783
785
|
)
|
|
784
786
|
else:
|
|
785
|
-
config
|
|
787
|
+
config = CLIConfig.get_project_config()
|
|
786
788
|
|
|
787
789
|
response = await client.user_workspaces_and_branches()
|
|
788
790
|
ws_client = None
|
|
@@ -792,7 +794,7 @@ async def diff(
|
|
|
792
794
|
raise CLIException(FeedbackManager.error_not_a_branch())
|
|
793
795
|
|
|
794
796
|
origin = workspace["main"]
|
|
795
|
-
workspace = await get_current_main_workspace(
|
|
797
|
+
workspace = await get_current_main_workspace(config)
|
|
796
798
|
|
|
797
799
|
if not workspace:
|
|
798
800
|
raise CLIException(FeedbackManager.error_workspace(workspace=origin))
|
|
@@ -1506,7 +1508,7 @@ async def deploy(
|
|
|
1506
1508
|
workspace_lib_paths=workspace,
|
|
1507
1509
|
run_tests=False,
|
|
1508
1510
|
folder=folder,
|
|
1509
|
-
config=
|
|
1511
|
+
config=config,
|
|
1510
1512
|
user_token=user_token,
|
|
1511
1513
|
fork_downstream=fork_downstream,
|
|
1512
1514
|
fork=fork,
|
|
@@ -19,7 +19,7 @@ from functools import wraps
|
|
|
19
19
|
from os import chmod, environ, getcwd, getenv
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, Set, Tuple, Union
|
|
22
|
-
from urllib.parse import
|
|
22
|
+
from urllib.parse import urlparse
|
|
23
23
|
|
|
24
24
|
import click
|
|
25
25
|
import click.formatting
|
|
@@ -42,7 +42,6 @@ from tinybird.client import (
|
|
|
42
42
|
)
|
|
43
43
|
from tinybird.config import (
|
|
44
44
|
DEFAULT_API_HOST,
|
|
45
|
-
DEFAULT_LOCALHOST,
|
|
46
45
|
DEFAULT_UI_HOST,
|
|
47
46
|
DEPRECATED_PROJECT_PATHS,
|
|
48
47
|
PROJECT_PATHS,
|
|
@@ -173,39 +172,12 @@ def generate_datafile(
|
|
|
173
172
|
click.echo(FeedbackManager.error_file_already_exists(file=f))
|
|
174
173
|
|
|
175
174
|
|
|
176
|
-
async def
|
|
177
|
-
"""Returns (config, host, ui_host)"""
|
|
178
|
-
|
|
179
|
-
config = ctx.ensure_object(dict)["config"]
|
|
180
|
-
|
|
181
|
-
if check_token_exists:
|
|
182
|
-
if config.get("token") is None:
|
|
183
|
-
raise AuthNoTokenException
|
|
184
|
-
|
|
185
|
-
if "id" not in config:
|
|
186
|
-
config = await _get_config(config["host"], config["token"], load_tb_file=False)
|
|
187
|
-
|
|
188
|
-
host = config["host"]
|
|
189
|
-
ui_host = DEFAULT_UI_HOST if host == DEFAULT_API_HOST else host
|
|
190
|
-
|
|
191
|
-
return config, host, ui_host
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
async def get_current_workspace_temp(config: CLIConfig) -> Optional[Dict[str, Any]]:
|
|
195
|
-
"""Pending to remove the _temp suffix once we fully integrate the class CLIConfig.
|
|
196
|
-
Please, don't work with the previous version any more and make any changes here
|
|
197
|
-
"""
|
|
198
|
-
|
|
175
|
+
async def get_current_workspace(config: CLIConfig) -> Optional[Dict[str, Any]]:
|
|
199
176
|
client = config.get_client()
|
|
200
177
|
workspaces: List[Dict[str, Any]] = (await client.user_workspaces_and_branches()).get("workspaces", [])
|
|
201
178
|
return _get_current_workspace_common(workspaces, config["id"])
|
|
202
179
|
|
|
203
180
|
|
|
204
|
-
async def get_current_workspace(client: TinyB, config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
205
|
-
workspaces: List[Dict[str, Any]] = (await client.user_workspaces()).get("workspaces", [])
|
|
206
|
-
return _get_current_workspace_common(workspaces, config["id"])
|
|
207
|
-
|
|
208
|
-
|
|
209
181
|
def _get_current_workspace_common(
|
|
210
182
|
workspaces: List[Dict[str, Any]], current_workspace_id: str
|
|
211
183
|
) -> Optional[Dict[str, Any]]:
|
|
@@ -218,7 +190,7 @@ async def get_current_environment(client, config):
|
|
|
218
190
|
|
|
219
191
|
|
|
220
192
|
async def get_current_workspace_branches(config: CLIConfig) -> List[Dict[str, Any]]:
|
|
221
|
-
current_main_workspace: Optional[Dict[str, Any]] = await
|
|
193
|
+
current_main_workspace: Optional[Dict[str, Any]] = await get_current_main_workspace(config)
|
|
222
194
|
if not current_main_workspace:
|
|
223
195
|
raise CLIException(FeedbackManager.error_unable_to_identify_main_workspace())
|
|
224
196
|
|
|
@@ -553,135 +525,6 @@ async def configure_connector(connector):
|
|
|
553
525
|
click.echo(FeedbackManager.success_connector_config(connector=connector, file_name=file_name))
|
|
554
526
|
|
|
555
527
|
|
|
556
|
-
async def _get_config(host: str, token: str, load_tb_file: bool = True, semver: Optional[str] = None):
|
|
557
|
-
config = {}
|
|
558
|
-
|
|
559
|
-
try:
|
|
560
|
-
client = _get_tb_client(token, host)
|
|
561
|
-
response = await client.workspace_info()
|
|
562
|
-
except Exception:
|
|
563
|
-
raise CLIAuthException(FeedbackManager.error_invalid_token_for_host(host=host))
|
|
564
|
-
|
|
565
|
-
if semver:
|
|
566
|
-
release_exists = any(release["semver"] == semver for release in response["releases"])
|
|
567
|
-
if not release_exists:
|
|
568
|
-
raise CLIAuthException(
|
|
569
|
-
FeedbackManager.error_invalid_release_for_workspace(semver=semver, workspace=response["name"])
|
|
570
|
-
)
|
|
571
|
-
|
|
572
|
-
from_response = load_tb_file
|
|
573
|
-
|
|
574
|
-
try:
|
|
575
|
-
config_file = Path(getcwd()) / ".tinyb"
|
|
576
|
-
with open(config_file) as file:
|
|
577
|
-
config = json.loads(file.read())
|
|
578
|
-
except Exception:
|
|
579
|
-
from_response = True
|
|
580
|
-
|
|
581
|
-
if not from_response:
|
|
582
|
-
return config
|
|
583
|
-
|
|
584
|
-
config.update({"host": host, "token": token, "id": response["id"], "name": response["name"]})
|
|
585
|
-
|
|
586
|
-
if "user_email" in response:
|
|
587
|
-
config["user_email"] = response["user_email"]
|
|
588
|
-
if "user_id" in response:
|
|
589
|
-
config["user_id"] = response["user_id"]
|
|
590
|
-
if "scope" in response:
|
|
591
|
-
config["scope"] = response["scope"]
|
|
592
|
-
if "id" in response:
|
|
593
|
-
config["id"] = response["id"]
|
|
594
|
-
|
|
595
|
-
tokens = config.get("tokens", {})
|
|
596
|
-
|
|
597
|
-
tokens.update({host: token})
|
|
598
|
-
config["tokens"] = tokens
|
|
599
|
-
config["token"] = tokens[host]
|
|
600
|
-
config["host"] = host
|
|
601
|
-
|
|
602
|
-
return config
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
async def get_regions(client: TinyB, config_file: Path) -> List[Dict[str, str]]:
|
|
606
|
-
regions: List[Dict[str, str]] = []
|
|
607
|
-
try:
|
|
608
|
-
response = await client.regions()
|
|
609
|
-
regions = response["regions"]
|
|
610
|
-
except Exception:
|
|
611
|
-
pass
|
|
612
|
-
|
|
613
|
-
try:
|
|
614
|
-
with open(config_file) as file:
|
|
615
|
-
config = json.loads(file.read())
|
|
616
|
-
if "tokens" not in config:
|
|
617
|
-
return regions
|
|
618
|
-
|
|
619
|
-
for key in config["tokens"]:
|
|
620
|
-
region = next(
|
|
621
|
-
(region for region in regions if key == region["api_host"] or key == region["host"]), None
|
|
622
|
-
)
|
|
623
|
-
if region:
|
|
624
|
-
region["default_password"] = config["tokens"][key]
|
|
625
|
-
else:
|
|
626
|
-
regions.append(
|
|
627
|
-
{
|
|
628
|
-
"api_host": format_host(key, subdomain="api"),
|
|
629
|
-
"host": format_host(key, subdomain="ui"),
|
|
630
|
-
"name": key,
|
|
631
|
-
"default_password": config["tokens"][key],
|
|
632
|
-
}
|
|
633
|
-
)
|
|
634
|
-
|
|
635
|
-
except Exception:
|
|
636
|
-
pass
|
|
637
|
-
|
|
638
|
-
return regions
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
def _compare_hosts(region: Dict[str, Any], config: Dict[str, Any]) -> bool:
|
|
642
|
-
return region["host"] == config["host"] or region["api_host"] == config["host"]
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
async def get_host_from_region(region_name_or_host_or_id: str, host: Optional[str] = None):
|
|
646
|
-
is_localhost = FeatureFlags.is_localhost()
|
|
647
|
-
|
|
648
|
-
if not host:
|
|
649
|
-
host = DEFAULT_API_HOST if not is_localhost else DEFAULT_LOCALHOST
|
|
650
|
-
|
|
651
|
-
client = _get_tb_client(token="", host=host)
|
|
652
|
-
|
|
653
|
-
try:
|
|
654
|
-
response = await client.regions()
|
|
655
|
-
regions = response["regions"]
|
|
656
|
-
except Exception:
|
|
657
|
-
regions = []
|
|
658
|
-
|
|
659
|
-
if not regions:
|
|
660
|
-
click.echo(f"No regions available, using host: {host}")
|
|
661
|
-
return [], host
|
|
662
|
-
|
|
663
|
-
try:
|
|
664
|
-
index = int(region_name_or_host_or_id)
|
|
665
|
-
try:
|
|
666
|
-
host = regions[index - 1]["api_host"]
|
|
667
|
-
except Exception:
|
|
668
|
-
raise CLIException(FeedbackManager.error_getting_region_by_index())
|
|
669
|
-
except Exception:
|
|
670
|
-
region_name_or_host_or_id = region_name_or_host_or_id.lower()
|
|
671
|
-
try:
|
|
672
|
-
region = next(
|
|
673
|
-
(region for region in regions if _compare_region_host(region_name_or_host_or_id, region)), None
|
|
674
|
-
)
|
|
675
|
-
host = region["api_host"] if region else None
|
|
676
|
-
except Exception:
|
|
677
|
-
raise CLIException(FeedbackManager.error_getting_region_by_name_or_url())
|
|
678
|
-
|
|
679
|
-
if not host:
|
|
680
|
-
raise CLIException(FeedbackManager.error_getting_region_by_name_or_url())
|
|
681
|
-
|
|
682
|
-
return regions, host
|
|
683
|
-
|
|
684
|
-
|
|
685
528
|
def _compare_region_host(region_name_or_host: str, region: Dict[str, Any]) -> bool:
|
|
686
529
|
if region["name"].lower() == region_name_or_host:
|
|
687
530
|
return True
|
|
@@ -771,93 +614,6 @@ def region_from_host(region_name_or_host, regions):
|
|
|
771
614
|
return next((r for r in regions if _compare_region_host(region_name_or_host, r)), None)
|
|
772
615
|
|
|
773
616
|
|
|
774
|
-
async def try_get_config(host, token):
|
|
775
|
-
try:
|
|
776
|
-
return await _get_config(host, token)
|
|
777
|
-
except Exception:
|
|
778
|
-
return None
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
async def authenticate(ctx, host, token=None, regions=None, interactive=False, try_all_regions=False):
|
|
782
|
-
is_localhost = FeatureFlags.is_localhost()
|
|
783
|
-
check_host = DEFAULT_API_HOST if not host and not is_localhost else DEFAULT_LOCALHOST
|
|
784
|
-
|
|
785
|
-
client = _get_tb_client(token="", host=check_host)
|
|
786
|
-
config_file = Path(getcwd()) / ".tinyb"
|
|
787
|
-
default_password: Optional[str] = None
|
|
788
|
-
|
|
789
|
-
if not regions and interactive:
|
|
790
|
-
regions = await get_regions(client, config_file)
|
|
791
|
-
|
|
792
|
-
selected_region = None
|
|
793
|
-
|
|
794
|
-
if regions and interactive:
|
|
795
|
-
selected_region = ask_for_region_interactively(regions)
|
|
796
|
-
if selected_region is None:
|
|
797
|
-
return None
|
|
798
|
-
|
|
799
|
-
host = selected_region["api_host"]
|
|
800
|
-
default_password = selected_region.get("default_password", None)
|
|
801
|
-
elif regions and not interactive:
|
|
802
|
-
selected_region = region_from_host(host, regions)
|
|
803
|
-
|
|
804
|
-
if host and not regions and not selected_region:
|
|
805
|
-
name, host, ui_host = (host, format_host(host, subdomain="api"), format_host(host, subdomain="ui"))
|
|
806
|
-
else:
|
|
807
|
-
name, host, ui_host = get_region_info(ctx, selected_region)
|
|
808
|
-
|
|
809
|
-
token = token or ctx.ensure_object(dict)["config"].get("token_passed")
|
|
810
|
-
|
|
811
|
-
if not token:
|
|
812
|
-
tokens_url = urljoin(ui_host, "tokens")
|
|
813
|
-
token = click.prompt(
|
|
814
|
-
f"\nCopy the \"admin your@email\" token from {tokens_url} and paste it here { f'OR press enter to use the token from .tinyb file' if default_password else ''}",
|
|
815
|
-
hide_input=True,
|
|
816
|
-
show_default=False,
|
|
817
|
-
default=default_password,
|
|
818
|
-
)
|
|
819
|
-
|
|
820
|
-
add_telemetry_event("auth_token", token=token)
|
|
821
|
-
|
|
822
|
-
config = await try_get_config(host, token)
|
|
823
|
-
if config is None and not try_all_regions:
|
|
824
|
-
raise CLIAuthException(FeedbackManager.error_invalid_token_for_host(host=host))
|
|
825
|
-
|
|
826
|
-
# No luck? Let's try auth in all other regions
|
|
827
|
-
if config is None and try_all_regions and not interactive:
|
|
828
|
-
if not regions:
|
|
829
|
-
regions = await get_regions(client, config_file)
|
|
830
|
-
|
|
831
|
-
# Check other regions, ignoring the previously tested region
|
|
832
|
-
for region in [r for r in regions if r is not selected_region]:
|
|
833
|
-
name, host, ui_host = get_region_info(ctx, region)
|
|
834
|
-
config = await try_get_config(host, token)
|
|
835
|
-
if config is not None:
|
|
836
|
-
click.echo(FeedbackManager.success_using_host(name=name, host=ui_host))
|
|
837
|
-
break
|
|
838
|
-
|
|
839
|
-
if config is None:
|
|
840
|
-
raise CLIAuthException(FeedbackManager.error_invalid_token())
|
|
841
|
-
|
|
842
|
-
try:
|
|
843
|
-
if "id" in config:
|
|
844
|
-
await write_config(config)
|
|
845
|
-
ctx.ensure_object(dict)["client"] = _get_tb_client(config["token"], config.get("host", DEFAULT_API_HOST))
|
|
846
|
-
ctx.ensure_object(dict)["config"] = config
|
|
847
|
-
else:
|
|
848
|
-
raise CLIAuthException(FeedbackManager.error_not_personal_auth())
|
|
849
|
-
except Exception as e:
|
|
850
|
-
raise CLIAuthException(FeedbackManager.error_exception(error=str(e)))
|
|
851
|
-
|
|
852
|
-
click.echo(FeedbackManager.success_auth())
|
|
853
|
-
click.echo(FeedbackManager.success_remember_api_host(api_host=host))
|
|
854
|
-
|
|
855
|
-
if "scope" not in config or not config["scope"]:
|
|
856
|
-
click.echo(FeedbackManager.warning_token_scope())
|
|
857
|
-
|
|
858
|
-
return config
|
|
859
|
-
|
|
860
|
-
|
|
861
617
|
def ask_for_user_token(action: str, ui_host: str) -> str:
|
|
862
618
|
return click.prompt(
|
|
863
619
|
f'\nUse the token called "user token" in order to {action}. Copy it from {ui_host}/tokens and paste it here',
|
|
@@ -941,8 +697,8 @@ async def ask_for_starterkit_interactively(ctx: Context) -> Optional[str]:
|
|
|
941
697
|
return starterkit[sk_index - 1]["friendly_name"]
|
|
942
698
|
|
|
943
699
|
|
|
944
|
-
async def fork_workspace(
|
|
945
|
-
config
|
|
700
|
+
async def fork_workspace(client: TinyB, user_client: TinyB, created_workspace):
|
|
701
|
+
config = CLIConfig.get_project_config()
|
|
946
702
|
|
|
947
703
|
datasources = await client.datasources()
|
|
948
704
|
for datasource in datasources:
|
|
@@ -963,7 +719,7 @@ async def create_workspace_non_interactive(
|
|
|
963
719
|
click.echo(FeedbackManager.success_workspace_created(workspace_name=workspace_name))
|
|
964
720
|
|
|
965
721
|
if fork:
|
|
966
|
-
await fork_workspace(
|
|
722
|
+
await fork_workspace(client, user_client, created_workspace)
|
|
967
723
|
|
|
968
724
|
except Exception as e:
|
|
969
725
|
raise CLIWorkspaceException(FeedbackManager.error_exception(error=str(e)))
|
|
@@ -1005,7 +761,7 @@ async def create_workspace_branch(
|
|
|
1005
761
|
_ = await try_update_config_with_remote(config)
|
|
1006
762
|
|
|
1007
763
|
try:
|
|
1008
|
-
workspace = await
|
|
764
|
+
workspace = await get_current_workspace(config)
|
|
1009
765
|
if not workspace:
|
|
1010
766
|
raise CLIWorkspaceException(FeedbackManager.error_workspace())
|
|
1011
767
|
|
|
@@ -1542,17 +1298,6 @@ def _get_setting_value(connection, setting, sensitive_settings):
|
|
|
1542
1298
|
return connection.get(setting, "")
|
|
1543
1299
|
|
|
1544
1300
|
|
|
1545
|
-
async def _get_config_or_load_tb_file(config, semver: Optional[str] = None):
|
|
1546
|
-
if "id" not in config:
|
|
1547
|
-
config = await _get_config(config["host"], config["token"], load_tb_file=False, semver=semver)
|
|
1548
|
-
else:
|
|
1549
|
-
config_file = Path(getcwd()) / ".tinyb"
|
|
1550
|
-
with open(config_file) as file:
|
|
1551
|
-
config = json.loads(file.read())
|
|
1552
|
-
config["semver"] = semver
|
|
1553
|
-
return config
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
1301
|
async def switch_workspace(config: CLIConfig, workspace_name_or_id: str, only_environments: bool = False) -> None:
|
|
1557
1302
|
try:
|
|
1558
1303
|
if only_environments:
|
|
@@ -1611,7 +1356,7 @@ async def switch_to_workspace_by_user_workspace_data(config: CLIConfig, user_wor
|
|
|
1611
1356
|
async def print_current_workspace(config: CLIConfig) -> None:
|
|
1612
1357
|
_ = await try_update_config_with_remote(config, only_if_needed=True)
|
|
1613
1358
|
|
|
1614
|
-
current_main_workspace = await
|
|
1359
|
+
current_main_workspace = await get_current_main_workspace(config)
|
|
1615
1360
|
assert isinstance(current_main_workspace, dict)
|
|
1616
1361
|
|
|
1617
1362
|
columns = ["name", "id", "role", "plan", "current"]
|
|
@@ -1643,7 +1388,7 @@ async def print_current_branch(config: CLIConfig) -> None:
|
|
|
1643
1388
|
click.echo(FeedbackManager.info_current_branch())
|
|
1644
1389
|
if workspace.get("is_branch"):
|
|
1645
1390
|
name = workspace["name"]
|
|
1646
|
-
main_workspace = await
|
|
1391
|
+
main_workspace = await get_current_main_workspace(config)
|
|
1647
1392
|
assert isinstance(main_workspace, dict)
|
|
1648
1393
|
main_name = main_workspace["name"]
|
|
1649
1394
|
else:
|
|
@@ -1714,20 +1459,16 @@ class ConnectionReplacements:
|
|
|
1714
1459
|
# ======
|
|
1715
1460
|
|
|
1716
1461
|
|
|
1717
|
-
async def
|
|
1462
|
+
async def get_host_from_region(
|
|
1718
1463
|
config: CLIConfig, region_name_or_host_or_id: str, host: Optional[str] = None
|
|
1719
1464
|
) -> Tuple[List[Region], str]:
|
|
1720
|
-
"""Pending to remove the _temp suffix once we fully integrate the class CLIConfig.
|
|
1721
|
-
Please, don't work with the previous version any more and make any changes here
|
|
1722
|
-
"""
|
|
1723
|
-
|
|
1724
1465
|
regions: List[Region]
|
|
1725
1466
|
region: Optional[Region]
|
|
1726
1467
|
|
|
1727
1468
|
host = host or config.get_host(use_defaults_if_needed=True)
|
|
1728
1469
|
|
|
1729
1470
|
try:
|
|
1730
|
-
regions = await
|
|
1471
|
+
regions = await get_regions(config)
|
|
1731
1472
|
assert isinstance(regions, list)
|
|
1732
1473
|
except Exception:
|
|
1733
1474
|
regions = []
|
|
@@ -1757,11 +1498,7 @@ async def get_host_from_region_temp(
|
|
|
1757
1498
|
return regions, host
|
|
1758
1499
|
|
|
1759
1500
|
|
|
1760
|
-
async def
|
|
1761
|
-
"""Pending to remove the _temp suffix once we fully integrate the class CLIConfig.
|
|
1762
|
-
Please, don't work with the previous version any more and make any changes here
|
|
1763
|
-
"""
|
|
1764
|
-
|
|
1501
|
+
async def get_regions(config: CLIConfig) -> List[Region]:
|
|
1765
1502
|
regions: List[Region] = []
|
|
1766
1503
|
|
|
1767
1504
|
try:
|
|
@@ -1797,10 +1534,6 @@ async def get_regions_temp(config: CLIConfig) -> List[Region]:
|
|
|
1797
1534
|
|
|
1798
1535
|
|
|
1799
1536
|
def get_region_from_host(region_name_or_host: str, regions: List[Region]) -> Optional[Region]:
|
|
1800
|
-
"""Pending to remove the _temp suffix once we fully integrate the class CLIConfig.
|
|
1801
|
-
Please, don't work with the previous version any more and make any changes here
|
|
1802
|
-
"""
|
|
1803
|
-
|
|
1804
1537
|
"""Returns the region that matches region_name_or_host by name, API host or ui host"""
|
|
1805
1538
|
for region in regions:
|
|
1806
1539
|
if region_name_or_host in (region["name"].lower(), region["host"], region["api_host"]):
|
|
@@ -1811,10 +1544,6 @@ def get_region_from_host(region_name_or_host: str, regions: List[Region]) -> Opt
|
|
|
1811
1544
|
async def try_update_config_with_remote(
|
|
1812
1545
|
config: CLIConfig, raise_on_errors: bool = True, only_if_needed: bool = False, auto_persist: bool = True
|
|
1813
1546
|
) -> bool:
|
|
1814
|
-
"""Pending to remove the _temp suffix once we fully integrate the class CLIConfig.
|
|
1815
|
-
Please, don't work with the previous version any more and make any changes here
|
|
1816
|
-
"""
|
|
1817
|
-
|
|
1818
1547
|
response: Dict[str, Any]
|
|
1819
1548
|
|
|
1820
1549
|
if not config.get_token():
|
|
@@ -1870,7 +1599,7 @@ async def try_authenticate(
|
|
|
1870
1599
|
host: Optional[str] = config.get_host()
|
|
1871
1600
|
|
|
1872
1601
|
if not regions and interactive:
|
|
1873
|
-
regions = await
|
|
1602
|
+
regions = await get_regions(config)
|
|
1874
1603
|
|
|
1875
1604
|
selected_region: Optional[Region] = None
|
|
1876
1605
|
default_password: Optional[str] = None
|
|
@@ -1909,7 +1638,7 @@ async def try_authenticate(
|
|
|
1909
1638
|
# No luck? Let's try auth in all other regions
|
|
1910
1639
|
if not authenticated and try_all_regions and not interactive:
|
|
1911
1640
|
if not regions:
|
|
1912
|
-
regions = await
|
|
1641
|
+
regions = await get_regions(config)
|
|
1913
1642
|
|
|
1914
1643
|
# Check other regions, ignoring the previously tested region
|
|
1915
1644
|
for region in [r for r in regions if r is not selected_region]:
|
|
@@ -1991,19 +1720,11 @@ async def wait_job_no_ui(
|
|
|
1991
1720
|
raise
|
|
1992
1721
|
|
|
1993
1722
|
|
|
1994
|
-
async def
|
|
1995
|
-
"""Pending to remove the _temp suffix once we fully integrate the class CLIConfig.
|
|
1996
|
-
Please, don't work with the previous version any more and make any changes here
|
|
1997
|
-
"""
|
|
1723
|
+
async def get_current_main_workspace(config: CLIConfig) -> Optional[Dict[str, Any]]:
|
|
1998
1724
|
current_workspace = await config.get_client().user_workspaces_and_branches()
|
|
1999
1725
|
return _get_current_main_workspace_common(current_workspace, config.get("id", current_workspace["id"]))
|
|
2000
1726
|
|
|
2001
1727
|
|
|
2002
|
-
async def get_current_main_workspace(client: TinyB, config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
2003
|
-
current_workspace = await client.user_workspaces_and_branches()
|
|
2004
|
-
return _get_current_main_workspace_common(current_workspace, config["id"])
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
1728
|
def _get_current_main_workspace_common(
|
|
2008
1729
|
user_workspace_and_branches: Dict[str, Any], current_workspace_id: str
|
|
2009
1730
|
) -> Optional[Dict[str, Any]]:
|
|
@@ -14,6 +14,8 @@ import humanfriendly
|
|
|
14
14
|
from click import Context
|
|
15
15
|
|
|
16
16
|
from tinybird.client import CanNotBeDeletedException, DoesNotExistException, TinyB
|
|
17
|
+
from tinybird.config import get_display_host
|
|
18
|
+
from tinybird.tb_cli_modules.config import CLIConfig
|
|
17
19
|
|
|
18
20
|
if TYPE_CHECKING:
|
|
19
21
|
from tinybird.connectors import Connector
|
|
@@ -30,7 +32,6 @@ from tinybird.tb_cli_modules.common import (
|
|
|
30
32
|
check_user_token,
|
|
31
33
|
coro,
|
|
32
34
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
33
|
-
get_config_and_hosts,
|
|
34
35
|
get_format_from_filename_or_url,
|
|
35
36
|
load_connector_config,
|
|
36
37
|
push_data,
|
|
@@ -602,9 +603,11 @@ async def datasource_connect(ctx, connection, datasource_name, topic, group, aut
|
|
|
602
603
|
async def datasource_share(ctx: Context, datasource_name: str, workspace_name_or_id: str, user_token: str, yes: bool):
|
|
603
604
|
"""Share a datasource"""
|
|
604
605
|
|
|
605
|
-
|
|
606
|
+
config = CLIConfig.get_project_config()
|
|
607
|
+
client = config.get_client()
|
|
608
|
+
host = config.get_host() or CLIConfig.DEFAULTS["host"]
|
|
609
|
+
ui_host = get_display_host(host)
|
|
606
610
|
|
|
607
|
-
config, host, ui_host = await get_config_and_hosts(ctx)
|
|
608
611
|
_datasource: Dict[str, Any] = {}
|
|
609
612
|
try:
|
|
610
613
|
_datasource = await client.get_datasource(datasource_name)
|
|
@@ -668,9 +671,11 @@ async def datasource_share(ctx: Context, datasource_name: str, workspace_name_or
|
|
|
668
671
|
async def datasource_unshare(ctx: Context, datasource_name: str, workspace_name_or_id: str, user_token: str, yes: bool):
|
|
669
672
|
"""Unshare a datasource"""
|
|
670
673
|
|
|
671
|
-
|
|
674
|
+
config = CLIConfig.get_project_config()
|
|
675
|
+
client = config.get_client()
|
|
676
|
+
host = config.get_host() or CLIConfig.DEFAULTS["host"]
|
|
677
|
+
ui_host = get_display_host(host)
|
|
672
678
|
|
|
673
|
-
config, host, ui_host = await get_config_and_hosts(ctx)
|
|
674
679
|
_datasource: Dict[str, Any] = {}
|
|
675
680
|
try:
|
|
676
681
|
_datasource = await client.get_datasource(datasource_name)
|
|
@@ -5,11 +5,7 @@ from click import Context
|
|
|
5
5
|
|
|
6
6
|
from tinybird.feedback_manager import FeedbackManager
|
|
7
7
|
from tinybird.tb_cli_modules.cli import cli
|
|
8
|
-
from tinybird.tb_cli_modules.common import
|
|
9
|
-
coro,
|
|
10
|
-
echo_safe_humanfriendly_tables_format_smart_table,
|
|
11
|
-
get_current_main_workspace,
|
|
12
|
-
)
|
|
8
|
+
from tinybird.tb_cli_modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table
|
|
13
9
|
|
|
14
10
|
|
|
15
11
|
@cli.group()
|
|
@@ -26,11 +22,7 @@ async def tag_ls(ctx: Context, tag_name: Optional[str]) -> None:
|
|
|
26
22
|
"""List all the tags of the current Workspace or the resources associated to a specific tag."""
|
|
27
23
|
|
|
28
24
|
client = ctx.ensure_object(dict)["client"]
|
|
29
|
-
|
|
30
|
-
main_workspace = await get_current_main_workspace(client, config)
|
|
31
|
-
token = main_workspace.get("token") if main_workspace else None
|
|
32
|
-
|
|
33
|
-
response = await client.get_all_tags(token=token)
|
|
25
|
+
response = await client.get_all_tags()
|
|
34
26
|
|
|
35
27
|
if tag_name:
|
|
36
28
|
the_tag = [tag for tag in response["tags"] if tag["name"] == tag_name]
|
|
@@ -68,11 +60,7 @@ async def tag_create(ctx: Context, tag_name: str) -> None:
|
|
|
68
60
|
"""Create a tag in the current Workspace."""
|
|
69
61
|
|
|
70
62
|
client = ctx.ensure_object(dict)["client"]
|
|
71
|
-
|
|
72
|
-
main_workspace = await get_current_main_workspace(client, config)
|
|
73
|
-
token = main_workspace.get("token") if main_workspace else None
|
|
74
|
-
|
|
75
|
-
await client.create_tag(name=tag_name, token=token)
|
|
63
|
+
await client.create_tag(name=tag_name)
|
|
76
64
|
|
|
77
65
|
click.echo(FeedbackManager.success_tag_created(tag_name=tag_name))
|
|
78
66
|
|
|
@@ -86,14 +74,10 @@ async def tag_rm(ctx: Context, tag_name: str, yes: bool) -> None:
|
|
|
86
74
|
"""Remove a tag from the current Workspace."""
|
|
87
75
|
|
|
88
76
|
client = ctx.ensure_object(dict)["client"]
|
|
89
|
-
config = ctx.ensure_object(dict)["config"]
|
|
90
|
-
main_workspace = await get_current_main_workspace(client, config)
|
|
91
|
-
token = main_workspace.get("token") if main_workspace else None
|
|
92
|
-
|
|
93
77
|
remove_tag = True
|
|
94
78
|
|
|
95
79
|
if not yes:
|
|
96
|
-
all_tags = await client.get_all_tags(
|
|
80
|
+
all_tags = await client.get_all_tags()
|
|
97
81
|
the_tag = [tag for tag in all_tags["tags"] if tag["name"] == tag_name]
|
|
98
82
|
if len(the_tag) > 0:
|
|
99
83
|
unique_resources = []
|
|
@@ -112,5 +96,5 @@ async def tag_rm(ctx: Context, tag_name: str, yes: bool) -> None:
|
|
|
112
96
|
click.echo(FeedbackManager.error_tag_not_found(tag_name=tag_name))
|
|
113
97
|
|
|
114
98
|
if remove_tag:
|
|
115
|
-
await client.delete_tag(tag_name
|
|
99
|
+
await client.delete_tag(tag_name)
|
|
116
100
|
click.echo(FeedbackManager.success_tag_removed(tag_name=tag_name))
|
|
@@ -8,9 +8,11 @@ from typing import Any, Dict, Iterable, List, Tuple
|
|
|
8
8
|
|
|
9
9
|
import click
|
|
10
10
|
|
|
11
|
+
from tinybird.client import AuthNoTokenException
|
|
11
12
|
from tinybird.feedback_manager import FeedbackManager
|
|
12
13
|
from tinybird.tb_cli_modules.cli import cli
|
|
13
|
-
from tinybird.tb_cli_modules.common import coro, create_tb_client, gather_with_concurrency
|
|
14
|
+
from tinybird.tb_cli_modules.common import coro, create_tb_client, gather_with_concurrency
|
|
15
|
+
from tinybird.tb_cli_modules.config import CLIConfig
|
|
14
16
|
from tinybird.tb_cli_modules.exceptions import CLIException
|
|
15
17
|
from tinybird.tb_cli_modules.tinyunit.tinyunit import (
|
|
16
18
|
TestSummaryResults,
|
|
@@ -42,7 +44,9 @@ async def test_run(ctx: click.Context, file: Tuple[str, ...], verbose: bool, onl
|
|
|
42
44
|
|
|
43
45
|
try:
|
|
44
46
|
tb_client = create_tb_client(ctx)
|
|
45
|
-
config
|
|
47
|
+
config = CLIConfig.get_project_config()
|
|
48
|
+
if config.get("token") is None:
|
|
49
|
+
raise AuthNoTokenException
|
|
46
50
|
workspaces: List[Dict[str, Any]] = (await tb_client.user_workspaces_and_branches()).get("workspaces", [])
|
|
47
51
|
current_ws: Dict[str, Any] = next(
|
|
48
52
|
(workspace for workspace in workspaces if config and workspace.get("id", ".") == config.get("id", "..")), {}
|
|
@@ -9,11 +9,11 @@ import click
|
|
|
9
9
|
from click import Context
|
|
10
10
|
|
|
11
11
|
from tinybird.client import CanNotBeDeletedException, DoesNotExistException, TinyB
|
|
12
|
+
from tinybird.config import get_display_host
|
|
12
13
|
from tinybird.datafile import PipeTypes
|
|
13
14
|
from tinybird.feedback_manager import FeedbackManager
|
|
14
15
|
from tinybird.tb_cli_modules.cli import cli
|
|
15
16
|
from tinybird.tb_cli_modules.common import (
|
|
16
|
-
_get_config,
|
|
17
17
|
_get_workspace_plan_name,
|
|
18
18
|
ask_for_user_token,
|
|
19
19
|
check_user_token,
|
|
@@ -21,12 +21,10 @@ from tinybird.tb_cli_modules.common import (
|
|
|
21
21
|
create_workspace_interactive,
|
|
22
22
|
create_workspace_non_interactive,
|
|
23
23
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
24
|
-
get_config_and_hosts,
|
|
25
24
|
get_current_main_workspace,
|
|
26
25
|
is_valid_starterkit,
|
|
27
26
|
print_current_workspace,
|
|
28
27
|
switch_workspace,
|
|
29
|
-
try_update_config_with_remote,
|
|
30
28
|
)
|
|
31
29
|
from tinybird.tb_cli_modules.config import CLIConfig
|
|
32
30
|
from tinybird.tb_cli_modules.exceptions import CLIWorkspaceException
|
|
@@ -44,15 +42,12 @@ def workspace(ctx: Context) -> None:
|
|
|
44
42
|
async def workspace_ls(ctx: Context) -> None:
|
|
45
43
|
"""List all the workspaces you have access to in the account you're currently authenticated into."""
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if "id" not in config:
|
|
51
|
-
config = await _get_config(config["host"], config["token"], load_tb_file=False)
|
|
45
|
+
config = CLIConfig.get_project_config()
|
|
46
|
+
client = config.get_client()
|
|
52
47
|
|
|
53
48
|
response = await client.user_workspaces()
|
|
54
49
|
|
|
55
|
-
current_main_workspace = await get_current_main_workspace(
|
|
50
|
+
current_main_workspace = await get_current_main_workspace(config)
|
|
56
51
|
if not current_main_workspace:
|
|
57
52
|
raise CLIWorkspaceException(FeedbackManager.error_unable_to_identify_main_workspace())
|
|
58
53
|
|
|
@@ -80,7 +75,6 @@ async def workspace_ls(ctx: Context) -> None:
|
|
|
80
75
|
async def workspace_use(workspace_name_or_id: str) -> None:
|
|
81
76
|
"""Switch to another workspace. Use 'tb workspace ls' to list the workspaces you have access to."""
|
|
82
77
|
config = CLIConfig.get_project_config()
|
|
83
|
-
_ = await try_update_config_with_remote(config)
|
|
84
78
|
|
|
85
79
|
await switch_workspace(config, workspace_name_or_id)
|
|
86
80
|
|
|
@@ -90,7 +84,6 @@ async def workspace_use(workspace_name_or_id: str) -> None:
|
|
|
90
84
|
async def workspace_current():
|
|
91
85
|
"""Show the workspace you're currently authenticated to"""
|
|
92
86
|
config = CLIConfig.get_project_config()
|
|
93
|
-
_ = await try_update_config_with_remote(config)
|
|
94
87
|
|
|
95
88
|
await print_current_workspace(config)
|
|
96
89
|
|
|
@@ -107,11 +100,8 @@ async def clear_workspace(ctx: Context, yes: bool, dry_run: bool) -> None:
|
|
|
107
100
|
"""Drop all the resources inside a project. This command is dangerous because it removes everything, use with care."""
|
|
108
101
|
|
|
109
102
|
# Get current workspace to add the name to the alert message
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if "id" not in config:
|
|
114
|
-
config = await _get_config(config["host"], config["token"], load_tb_file=False)
|
|
103
|
+
config = CLIConfig.get_project_config()
|
|
104
|
+
client: TinyB = config.get_client()
|
|
115
105
|
|
|
116
106
|
response = await client.user_workspaces_and_branches()
|
|
117
107
|
|
|
@@ -213,7 +203,9 @@ async def create_workspace(
|
|
|
213
203
|
raise CLIWorkspaceException(FeedbackManager.error_starterkit_name(starterkit_name=starter_kit))
|
|
214
204
|
|
|
215
205
|
if not user_token:
|
|
216
|
-
|
|
206
|
+
config = CLIConfig.get_project_config()
|
|
207
|
+
host = config.get_host() or CLIConfig.DEFAULTS["host"]
|
|
208
|
+
ui_host = get_display_host(host)
|
|
217
209
|
user_token = ask_for_user_token("create a new workspace", ui_host)
|
|
218
210
|
if not user_token:
|
|
219
211
|
return
|
|
@@ -244,8 +236,10 @@ async def delete_workspace(
|
|
|
244
236
|
) -> None:
|
|
245
237
|
"""Delete a workspace where you are an admin."""
|
|
246
238
|
|
|
247
|
-
|
|
248
|
-
|
|
239
|
+
config = CLIConfig.get_project_config()
|
|
240
|
+
client = config.get_client()
|
|
241
|
+
host = config.get_host() or CLIConfig.DEFAULTS["host"]
|
|
242
|
+
ui_host = get_display_host(host)
|
|
249
243
|
|
|
250
244
|
if not user_token:
|
|
251
245
|
user_token = ask_for_user_token("delete a workspace", ui_host)
|
{tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/workspace_members.py
RENAMED
|
@@ -11,15 +11,16 @@ import click
|
|
|
11
11
|
from click import Context
|
|
12
12
|
|
|
13
13
|
from tinybird.client import TinyB
|
|
14
|
+
from tinybird.config import get_display_host
|
|
14
15
|
from tinybird.feedback_manager import FeedbackManager
|
|
15
16
|
from tinybird.tb_cli_modules.common import (
|
|
16
17
|
ask_for_user_token,
|
|
17
18
|
check_user_token,
|
|
18
19
|
coro,
|
|
19
20
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
20
|
-
get_config_and_hosts,
|
|
21
21
|
get_current_workspace,
|
|
22
22
|
)
|
|
23
|
+
from tinybird.tb_cli_modules.config import CLIConfig
|
|
23
24
|
from tinybird.tb_cli_modules.exceptions import CLIWorkspaceMembersException
|
|
24
25
|
from tinybird.tb_cli_modules.workspace import workspace
|
|
25
26
|
|
|
@@ -29,17 +30,20 @@ ROLES = ["viewer", "guest", "admin"]
|
|
|
29
30
|
@dataclass
|
|
30
31
|
class WorkspaceMemberCommandContext:
|
|
31
32
|
client: TinyB
|
|
32
|
-
config:
|
|
33
|
+
config: CLIConfig
|
|
33
34
|
host: str
|
|
34
35
|
ui_host: str
|
|
35
36
|
workspace: Dict[str, Any]
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
async def get_command_context(ctx: click.Context) -> WorkspaceMemberCommandContext:
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
config = CLIConfig.get_project_config()
|
|
41
|
+
client = config.get_client()
|
|
42
|
+
host = config.get_host() or CLIConfig.DEFAULTS["host"]
|
|
43
|
+
ui_host = get_display_host(host)
|
|
44
|
+
|
|
45
|
+
workspace = await get_current_workspace(config)
|
|
41
46
|
|
|
42
|
-
workspace = await get_current_workspace(client, config)
|
|
43
47
|
if not workspace:
|
|
44
48
|
raise CLIWorkspaceMembersException(FeedbackManager.error_unknown_resource(resource=config["d"]))
|
|
45
49
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tinybird-cli
|
|
3
|
-
Version: 5.8.
|
|
3
|
+
Version: 5.8.2.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
@@ -17,7 +17,8 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
17
17
|
|
|
18
18
|
Changelog
|
|
19
19
|
----------
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
5.8.1
|
|
21
22
|
***********
|
|
22
23
|
|
|
23
24
|
- `Improved` error message of `tb push` when pushing .datasource files
|
|
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-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py
RENAMED
|
File without changes
|
{tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-cli-5.8.1.dev1 → tinybird-cli-5.8.2.dev0}/tinybird_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|