tinybird-cli 3.8.2.dev1__tar.gz → 3.8.2.dev2__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.
Files changed (46) hide show
  1. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/PKG-INFO +12 -2
  2. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/__cli__.py +2 -2
  3. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/client.py +5 -2
  4. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/feedback_manager.py +1 -1
  5. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/sql_template.py +71 -1
  6. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/sql_toolset.py +1 -0
  7. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/connection.py +27 -6
  8. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird_cli.egg-info/PKG-INFO +12 -2
  9. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/setup.cfg +0 -0
  10. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/ch_utils/constants.py +0 -0
  11. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/ch_utils/engine.py +0 -0
  12. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/check_pypi.py +0 -0
  13. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/config.py +0 -0
  14. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/connectors.py +0 -0
  15. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/context.py +0 -0
  16. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/datafile.py +0 -0
  17. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/datatypes.py +0 -0
  18. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/git_settings.py +0 -0
  19. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/sql.py +0 -0
  20. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/sql_template_fmt.py +0 -0
  21. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/syncasync.py +0 -0
  22. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli.py +0 -0
  23. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/auth.py +0 -0
  24. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/branch.py +0 -0
  25. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/cicd.py +0 -0
  26. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/cli.py +0 -0
  27. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/common.py +0 -0
  28. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/config.py +0 -0
  29. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/datasource.py +0 -0
  30. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/exceptions.py +0 -0
  31. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/job.py +0 -0
  32. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/pipe.py +0 -0
  33. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/regions.py +0 -0
  34. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/telemetry.py +0 -0
  35. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/test.py +0 -0
  36. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  37. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  38. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/token.py +0 -0
  39. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/workspace.py +0 -0
  40. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  41. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird/tornado_template.py +0 -0
  42. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird_cli.egg-info/SOURCES.txt +0 -0
  43. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird_cli.egg-info/dependency_links.txt +0 -0
  44. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird_cli.egg-info/entry_points.txt +0 -0
  45. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/tinybird_cli.egg-info/requires.txt +0 -0
  46. {tinybird-cli-3.8.2.dev1 → tinybird-cli-3.8.2.dev2}/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.8.2.dev1
3
+ Version: 3.8.2.dev2
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,25 @@ 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
 
21
+ 3.8.2.dev2
22
+ ************
23
+
24
+ - `Added` New `--policy` option for `create s3_iamrole` command that will generate different hints depending on the case
25
+
26
+ 3.8.2.dev1
27
+ ************
28
+
29
+ - `Added` Support for connection names when doing `tb connection rm`
30
+
22
31
  3.8.1
23
32
  ************
24
33
 
25
34
  - `Fixed` Avoid system vars evaluation when doing `tb fmt`
26
35
  - `Fixed` environment variables substitution for Data Source engine parameters.
27
36
 
37
+
28
38
  3.8.0
29
39
  ************
30
40
 
@@ -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.2.dev1'
8
- __revision__ = 'f993ee3'
7
+ __version__ = '3.8.2.dev2'
8
+ __revision__ = 'b88d054'
@@ -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 get_s3_access_policy(self) -> Dict[str, Any]:
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 {connection} does not exist")
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")
@@ -1655,6 +1655,11 @@ def get_var_names_and_types(t, node_id=None): # noqa: C901
1655
1655
  raise SQLTemplateException(e)
1656
1656
 
1657
1657
 
1658
+ @lru_cache(maxsize=256)
1659
+ def get_var_names_and_types_cached(t: Template):
1660
+ return get_var_names_and_types(t)
1661
+
1662
+
1658
1663
  def wrap_vars(t):
1659
1664
  def _n(chunks, v):
1660
1665
  for x in chunks:
@@ -1746,8 +1751,55 @@ def get_template_and_variables(sql: str, name: Optional[str]):
1746
1751
  raise SQLTemplateException(e)
1747
1752
 
1748
1753
 
1754
+ def preprocess_variables(variables: dict, t: Template):
1755
+ """
1756
+ >>> preprocess_variables({"test": "1,2"}, Template("select * from table where f = {{Array(test, 'String')}}"))
1757
+ {'test': ['1', '2']}
1758
+ >>> preprocess_variables({"test": ['1', '2']}, Template("select * from table where f = {{Array(test, 'String')}}"))
1759
+ {'test': ['1', '2']}
1760
+ >>> preprocess_variables({"test": [1,2]}, Template("select * from table where f = {{Array(test, 'String')}}"))
1761
+ {'test': ['1', '2']}
1762
+ >>> preprocess_variables({"test": '24'}, Template("select * from table where f = {{Int32(test)}}"))
1763
+ {}
1764
+ >>> preprocess_variables({"test": "1,2,3"}, Template("select * from table where f = {{Array(test,'Int32')}}"))
1765
+ {'test': [1, 2, 3]}
1766
+ >>> preprocess_variables({"test": "1,2,msg"}, Template("select * from table where f = {{Array(test,'Int32')}}"))
1767
+ {}
1768
+ """
1769
+ template_variables = get_var_names_and_types_cached(t)
1770
+ processed_variables = {}
1771
+ for variable, value in variables.items():
1772
+ try:
1773
+ template_vars = [t_var for t_var in template_variables if t_var["name"] == variable] or None
1774
+ if template_vars is None or value is None:
1775
+ continue
1776
+
1777
+ t_var = template_vars[0]
1778
+ var_type = t_var.get("type")
1779
+ if var_type is None:
1780
+ continue
1781
+
1782
+ # For now, we only preprocess Array types
1783
+ match = re.match(r"Array\((\w+)\)", var_type)
1784
+ if match is None:
1785
+ continue
1786
+
1787
+ array_type = match.group(1)
1788
+ array_fn = type_fns.get("Array")
1789
+ parsed_exp = array_fn(value, array_type)
1790
+ processed_variables[variable] = ast.literal_eval(parsed_exp)
1791
+ except Exception:
1792
+ continue
1793
+
1794
+ return processed_variables
1795
+
1796
+
1749
1797
  def render_sql_template(
1750
- sql: str, variables: Optional[dict] = None, test_mode: bool = False, name: Optional[str] = None
1798
+ sql: str,
1799
+ variables: Optional[dict] = None,
1800
+ test_mode: bool = False,
1801
+ name: Optional[str] = None,
1802
+ preprocess_variables_flag: bool = False,
1751
1803
  ) -> Tuple[str, dict]:
1752
1804
  """
1753
1805
  >>> render_sql_template("select * from table where f = {{Float32(foo)}}", { 'foo': -1 })
@@ -1934,10 +1986,28 @@ def render_sql_template(
1934
1986
  Traceback (most recent call last):
1935
1987
  ...
1936
1988
  tinybird.sql_template.SQLTemplateException: Template Syntax Error: Error parsing JSON: '' - Expecting value: line 1 column 1 (char 0)
1989
+ >>> 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)
1990
+ ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
1991
+ >>> 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)
1992
+ ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
1993
+ >>> 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)
1994
+ ('% SELECT test as aa, [1,2] as test, 3 as a ', {})
1995
+ >>> 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"})
1996
+ ("% SELECT test as aa, ['1','2'] as test, '1,,,2' as a ", {})
1997
+ >>> 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"]})
1998
+ ("% SELECT test as aa, ['1','2'] as test, '1,2' as a ", {})
1999
+ >>> 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"})
2000
+ Traceback (most recent call last):
2001
+ ...
2002
+ ValueError: unsupported operand type(s) for +: 'int' and 'str'
1937
2003
  """
1938
2004
 
1939
2005
  t, template_variables = get_template_and_variables(sql, name)
1940
2006
 
2007
+ if preprocess_variables_flag and variables is not None:
2008
+ processed_variables = preprocess_variables(variables, t)
2009
+ variables.update(processed_variables)
2010
+
1941
2011
  if test_mode:
1942
2012
 
1943
2013
  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("connection_id")
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, connection_id: str, force: bool) -> None:
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(connection_id)
410
+ await client.connector_delete(connection_id_or_name)
411
411
  except DoesNotExistException:
412
- raise CLIConnectionException(FeedbackManager.error_connection_does_not_exists(connection_id=connection_id))
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=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
- s3_access_policy = await client.get_s3_access_policy()
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.8.2.dev1
3
+ Version: 3.8.2.dev2
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,25 @@ 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
 
21
+ 3.8.2.dev2
22
+ ************
23
+
24
+ - `Added` New `--policy` option for `create s3_iamrole` command that will generate different hints depending on the case
25
+
26
+ 3.8.2.dev1
27
+ ************
28
+
29
+ - `Added` Support for connection names when doing `tb connection rm`
30
+
22
31
  3.8.1
23
32
  ************
24
33
 
25
34
  - `Fixed` Avoid system vars evaluation when doing `tb fmt`
26
35
  - `Fixed` environment variables substitution for Data Source engine parameters.
27
36
 
37
+
28
38
  3.8.0
29
39
  ************
30
40