tinybird-cli 5.20.1.dev0__tar.gz → 5.20.1.dev1__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.20.1.dev0 → tinybird_cli-5.20.1.dev1}/PKG-INFO +7 -1
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/__cli__.py +2 -2
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/ch_utils/engine.py +5 -2
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/datafile.py +2 -3
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/feedback_manager.py +1 -1
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/sql_template.py +3 -3
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/sql_toolset.py +79 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/connection.py +1 -1
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/fmt.py +1 -1
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +1 -1
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird_cli.egg-info/PKG-INFO +7 -1
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/setup.cfg +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/ch_utils/constants.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/check_pypi.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/client.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/config.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/connectors.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/context.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/datatypes.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/git_settings.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/sql.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/sql_template_fmt.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/syncasync.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/token.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tornado_template.py +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird_cli.egg-info/SOURCES.txt +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird_cli.egg-info/dependency_links.txt +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird_cli.egg-info/entry_points.txt +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird_cli.egg-info/requires.txt +0 -0
- {tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird_cli
|
|
3
|
-
Version: 5.20.1.
|
|
3
|
+
Version: 5.20.1.dev1
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli
|
|
6
6
|
Author: Tinybird
|
|
@@ -61,6 +61,11 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
61
61
|
Changelog
|
|
62
62
|
----------
|
|
63
63
|
|
|
64
|
+
5.20.1.dev1
|
|
65
|
+
***********
|
|
66
|
+
|
|
67
|
+
- `Added` When trying to push a materialized view with an unoptimized join, the CLI will now warn the user.
|
|
68
|
+
|
|
64
69
|
5.19.0
|
|
65
70
|
***********
|
|
66
71
|
|
|
@@ -198,6 +203,7 @@ Changelog
|
|
|
198
203
|
- `Added` `tb tag` commands to manage tags from the CLI.
|
|
199
204
|
- `Added` support to `TAGS` in `tb fmt`.
|
|
200
205
|
- `Added` support to `TAGS` in `tb pull` and `tb push`. Allows tagging resources for filtering in the UI.
|
|
206
|
+
- `Changed` Improved message when creating a DynamoDB connection
|
|
201
207
|
|
|
202
208
|
5.7.0
|
|
203
209
|
**********
|
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/cli'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '5.20.1.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '5.20.1.dev1'
|
|
8
|
+
__revision__ = '6ec3b53'
|
|
@@ -146,10 +146,9 @@ class TableDetails:
|
|
|
146
146
|
def is_replacing_engine(self) -> bool:
|
|
147
147
|
if self.engine:
|
|
148
148
|
engine_lower = self.engine.lower()
|
|
149
|
-
is_aggregating = "aggregatingmergetree" in engine_lower
|
|
150
149
|
is_replacing = "replacingmergetree" in engine_lower
|
|
151
150
|
is_collapsing = "collapsingmergetree" in engine_lower
|
|
152
|
-
return
|
|
151
|
+
return is_replacing or is_collapsing
|
|
153
152
|
return False
|
|
154
153
|
|
|
155
154
|
def diff_ttl(self, new_ttl: str) -> bool:
|
|
@@ -169,6 +168,10 @@ class TableDetails:
|
|
|
169
168
|
@property
|
|
170
169
|
def sorting_key(self) -> Optional[str]:
|
|
171
170
|
_sorting_key = self.details.get("sorting_key", None)
|
|
171
|
+
# TODO: This should use ENABLED_ENGINES to guess if the sorting key is required or not
|
|
172
|
+
# Also checking this and raising an error in a getter is a bit of an anti-pattern,
|
|
173
|
+
# a data source could have a "wrong" sorting key and we won't be able to even show it in the API.
|
|
174
|
+
# All these checks be performed only on creation time.
|
|
172
175
|
if self.is_replacing_engine() and not _sorting_key:
|
|
173
176
|
raise ValueError(f"SORTING_KEY must be defined for the {self.engine} engine")
|
|
174
177
|
if self.is_mergetree_family():
|
|
@@ -1872,8 +1872,7 @@ def drop_token(url: str) -> str:
|
|
|
1872
1872
|
parsed = urlparse(url)
|
|
1873
1873
|
qs = parse_qs(parsed.query)
|
|
1874
1874
|
qs_simplify = {k: v[0] for k, v in qs.items()} # change several arguments to single one
|
|
1875
|
-
|
|
1876
|
-
del qs_simplify["token"]
|
|
1875
|
+
qs_simplify.pop("token", None)
|
|
1877
1876
|
return f"{parsed.scheme}://{parsed.netloc}{parsed.path}?{urlencode(qs_simplify)}"
|
|
1878
1877
|
|
|
1879
1878
|
|
|
@@ -4849,7 +4848,7 @@ def format_include(file_parts: List[str], doc: Datafile, unroll_includes: bool =
|
|
|
4849
4848
|
assert doc.raw is not None
|
|
4850
4849
|
|
|
4851
4850
|
include = [line for line in doc.raw if "INCLUDE" in line and ".incl" in line]
|
|
4852
|
-
if
|
|
4851
|
+
if include:
|
|
4853
4852
|
file_parts.append(include[0])
|
|
4854
4853
|
file_parts.append(DATAFILE_NEW_LINE)
|
|
4855
4854
|
return file_parts
|
|
@@ -491,7 +491,7 @@ Ready? """
|
|
|
491
491
|
"""\n[2] Go to IAM > Policies. Create a new policy with the following permissions. Please, replace {replacements}:\n\n{access_policy}\n\n(The policy has been copied to your clipboard)\n\n"""
|
|
492
492
|
)
|
|
493
493
|
prompt_s3_iamrole_connection_policy_not_copied = prompt_message(
|
|
494
|
-
"""\n[2] Go to IAM > Policies. Create a new policy with the following permissions. Please, copy this policy and replace <bucket> with your bucket name:\n\n{access_policy}\n\n"""
|
|
494
|
+
"""\n[2] Go to IAM > Policies. Create a new policy with the following permissions. Please, copy this policy and replace <bucket> with your bucket name and <table_name> with your table name:\n\n{access_policy}\n\n"""
|
|
495
495
|
)
|
|
496
496
|
prompt_s3_iamrole_connection_role = prompt_message(
|
|
497
497
|
"""\n[3] Go to IAM > Roles. Create a new IAM Role using the following custom trust policy and attach the access policy you just created in the previous step:\n\n{trust_policy}\n\n(The policy has been copied to your clipboard)\n\n"""
|
|
@@ -1657,7 +1657,7 @@ def get_var_data(content, node_id=None):
|
|
|
1657
1657
|
# It will be overriden in later definitions or left as is otherwise.
|
|
1658
1658
|
# args[0] check is used to avoid adding unnamed parameters found in
|
|
1659
1659
|
# templates like: `split_to_array('')`
|
|
1660
|
-
if
|
|
1660
|
+
if args and isinstance(args[0], list):
|
|
1661
1661
|
raise ValueError(f'"{args[0]}" can not be used as a variable name')
|
|
1662
1662
|
if len(args) > 0 and args[0] not in vars and args[0]:
|
|
1663
1663
|
vars[args[0]] = {
|
|
@@ -1669,7 +1669,7 @@ def get_var_data(content, node_id=None):
|
|
|
1669
1669
|
if "default" not in kwargs:
|
|
1670
1670
|
default = kwargs.get("default", args[2] if len(args) > 2 and args[2] else None)
|
|
1671
1671
|
kwargs["default"] = check_default_value(default)
|
|
1672
|
-
if
|
|
1672
|
+
if args:
|
|
1673
1673
|
if isinstance(args[0], list):
|
|
1674
1674
|
raise ValueError(f'"{args[0]}" can not be used as a variable name')
|
|
1675
1675
|
vars[args[0]] = {
|
|
@@ -1678,7 +1678,7 @@ def get_var_data(content, node_id=None):
|
|
|
1678
1678
|
}
|
|
1679
1679
|
elif func in parameter_types:
|
|
1680
1680
|
# avoid variable names to be None
|
|
1681
|
-
if
|
|
1681
|
+
if args and args[0] is not None:
|
|
1682
1682
|
# if this is a cast use the function name to get the type
|
|
1683
1683
|
if "default" not in kwargs:
|
|
1684
1684
|
default = kwargs.get("default", args[1] if len(args) > 1 else None)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import logging
|
|
3
|
+
import re
|
|
3
4
|
from collections import defaultdict
|
|
4
5
|
from datetime import datetime
|
|
5
6
|
from functools import lru_cache
|
|
@@ -42,10 +43,88 @@ class InvalidResource(ValueError):
|
|
|
42
43
|
self.table = table
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
class UnoptimizedJoinException(Exception):
|
|
47
|
+
def __init__(self, sql: str):
|
|
48
|
+
self.sql = sql
|
|
49
|
+
self.msg = f"Materialized node SQL contains a join that is not optimized: {sql}"
|
|
50
|
+
self.documentation = (
|
|
51
|
+
"/docs/work-with-data/optimization/opt201-fix-mistakes#understanding-the-materialized-join-issue"
|
|
52
|
+
)
|
|
53
|
+
super().__init__(self.msg)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
ChQueryTable = Tuple[Optional[str], Optional[str], Optional[str]]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_left_table(sql: str, default_database: Optional[str] = None) -> ChQueryTable:
|
|
60
|
+
if default_database is None:
|
|
61
|
+
left_table = chquery.get_left_table(sql)
|
|
62
|
+
else:
|
|
63
|
+
left_table = chquery.get_left_table(sql, default_database=default_database)
|
|
64
|
+
return left_table
|
|
65
|
+
|
|
66
|
+
|
|
45
67
|
def format_sql(sql: str) -> str:
|
|
46
68
|
return chquery.format(sql)
|
|
47
69
|
|
|
48
70
|
|
|
71
|
+
def explain_plan(sql: str) -> str:
|
|
72
|
+
return chquery.explain_ast(sql)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def has_join(sql: str) -> bool:
|
|
76
|
+
return any(line.rstrip().startswith("TableJoin") for line in explain_plan(sql).split())
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def has_unoptimized_join(sql: str, left_table: Optional[Union[Tuple[str, str], Tuple[str, str, str]]] = None) -> None:
|
|
80
|
+
"""
|
|
81
|
+
Check if a SQL query contains an unoptimized join.
|
|
82
|
+
A join is considered optimized if the right table is filtered by the left table's data.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
sql: The SQL query to check
|
|
86
|
+
left_table: Optional tuple of (database, table) for the left table
|
|
87
|
+
|
|
88
|
+
Raises:
|
|
89
|
+
UnoptimizedJoin: If an unoptimized join is found
|
|
90
|
+
"""
|
|
91
|
+
# TODO: We should check that we are filtering the right table by the left table's data
|
|
92
|
+
# TODO: We should check if using EXPLAIN AST is better than using regex
|
|
93
|
+
|
|
94
|
+
number_of_joins = sum(1 for line in explain_plan(sql).split() if line.rstrip().startswith("TableJoin"))
|
|
95
|
+
if number_of_joins == 0:
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
if not left_table:
|
|
99
|
+
left_table = chquery.get_left_table(sql)
|
|
100
|
+
if not left_table:
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
# Find all JOIN clauses with subqueries
|
|
104
|
+
# This pattern matches anything between JOIN and ON/USING
|
|
105
|
+
join_pattern = r"(?:LEFT\s+|RIGHT\s+|INNER\s+|FULL\s+OUTER\s+)?JOIN\s*\((.*?)\)\s+(?:AS\s+\w+)?\s*(?:ON|USING)"
|
|
106
|
+
|
|
107
|
+
# Find all joins with subqueries
|
|
108
|
+
join_matches = list(re.finditer(join_pattern, sql, re.IGNORECASE | re.DOTALL))
|
|
109
|
+
|
|
110
|
+
if number_of_joins != len(join_matches):
|
|
111
|
+
logging.debug(f"number_of_joins: {number_of_joins}, join_matches: {join_matches}")
|
|
112
|
+
raise UnoptimizedJoinException(sql)
|
|
113
|
+
|
|
114
|
+
# If no joins with subqueries found, probably is an unoptimized join
|
|
115
|
+
if not join_matches:
|
|
116
|
+
raise UnoptimizedJoinException(sql)
|
|
117
|
+
|
|
118
|
+
# Check if the left table is referenced in the subquery
|
|
119
|
+
left_table_ref = f"{left_table[0]}.{left_table[1]}"
|
|
120
|
+
|
|
121
|
+
for match in join_matches:
|
|
122
|
+
subquery = match.group(1) # Get the captured subquery
|
|
123
|
+
logging.debug(f"subquery: {subquery} left_table_ref: {left_table_ref}")
|
|
124
|
+
if left_table_ref not in subquery:
|
|
125
|
+
raise UnoptimizedJoinException(sql)
|
|
126
|
+
|
|
127
|
+
|
|
49
128
|
def format_where_for_mutation_command(where_clause: str) -> str:
|
|
50
129
|
"""
|
|
51
130
|
>>> format_where_for_mutation_command("numnights = 99")
|
|
@@ -293,7 +293,7 @@ async def connection_create_snowflake(
|
|
|
293
293
|
if not warehouse:
|
|
294
294
|
warehouses = await client.get_snowflake_warehouses(account, username, password, role) or []
|
|
295
295
|
warehouses_names = [w["name"] for w in warehouses]
|
|
296
|
-
default_warehouse = warehouses_names[0] if
|
|
296
|
+
default_warehouse = warehouses_names[0] if warehouses_names else ""
|
|
297
297
|
warehouse = click.prompt(
|
|
298
298
|
"Warehouse (optional)",
|
|
299
299
|
type=click.types.Choice(warehouses_names, case_sensitive=False),
|
|
@@ -83,7 +83,7 @@ async def fmt(
|
|
|
83
83
|
|
|
84
84
|
click.echo(FeedbackManager.success_generated_local_file(file=filename))
|
|
85
85
|
|
|
86
|
-
if
|
|
86
|
+
if failed:
|
|
87
87
|
click.echo(FeedbackManager.error_failed_to_format_files(number=len(failed)))
|
|
88
88
|
for f in failed:
|
|
89
89
|
click.echo(f"tb fmt {f} --yes")
|
{tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/tinyunit/tinyunit.py
RENAMED
|
@@ -317,7 +317,7 @@ def test_run_summary(results: List[TestSummaryResults], only_fail: bool = False,
|
|
|
317
317
|
if test.error:
|
|
318
318
|
click.secho(test.error, fg=test.status.color, bold=True, nl=True, err=True)
|
|
319
319
|
|
|
320
|
-
if
|
|
320
|
+
if total_counts:
|
|
321
321
|
click.echo("\nTotals:")
|
|
322
322
|
for key_status, value_total in total_counts.items():
|
|
323
323
|
code_summary = f"Total {key_status.description}: {value_total}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird_cli
|
|
3
|
-
Version: 5.20.1.
|
|
3
|
+
Version: 5.20.1.dev1
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli
|
|
6
6
|
Author: Tinybird
|
|
@@ -61,6 +61,11 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
61
61
|
Changelog
|
|
62
62
|
----------
|
|
63
63
|
|
|
64
|
+
5.20.1.dev1
|
|
65
|
+
***********
|
|
66
|
+
|
|
67
|
+
- `Added` When trying to push a materialized view with an unoptimized join, the CLI will now warn the user.
|
|
68
|
+
|
|
64
69
|
5.19.0
|
|
65
70
|
***********
|
|
66
71
|
|
|
@@ -198,6 +203,7 @@ Changelog
|
|
|
198
203
|
- `Added` `tb tag` commands to manage tags from the CLI.
|
|
199
204
|
- `Added` support to `TAGS` in `tb fmt`.
|
|
200
205
|
- `Added` support to `TAGS` in `tb pull` and `tb push`. Allows tagging resources for filtering in the UI.
|
|
206
|
+
- `Changed` Improved message when creating a DynamoDB connection
|
|
201
207
|
|
|
202
208
|
5.7.0
|
|
203
209
|
**********
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird/tb_cli_modules/workspace_members.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{tinybird_cli-5.20.1.dev0 → tinybird_cli-5.20.1.dev1}/tinybird_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|