tinybird-cli 3.8.2.dev1__tar.gz → 3.9.0__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-3.8.2.dev1 → tinybird-cli-3.9.0}/PKG-INFO +5 -3
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/__cli__.py +2 -2
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/client.py +5 -2
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/feedback_manager.py +1 -1
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/sql_template.py +89 -2
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/sql_toolset.py +1 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/connection.py +27 -6
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird_cli.egg-info/PKG-INFO +5 -3
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/setup.cfg +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/check_pypi.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/config.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/connectors.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/context.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/datafile.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/datatypes.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/git_settings.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/sql.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/syncasync.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/token.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tornado_template.py +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird_cli.egg-info/SOURCES.txt +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird_cli.egg-info/dependency_links.txt +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird_cli.egg-info/entry_points.txt +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird_cli.egg-info/requires.txt +0 -0
- {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.9.0}/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: 3.
|
|
3
|
+
Version: 3.9.0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
@@ -16,15 +16,17 @@ Tinybird CLI
|
|
|
16
16
|
The Tinybird command-line tool allows you to use all the Tinybird functionality directly from the command line. Additionally, it includes several functions to create and manage data projects easily.
|
|
17
17
|
|
|
18
18
|
Changelog
|
|
19
|
-
|
|
20
19
|
---------
|
|
21
20
|
|
|
22
|
-
3.
|
|
21
|
+
3.9.0
|
|
23
22
|
************
|
|
24
23
|
|
|
24
|
+
- `Added` Support for connection names when doing `tb connection rm`
|
|
25
|
+
- `Added` New `--policy` option for `create s3_iamrole` command that will generate different hints depending on the case
|
|
25
26
|
- `Fixed` Avoid system vars evaluation when doing `tb fmt`
|
|
26
27
|
- `Fixed` environment variables substitution for Data Source engine parameters.
|
|
27
28
|
|
|
29
|
+
|
|
28
30
|
3.8.0
|
|
29
31
|
************
|
|
30
32
|
|
|
@@ -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__ = '3.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '3.9.0'
|
|
8
|
+
__revision__ = 'e7e3bee'
|
|
@@ -997,8 +997,11 @@ class TinyB(object):
|
|
|
997
997
|
async def get_s3_trust_policy(self) -> Dict[str, Any]:
|
|
998
998
|
return await self._req("/v0/integrations/s3/policies/trust-policy")
|
|
999
999
|
|
|
1000
|
-
async def
|
|
1001
|
-
return await self._req("/v0/integrations/s3/policies/access-policy")
|
|
1000
|
+
async def get_s3_access_write_policy(self) -> Dict[str, Any]:
|
|
1001
|
+
return await self._req("/v0/integrations/s3/policies/write-access-policy")
|
|
1002
|
+
|
|
1003
|
+
async def get_s3_access_read_policy(self) -> Dict[str, Any]:
|
|
1004
|
+
return await self._req("/v0/integrations/s3/policies/read-access-policy")
|
|
1002
1005
|
|
|
1003
1006
|
async def sql_get_format(self, sql: str, with_clickhouse_format: bool = False) -> str:
|
|
1004
1007
|
try:
|
|
@@ -205,7 +205,7 @@ class FeedbackManager:
|
|
|
205
205
|
error_connection_already_exists = error_message(
|
|
206
206
|
"Connection {name} already exists. Use 'tb connection ls' to list your connections"
|
|
207
207
|
)
|
|
208
|
-
error_connection_does_not_exists = error_message("Connection {
|
|
208
|
+
error_connection_does_not_exists = error_message("Connection {connection_id} does not exist")
|
|
209
209
|
error_connection_create = error_message("Connection {connection_name} could not be created: {error}")
|
|
210
210
|
error_connection_integration_not_available = error_message("Connection could not be created: {error}")
|
|
211
211
|
error_workspace = error_message("Workspace {workspace} not found. use 'tb workspace ls' to list your workspaces")
|
|
@@ -1562,7 +1562,20 @@ def get_var_data(content, node_id=None): # noqa: C901
|
|
|
1562
1562
|
|
|
1563
1563
|
return vars
|
|
1564
1564
|
|
|
1565
|
-
|
|
1565
|
+
def parse_content(content, retries=0):
|
|
1566
|
+
try:
|
|
1567
|
+
parsed = ast.parse(content)
|
|
1568
|
+
return parsed
|
|
1569
|
+
except Exception as e:
|
|
1570
|
+
if "AST constructor recursion depth mismatch" not in str(e):
|
|
1571
|
+
raise e
|
|
1572
|
+
retries += 1
|
|
1573
|
+
if retries > 3:
|
|
1574
|
+
raise e
|
|
1575
|
+
return parse_content(content, retries)
|
|
1576
|
+
|
|
1577
|
+
parsed = parse_content(content)
|
|
1578
|
+
|
|
1566
1579
|
# calculate parents for each node for later checks
|
|
1567
1580
|
for node in ast.walk(parsed):
|
|
1568
1581
|
for child in ast.iter_child_nodes(node):
|
|
@@ -1655,6 +1668,11 @@ def get_var_names_and_types(t, node_id=None): # noqa: C901
|
|
|
1655
1668
|
raise SQLTemplateException(e)
|
|
1656
1669
|
|
|
1657
1670
|
|
|
1671
|
+
@lru_cache(maxsize=256)
|
|
1672
|
+
def get_var_names_and_types_cached(t: Template):
|
|
1673
|
+
return get_var_names_and_types(t)
|
|
1674
|
+
|
|
1675
|
+
|
|
1658
1676
|
def wrap_vars(t):
|
|
1659
1677
|
def _n(chunks, v):
|
|
1660
1678
|
for x in chunks:
|
|
@@ -1746,8 +1764,55 @@ def get_template_and_variables(sql: str, name: Optional[str]):
|
|
|
1746
1764
|
raise SQLTemplateException(e)
|
|
1747
1765
|
|
|
1748
1766
|
|
|
1767
|
+
def preprocess_variables(variables: dict, t: Template):
|
|
1768
|
+
"""
|
|
1769
|
+
>>> preprocess_variables({"test": "1,2"}, Template("select * from table where f = {{Array(test, 'String')}}"))
|
|
1770
|
+
{'test': ['1', '2']}
|
|
1771
|
+
>>> preprocess_variables({"test": ['1', '2']}, Template("select * from table where f = {{Array(test, 'String')}}"))
|
|
1772
|
+
{'test': ['1', '2']}
|
|
1773
|
+
>>> preprocess_variables({"test": [1,2]}, Template("select * from table where f = {{Array(test, 'String')}}"))
|
|
1774
|
+
{'test': ['1', '2']}
|
|
1775
|
+
>>> preprocess_variables({"test": '24'}, Template("select * from table where f = {{Int32(test)}}"))
|
|
1776
|
+
{}
|
|
1777
|
+
>>> preprocess_variables({"test": "1,2,3"}, Template("select * from table where f = {{Array(test,'Int32')}}"))
|
|
1778
|
+
{'test': [1, 2, 3]}
|
|
1779
|
+
>>> preprocess_variables({"test": "1,2,msg"}, Template("select * from table where f = {{Array(test,'Int32')}}"))
|
|
1780
|
+
{}
|
|
1781
|
+
"""
|
|
1782
|
+
template_variables = get_var_names_and_types_cached(t)
|
|
1783
|
+
processed_variables = {}
|
|
1784
|
+
for variable, value in variables.items():
|
|
1785
|
+
try:
|
|
1786
|
+
template_vars = [t_var for t_var in template_variables if t_var["name"] == variable] or None
|
|
1787
|
+
if template_vars is None or value is None:
|
|
1788
|
+
continue
|
|
1789
|
+
|
|
1790
|
+
t_var = template_vars[0]
|
|
1791
|
+
var_type = t_var.get("type")
|
|
1792
|
+
if var_type is None:
|
|
1793
|
+
continue
|
|
1794
|
+
|
|
1795
|
+
# For now, we only preprocess Array types
|
|
1796
|
+
match = re.match(r"Array\((\w+)\)", var_type)
|
|
1797
|
+
if match is None:
|
|
1798
|
+
continue
|
|
1799
|
+
|
|
1800
|
+
array_type = match.group(1)
|
|
1801
|
+
array_fn = type_fns.get("Array")
|
|
1802
|
+
parsed_exp = array_fn(value, array_type)
|
|
1803
|
+
processed_variables[variable] = ast.literal_eval(parsed_exp)
|
|
1804
|
+
except Exception:
|
|
1805
|
+
continue
|
|
1806
|
+
|
|
1807
|
+
return processed_variables
|
|
1808
|
+
|
|
1809
|
+
|
|
1749
1810
|
def render_sql_template(
|
|
1750
|
-
sql: str,
|
|
1811
|
+
sql: str,
|
|
1812
|
+
variables: Optional[dict] = None,
|
|
1813
|
+
test_mode: bool = False,
|
|
1814
|
+
name: Optional[str] = None,
|
|
1815
|
+
preprocess_variables_flag: bool = False,
|
|
1751
1816
|
) -> Tuple[str, dict]:
|
|
1752
1817
|
"""
|
|
1753
1818
|
>>> render_sql_template("select * from table where f = {{Float32(foo)}}", { 'foo': -1 })
|
|
@@ -1934,10 +1999,32 @@ def render_sql_template(
|
|
|
1934
1999
|
Traceback (most recent call last):
|
|
1935
2000
|
...
|
|
1936
2001
|
tinybird.sql_template.SQLTemplateException: Template Syntax Error: Error parsing JSON: '' - Expecting value: line 1 column 1 (char 0)
|
|
2002
|
+
>>> render_sql_template("% {% if defined(test) %}{% set _groupByCSV = ','.join(test) %} SELECT test as aa, {{Array(test, 'String')}} as test, {{_groupByCSV}} as a {% end %}", {"test": "1,2"}, preprocess_variables_flag=True)
|
|
2003
|
+
("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
|
|
2004
|
+
>>> render_sql_template("% {% if defined(test) %}{% set _groupByCSV = ','.join(test) %} SELECT test as aa, {{Array(test, 'String')}} as test, {{_groupByCSV}} as a {% end %}", {"test": ["1","2"]}, preprocess_variables_flag=True)
|
|
2005
|
+
("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
|
|
2006
|
+
>>> render_sql_template("% {% if defined(test) %}{% set _total = sum(test) %} SELECT test as aa, {{Array(test, 'Int32')}} as test, {{_total}} as a {% end %}", {"test": "1,2"}, preprocess_variables_flag=True)
|
|
2007
|
+
('% SELECT test as aa, [1,2] as test, 3 as a ', {})
|
|
2008
|
+
>>> render_sql_template("% {% if defined(test) %}{% set _groupByCSV = ','.join(test) %} SELECT test as aa, {{Array(test, 'String')}} as test, {{_groupByCSV}} as a {% end %}", {"test": "1,2"})
|
|
2009
|
+
("% SELECT test as aa, ['1','2'] as test, '1,,,2' as a ", {})
|
|
2010
|
+
>>> render_sql_template("% {% if defined(test) %}{% set _groupByCSV = ','.join(test) %} SELECT test as aa, {{Array(test, 'String')}} as test, {{_groupByCSV}} as a {% end %}", {"test": ["1","2"]})
|
|
2011
|
+
("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
|
|
2012
|
+
>>> render_sql_template("% {% if defined(test) %}{% set _total = sum(test) %} SELECT test as aa, {{Array(test, 'Int32')}} as test, {{_total}} as a {% end %}", {"test": "1,2"})
|
|
2013
|
+
Traceback (most recent call last):
|
|
2014
|
+
...
|
|
2015
|
+
ValueError: unsupported operand type(s) for +: 'int' and 'str'
|
|
2016
|
+
>>> render_sql_template("% SELECT {% if defined(x) %} x, 1", preprocess_variables_flag=True)
|
|
2017
|
+
Traceback (most recent call last):
|
|
2018
|
+
...
|
|
2019
|
+
tinybird.tornado_template.UnClosedIfError: Missing {% end %} block for if at line 1
|
|
1937
2020
|
"""
|
|
1938
2021
|
|
|
1939
2022
|
t, template_variables = get_template_and_variables(sql, name)
|
|
1940
2023
|
|
|
2024
|
+
if preprocess_variables_flag and variables is not None:
|
|
2025
|
+
processed_variables = preprocess_variables(variables, t)
|
|
2026
|
+
variables.update(processed_variables)
|
|
2027
|
+
|
|
1941
2028
|
if test_mode:
|
|
1942
2029
|
|
|
1943
2030
|
def dummy(*args, **kwargs):
|
|
@@ -164,6 +164,7 @@ def replace_tables(
|
|
|
164
164
|
valid_tables: Optional[Set[Tuple[str, str]]] = None,
|
|
165
165
|
output_one_line: bool = False,
|
|
166
166
|
timestamp: Optional[datetime] = None,
|
|
167
|
+
preprocess_variables_flag: bool = False,
|
|
167
168
|
) -> str:
|
|
168
169
|
"""
|
|
169
170
|
Given a query and a list of table replacements, returns the query after applying the table replacements.
|
|
@@ -394,25 +394,39 @@ async def connection_create_bigquery(ctx: Context, no_validate: bool) -> None:
|
|
|
394
394
|
|
|
395
395
|
|
|
396
396
|
@connection.command(name="rm")
|
|
397
|
-
@click.argument("
|
|
397
|
+
@click.argument("connection_id_or_name")
|
|
398
398
|
@click.option(
|
|
399
399
|
"--force", default=False, help="Force connection removal even if there are datasources currently using it"
|
|
400
400
|
)
|
|
401
401
|
@click.pass_context
|
|
402
402
|
@coro
|
|
403
|
-
async def connection_rm(ctx: Context,
|
|
403
|
+
async def connection_rm(ctx: Context, connection_id_or_name: str, force: bool) -> None:
|
|
404
404
|
"""Remove a connection."""
|
|
405
405
|
|
|
406
406
|
obj: Dict[str, Any] = ctx.ensure_object(dict)
|
|
407
407
|
client: TinyB = obj["client"]
|
|
408
408
|
|
|
409
409
|
try:
|
|
410
|
-
await client.connector_delete(
|
|
410
|
+
await client.connector_delete(connection_id_or_name)
|
|
411
411
|
except DoesNotExistException:
|
|
412
|
-
|
|
412
|
+
connections = await client.connections()
|
|
413
|
+
connection = next(
|
|
414
|
+
(connection for connection in connections if connection["name"] == connection_id_or_name), None
|
|
415
|
+
)
|
|
416
|
+
if connection:
|
|
417
|
+
try:
|
|
418
|
+
await client.connector_delete(connection["id"])
|
|
419
|
+
except DoesNotExistException:
|
|
420
|
+
raise CLIConnectionException(
|
|
421
|
+
FeedbackManager.error_connection_does_not_exists(connection_id=connection_id_or_name)
|
|
422
|
+
)
|
|
423
|
+
else:
|
|
424
|
+
raise CLIConnectionException(
|
|
425
|
+
FeedbackManager.error_connection_does_not_exists(connection_id=connection_id_or_name)
|
|
426
|
+
)
|
|
413
427
|
except Exception as e:
|
|
414
428
|
raise CLIConnectionException(FeedbackManager.error_exception(error=e))
|
|
415
|
-
click.echo(FeedbackManager.success_delete_connection(connection_id=
|
|
429
|
+
click.echo(FeedbackManager.success_delete_connection(connection_id=connection_id_or_name))
|
|
416
430
|
|
|
417
431
|
|
|
418
432
|
@connection.command(name="ls")
|
|
@@ -698,6 +712,7 @@ async def connection_create_gcs(
|
|
|
698
712
|
@click.option("--connection-name", default=None, help="The name of the connection to identify it in Tinybird")
|
|
699
713
|
@click.option("--role-arn", default=None, help="The ARN of the IAM role to use for the connection")
|
|
700
714
|
@click.option("--region", default=None, help="The Amazon S3 region where the bucket is located")
|
|
715
|
+
@click.option("--policy", default="write", help="The Amazon S3 access policy: write or read")
|
|
701
716
|
@click.option(
|
|
702
717
|
"--no-validate", is_flag=True, default=False, help="Do not validate S3 permissions during connection creation"
|
|
703
718
|
)
|
|
@@ -708,6 +723,7 @@ async def connection_create_s3_iamrole(
|
|
|
708
723
|
connection_name: Optional[str] = "",
|
|
709
724
|
role_arn: Optional[str] = "",
|
|
710
725
|
region: Optional[str] = "",
|
|
726
|
+
policy: str = "write",
|
|
711
727
|
no_validate: Optional[bool] = False,
|
|
712
728
|
) -> None:
|
|
713
729
|
"""
|
|
@@ -723,7 +739,12 @@ async def connection_create_s3_iamrole(
|
|
|
723
739
|
async def get_s3_policies():
|
|
724
740
|
s3_access_policy: Dict[str, Any] = {}
|
|
725
741
|
try:
|
|
726
|
-
|
|
742
|
+
if policy == "write":
|
|
743
|
+
s3_access_policy = await client.get_s3_access_write_policy()
|
|
744
|
+
elif policy == "read":
|
|
745
|
+
s3_access_policy = await client.get_s3_access_read_policy()
|
|
746
|
+
else:
|
|
747
|
+
raise Exception(f"Access policy {policy} not supported. Choose from 'read' or 'write'")
|
|
727
748
|
if not len(s3_access_policy) > 0:
|
|
728
749
|
raise Exception("S3 Integration not supported in this region")
|
|
729
750
|
except Exception as e:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tinybird-cli
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.9.0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
@@ -16,15 +16,17 @@ Tinybird CLI
|
|
|
16
16
|
The Tinybird command-line tool allows you to use all the Tinybird functionality directly from the command line. Additionally, it includes several functions to create and manage data projects easily.
|
|
17
17
|
|
|
18
18
|
Changelog
|
|
19
|
-
|
|
20
19
|
---------
|
|
21
20
|
|
|
22
|
-
3.
|
|
21
|
+
3.9.0
|
|
23
22
|
************
|
|
24
23
|
|
|
24
|
+
- `Added` Support for connection names when doing `tb connection rm`
|
|
25
|
+
- `Added` New `--policy` option for `create s3_iamrole` command that will generate different hints depending on the case
|
|
25
26
|
- `Fixed` Avoid system vars evaluation when doing `tb fmt`
|
|
26
27
|
- `Fixed` environment variables substitution for Data Source engine parameters.
|
|
27
28
|
|
|
29
|
+
|
|
28
30
|
3.8.0
|
|
29
31
|
************
|
|
30
32
|
|
|
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-3.8.2.dev1 → tinybird-cli-3.9.0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|