tinybird-cli 5.0.0.dev4__tar.gz → 5.0.1.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.
Files changed (46) hide show
  1. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/PKG-INFO +9 -26
  2. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/__cli__.py +2 -2
  3. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/ch_utils/constants.py +1 -0
  4. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/client.py +21 -9
  5. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/datafile.py +2 -1
  6. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/sql_toolset.py +69 -16
  7. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/workspace_members.py +8 -3
  8. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird_cli.egg-info/PKG-INFO +9 -26
  9. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/setup.cfg +0 -0
  10. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/ch_utils/engine.py +0 -0
  11. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/check_pypi.py +0 -0
  12. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/config.py +0 -0
  13. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/connectors.py +0 -0
  14. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/context.py +0 -0
  15. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/datatypes.py +0 -0
  16. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/feedback_manager.py +0 -0
  17. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/git_settings.py +0 -0
  18. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/sql.py +0 -0
  19. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/sql_template.py +0 -0
  20. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/sql_template_fmt.py +0 -0
  21. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/syncasync.py +0 -0
  22. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli.py +0 -0
  23. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
  24. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/branch.py +0 -0
  25. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/cicd.py +0 -0
  26. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/cli.py +0 -0
  27. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/common.py +0 -0
  28. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/config.py +0 -0
  29. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
  30. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/datasource.py +0 -0
  31. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
  32. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/job.py +0 -0
  33. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/pipe.py +0 -0
  34. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
  35. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
  36. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/test.py +0 -0
  37. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  38. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  39. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/token.py +0 -0
  40. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tb_cli_modules/workspace.py +0 -0
  41. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird/tornado_template.py +0 -0
  42. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird_cli.egg-info/SOURCES.txt +0 -0
  43. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird_cli.egg-info/dependency_links.txt +0 -0
  44. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird_cli.egg-info/entry_points.txt +0 -0
  45. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.dev0}/tinybird_cli.egg-info/requires.txt +0 -0
  46. {tinybird-cli-5.0.0.dev4 → tinybird-cli-5.0.1.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.0.0.dev4
3
+ Version: 5.0.1.dev0
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,37 +18,20 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
- 5.0.0.dev4
22
- ************
21
+ 5.0.0
22
+ ******
23
23
 
24
- - `Improved` help message of `tb workspace members set-role` now displays the 3 valid roles: viewer|guest|admin.
24
+ - `Breaking change` Make `insertion_date` column explicit. This column is no longer inferred, it must be present in the Data Source file.
25
25
 
26
- 5.0.0.dev3
27
- ************
26
+ Detailed info at https://www.tinybird.co/docs/changelog/2024-06-17-insertion_date-deprecation
28
27
 
28
+ - `Added` parameter to `tb pipe regression-test` --relative-change
29
+ - `Added` `tb push` displays warnings when using a reserved parameter in a pipe.
30
+ - `Added` --role parameter to `tb workspace members add`
29
31
  - `Changed` Point region hosts to new `app.tinybird.co` domain
30
-
31
- 5.0.0.dev2
32
- ************
33
-
32
+ - `Improved` help message of `tb workspace members set-role` now displays the 3 valid roles: viewer|guest|admin.
34
33
  - `Improved` syntax error messages when parsing endpoints.
35
34
 
36
- 5.0.0.dev1
37
- ************
38
-
39
- - `Added` `tb push` displays warnings when using a reserved parameter in a pipe.
40
-
41
- 5.0.0.dev0
42
- ************
43
-
44
- - `Changed` Make `insertion_date` column explicit. This column is no longer inferred, it must be present in the Data Source file.
45
-
46
- 4.1.2.dev0
47
- ************
48
-
49
- - `Added` parameter to `tb pipe regression-test` --relative-change
50
-
51
-
52
35
  4.1.1
53
36
  ************
54
37
 
@@ -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.0.0.dev4'
8
- __revision__ = 'e41eaa1'
7
+ __version__ = '5.0.1.dev0'
8
+ __revision__ = '2af0ad5'
@@ -4,6 +4,7 @@ LIVE_WS_NAME = "live"
4
4
  SNAPSHOT_WS_NAME = "snapshot"
5
5
 
6
6
  ENABLED_TABLE_FUNCTIONS = {"generateRandom", "null", "numbers", "numbers_mt", "values", "zeros", "zeros_mt"}
7
+ COPY_ENABLED_TABLE_FUNCTIONS = frozenset(["postgresql"])
7
8
 
8
9
  ENABLED_SYSTEM_TABLES = {
9
10
  "functions",
@@ -11,6 +11,7 @@ import requests.adapters
11
11
  from requests import Response
12
12
  from urllib3 import Retry
13
13
 
14
+ from tinybird.ch_utils.constants import COPY_ENABLED_TABLE_FUNCTIONS
14
15
  from tinybird.syncasync import sync_to_async
15
16
  from tinybird.tb_cli_modules.regions import fill_with_public_regions
16
17
  from tinybird.tb_cli_modules.telemetry import add_telemetry_event
@@ -749,10 +750,12 @@ class TinyB(object):
749
750
  async def delete_branch(self, id: str):
750
751
  return await self._req(f"/v0/environments/{id}", method="DELETE")
751
752
 
752
- async def add_users_to_workspace(self, workspace: Dict[str, Any], users_emails: List[str]):
753
+ async def add_users_to_workspace(self, workspace: Dict[str, Any], users_emails: List[str], role: Optional[str]):
753
754
  users = ",".join(users_emails)
754
755
  return await self._req(
755
- f"/v0/workspaces/{workspace['id']}/users/", method="PUT", data={"operation": "add", "users": users}
756
+ f"/v0/workspaces/{workspace['id']}/users/",
757
+ method="PUT",
758
+ data={"operation": "add", "users": users, "role": role},
756
759
  )
757
760
 
758
761
  async def remove_users_from_workspace(self, workspace: Dict[str, Any], users_emails: List[str]):
@@ -1033,23 +1036,32 @@ class TinyB(object):
1033
1036
  return result["q"]
1034
1037
 
1035
1038
  @staticmethod
1036
- def _sql_get_used_tables_local(sql: str, raising: bool = False) -> List[str]:
1039
+ def _sql_get_used_tables_local(sql: str, raising: bool = False, is_copy: Optional[bool] = False) -> List[str]:
1037
1040
  from tinybird.sql_toolset import sql_get_used_tables
1038
1041
 
1039
- tables = sql_get_used_tables(sql, raising, table_functions=False)
1042
+ tables = sql_get_used_tables(
1043
+ sql, raising, table_functions=False, function_allow_list=COPY_ENABLED_TABLE_FUNCTIONS if is_copy else None
1044
+ )
1040
1045
  return [t[1] if t[0] == "" else f"{t[0]}.{t[1]}" for t in tables]
1041
1046
 
1042
- async def _sql_get_used_tables_remote(self, sql: str, raising: bool = False) -> List[str]:
1043
- params = {"q": sql, "raising": "true" if raising else "false", "table_functions": "false"}
1047
+ async def _sql_get_used_tables_remote(
1048
+ self, sql: str, raising: bool = False, is_copy: Optional[bool] = False
1049
+ ) -> List[str]:
1050
+ params = {
1051
+ "q": sql,
1052
+ "raising": "true" if raising else "false",
1053
+ "table_functions": "false",
1054
+ "is_copy": "true" if is_copy else "false",
1055
+ }
1044
1056
  result = await self._req("/v0/sql_tables", data=params, method="POST")
1045
1057
  return [t[1] if t[0] == "" else f"{t[0]}.{t[1]}" for t in result["tables"]]
1046
1058
 
1047
1059
  # Get used tables from a query. Does not include table functions
1048
- async def sql_get_used_tables(self, sql: str, raising: bool = False) -> List[str]:
1060
+ async def sql_get_used_tables(self, sql: str, raising: bool = False, is_copy: Optional[bool] = False) -> List[str]:
1049
1061
  try:
1050
- return self._sql_get_used_tables_local(sql, raising)
1062
+ return self._sql_get_used_tables_local(sql, raising, is_copy)
1051
1063
  except ModuleNotFoundError:
1052
- return await self._sql_get_used_tables_remote(sql, raising)
1064
+ return await self._sql_get_used_tables_remote(sql, raising, is_copy)
1053
1065
 
1054
1066
  @staticmethod
1055
1067
  def _replace_tables_local(q: str, replacements):
@@ -1476,6 +1476,7 @@ async def process_file(
1476
1476
  deps = []
1477
1477
  nodes: List[Dict[str, Any]] = []
1478
1478
 
1479
+ is_copy = any([node for node in doc.nodes if node.get("type", "standard").lower() == PipeNodeTypes.COPY])
1479
1480
  for node in doc.nodes:
1480
1481
  sql = node["sql"]
1481
1482
  node_type = node.get("type", "standard").lower()
@@ -1504,7 +1505,7 @@ async def process_file(
1504
1505
  sql_rendered = sql
1505
1506
 
1506
1507
  try:
1507
- dependencies = await tb_client.sql_get_used_tables(sql_rendered, raising=True)
1508
+ dependencies = await tb_client.sql_get_used_tables(sql_rendered, raising=True, is_copy=is_copy)
1508
1509
  deps += [t for t in dependencies if t not in [n["name"] for n in doc.nodes]]
1509
1510
 
1510
1511
  except Exception as e:
@@ -3,20 +3,26 @@ import logging
3
3
  from collections import defaultdict
4
4
  from datetime import datetime
5
5
  from functools import lru_cache
6
- from typing import Any, List, Optional, Set, Tuple
6
+ from typing import Any, FrozenSet, List, Optional, Set, Tuple
7
7
 
8
8
  from chtoolset import query as chquery
9
9
  from toposort import toposort
10
10
 
11
- from tinybird.ch_utils.constants import ENABLED_TABLE_FUNCTIONS
11
+ from tinybird.ch_utils.constants import COPY_ENABLED_TABLE_FUNCTIONS, ENABLED_TABLE_FUNCTIONS
12
12
 
13
13
  VALID_REMOTE = "VALID_REMOTE"
14
14
 
15
15
 
16
16
  class InvalidFunction(ValueError):
17
17
  def __init__(self, msg: str = "", table_function_names: str = ""):
18
+ if any([fn for fn in COPY_ENABLED_TABLE_FUNCTIONS if fn in msg]):
19
+ msg = msg.replace("is restricted", "is restricted to Copy Pipes")
20
+
18
21
  if table_function_names:
19
- self.msg = f"The query uses disabled table functions: '{table_function_names}'"
22
+ if "postgresql" in table_function_names:
23
+ self.msg = "The postgresql table function is only allowed in Copy Pipes"
24
+ else:
25
+ self.msg = f"The query uses disabled table functions: '{table_function_names}'"
20
26
  else:
21
27
  self.msg = msg
22
28
  super().__init__(self.msg)
@@ -58,7 +64,11 @@ def format_where_for_mutation_command(where_clause: str) -> str:
58
64
 
59
65
  @lru_cache(maxsize=2**13)
60
66
  def sql_get_used_tables_cached(
61
- sql: str, raising: bool = False, default_database: str = "", table_functions: bool = True
67
+ sql: str,
68
+ raising: bool = False,
69
+ default_database: str = "",
70
+ table_functions: bool = True,
71
+ function_allow_list: Optional[FrozenSet[str]] = None,
62
72
  ) -> List[Tuple[str, str, str]]:
63
73
  """
64
74
  >>> sql_get_used_tables("SELECT 1 FROM the_table")
@@ -79,7 +89,11 @@ def sql_get_used_tables_cached(
79
89
  [('d_d3926a', 't_976af08ec4b547419e729c63e754b17b', '')]
80
90
  """
81
91
  try:
82
- tables: List[Tuple[str, str, str]] = chquery.tables(sql, default_database=default_database)
92
+ _function_allow_list = list() if function_allow_list is None else list(function_allow_list)
93
+
94
+ tables: List[Tuple[str, str, str]] = chquery.tables(
95
+ sql, default_database=default_database, function_allow_list=_function_allow_list
96
+ )
83
97
  if not table_functions:
84
98
  return [(t[0], t[1], "") for t in tables if t[0] or t[1]]
85
99
  return tables
@@ -93,10 +107,17 @@ def sql_get_used_tables_cached(
93
107
 
94
108
 
95
109
  def sql_get_used_tables(
96
- sql: str, raising: bool = False, default_database: str = "", table_functions: bool = True
110
+ sql: str,
111
+ raising: bool = False,
112
+ default_database: str = "",
113
+ table_functions: bool = True,
114
+ function_allow_list: Optional[FrozenSet[str]] = None,
97
115
  ) -> List[Tuple[str, str, str]]:
98
- # We return a copy here since the callers might (and replace_tables does) edit the resulting object
99
- return copy.copy(sql_get_used_tables_cached(sql, raising, default_database, table_functions))
116
+ hashable_list = frozenset() if function_allow_list is None else function_allow_list
117
+
118
+ return copy.copy(
119
+ sql_get_used_tables_cached(sql, raising, default_database, table_functions, function_allow_list=hashable_list)
120
+ )
100
121
 
101
122
 
102
123
  class ReplacementsDict(dict):
@@ -150,9 +171,18 @@ def replace_tables_chquery_cached(
150
171
  default_database: str = "",
151
172
  output_one_line: bool = False,
152
173
  timestamp: Optional[datetime] = None,
174
+ function_allow_list: Optional[FrozenSet[str]] = None,
153
175
  ) -> str:
154
176
  replacements = dict(sorted_replacements) if sorted_replacements else {}
155
- return chquery.replace_tables(sql, replacements, default_database=default_database, one_line=output_one_line)
177
+ _function_allow_list = list() if function_allow_list is None else list(function_allow_list)
178
+
179
+ return chquery.replace_tables(
180
+ sql,
181
+ replacements,
182
+ default_database=default_database,
183
+ one_line=output_one_line,
184
+ function_allow_list=_function_allow_list,
185
+ )
156
186
 
157
187
 
158
188
  def replace_tables(
@@ -164,15 +194,19 @@ def replace_tables(
164
194
  valid_tables: Optional[Set[Tuple[str, str]]] = None,
165
195
  output_one_line: bool = False,
166
196
  timestamp: Optional[datetime] = None,
197
+ function_allow_list: Optional[FrozenSet[str]] = None,
167
198
  ) -> str:
168
199
  """
169
200
  Given a query and a list of table replacements, returns the query after applying the table replacements.
170
201
  It takes into account dependencies between replacement subqueries (if any)
171
202
  It also validates the sql to verify it's valid and doesn't use unknown or prohibited functions
172
203
  """
204
+ hashable_list = frozenset() if function_allow_list is None else function_allow_list
173
205
  if not replacements:
174
206
  # Always call replace_tables to do validation and formatting
175
- return replace_tables_chquery_cached(sql, None, output_one_line=output_one_line, timestamp=timestamp)
207
+ return replace_tables_chquery_cached(
208
+ sql, None, output_one_line=output_one_line, timestamp=timestamp, function_allow_list=hashable_list
209
+ )
176
210
 
177
211
  _replaced_with = set()
178
212
  _replacements = ReplacementsDict()
@@ -182,14 +216,24 @@ def replace_tables(
182
216
  _replaced_with.add(r)
183
217
 
184
218
  deps: defaultdict = defaultdict(set)
185
- _tables = sql_get_used_tables(sql, default_database=default_database, raising=True, table_functions=check_functions)
219
+ _tables = sql_get_used_tables(
220
+ sql,
221
+ default_database=default_database,
222
+ raising=True,
223
+ table_functions=check_functions,
224
+ function_allow_list=function_allow_list,
225
+ )
186
226
  seen_tables = set()
187
227
  table: Tuple[str, str] | Tuple[str, str, str]
228
+ if function_allow_list is None:
229
+ _enabled_table_functions = ENABLED_TABLE_FUNCTIONS
230
+ else:
231
+ _enabled_table_functions = ENABLED_TABLE_FUNCTIONS.union(set(function_allow_list))
188
232
  while _tables:
189
233
  table = _tables.pop()
190
234
  if len(table) == 3:
191
235
  first_table, second_table, last_table = table
192
- if last_table and last_table not in ENABLED_TABLE_FUNCTIONS:
236
+ if last_table and last_table not in _enabled_table_functions:
193
237
  raise InvalidFunction(table_function_names=last_table)
194
238
  if first_table or second_table:
195
239
  table = (first_table, second_table)
@@ -204,7 +248,7 @@ def replace_tables(
204
248
  if len(dependent_table) == 3:
205
249
  if (
206
250
  dependent_table[2]
207
- and dependent_table[2] not in ENABLED_TABLE_FUNCTIONS
251
+ and dependent_table[2] not in _enabled_table_functions
208
252
  and not (dependent_table[2] in ["cluster"] and replacement[0] == VALID_REMOTE)
209
253
  ):
210
254
  raise InvalidFunction(table_function_names=dependent_table[2])
@@ -219,7 +263,9 @@ def replace_tables(
219
263
  deps_sorted = list(reversed(list(toposort(deps))))
220
264
 
221
265
  if not deps_sorted:
222
- return replace_tables_chquery_cached(sql, None, output_one_line=output_one_line, timestamp=timestamp)
266
+ return replace_tables_chquery_cached(
267
+ sql, None, output_one_line=output_one_line, timestamp=timestamp, function_allow_list=hashable_list
268
+ )
223
269
 
224
270
  for current_deps in deps_sorted:
225
271
  current_replacements = {}
@@ -251,10 +297,17 @@ def replace_tables(
251
297
  # We need to transform the dictionary into something cacheable, so a sorted tuple of tuples it is
252
298
  r = tuple(sorted([(k, v) for k, v in current_replacements.items()]))
253
299
  sql = replace_tables_chquery_cached(
254
- sql, r, default_database=default_database, output_one_line=output_one_line, timestamp=timestamp
300
+ sql,
301
+ r,
302
+ default_database=default_database,
303
+ output_one_line=output_one_line,
304
+ timestamp=timestamp,
305
+ function_allow_list=hashable_list,
255
306
  )
256
307
  else:
257
- sql = replace_tables_chquery_cached(sql, None, output_one_line=output_one_line, timestamp=timestamp)
308
+ sql = replace_tables_chquery_cached(
309
+ sql, None, output_one_line=output_one_line, timestamp=timestamp, function_allow_list=hashable_list
310
+ )
258
311
 
259
312
  return sql
260
313
 
@@ -22,6 +22,8 @@ from tinybird.tb_cli_modules.common import (
22
22
  from tinybird.tb_cli_modules.exceptions import CLIWorkspaceMembersException
23
23
  from tinybird.tb_cli_modules.workspace import workspace
24
24
 
25
+ ROLES = ["viewer", "guest", "admin"]
26
+
25
27
 
26
28
  @dataclass
27
29
  class WorkspaceMemberCommandContext:
@@ -55,10 +57,13 @@ def members(ctx: Context) -> None:
55
57
 
56
58
  @members.command(name="add", short_help="Adds members to the current Workspace")
57
59
  @click.argument("members_emails")
60
+ @click.option("--role", is_flag=False, default=None, help="Role for the members being added", type=click.Choice(ROLES))
58
61
  @click.option("--user_token", is_flag=False, default=None, help="When passed, we won't prompt asking for it")
59
62
  @click.pass_context
60
63
  @coro
61
- async def add_members_to_workspace(ctx: Context, members_emails: str, user_token: Optional[str]) -> None:
64
+ async def add_members_to_workspace(
65
+ ctx: Context, members_emails: str, user_token: Optional[str], role: Optional[str]
66
+ ) -> None:
62
67
  """Adds members to the current Workspace."""
63
68
 
64
69
  cmd_ctx = await get_command_context(ctx)
@@ -79,7 +84,7 @@ async def add_members_to_workspace(ctx: Context, members_emails: str, user_token
79
84
 
80
85
  user_client: TinyB = deepcopy(cmd_ctx.client)
81
86
  user_client.token = user_token
82
- await user_client.add_users_to_workspace(cmd_ctx.workspace, users_to_add)
87
+ await user_client.add_users_to_workspace(cmd_ctx.workspace, users_to_add, role)
83
88
  msg = (
84
89
  FeedbackManager.success_workspace_user_added(user=users_to_add[0], workspace_name=cmd_ctx.workspace["name"])
85
90
  if len(users_to_add) == 1
@@ -149,7 +154,7 @@ async def remove_members_from_workspace(ctx: Context, members_emails: str, user_
149
154
 
150
155
 
151
156
  @members.command(name="set-role", short_help="Sets the role for existing workspace members")
152
- @click.argument("role", required=True, type=click.Choice(["viewer", "guest", "admin"]))
157
+ @click.argument("role", required=True, type=click.Choice(ROLES))
153
158
  @click.argument("members_emails", required=True, type=str)
154
159
  @click.option("--user_token", is_flag=False, default=None, help="When passed, we won't prompt asking for it")
155
160
  @click.pass_context
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird-cli
3
- Version: 5.0.0.dev4
3
+ Version: 5.0.1.dev0
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,37 +18,20 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
- 5.0.0.dev4
22
- ************
21
+ 5.0.0
22
+ ******
23
23
 
24
- - `Improved` help message of `tb workspace members set-role` now displays the 3 valid roles: viewer|guest|admin.
24
+ - `Breaking change` Make `insertion_date` column explicit. This column is no longer inferred, it must be present in the Data Source file.
25
25
 
26
- 5.0.0.dev3
27
- ************
26
+ Detailed info at https://www.tinybird.co/docs/changelog/2024-06-17-insertion_date-deprecation
28
27
 
28
+ - `Added` parameter to `tb pipe regression-test` --relative-change
29
+ - `Added` `tb push` displays warnings when using a reserved parameter in a pipe.
30
+ - `Added` --role parameter to `tb workspace members add`
29
31
  - `Changed` Point region hosts to new `app.tinybird.co` domain
30
-
31
- 5.0.0.dev2
32
- ************
33
-
32
+ - `Improved` help message of `tb workspace members set-role` now displays the 3 valid roles: viewer|guest|admin.
34
33
  - `Improved` syntax error messages when parsing endpoints.
35
34
 
36
- 5.0.0.dev1
37
- ************
38
-
39
- - `Added` `tb push` displays warnings when using a reserved parameter in a pipe.
40
-
41
- 5.0.0.dev0
42
- ************
43
-
44
- - `Changed` Make `insertion_date` column explicit. This column is no longer inferred, it must be present in the Data Source file.
45
-
46
- 4.1.2.dev0
47
- ************
48
-
49
- - `Added` parameter to `tb pipe regression-test` --relative-change
50
-
51
-
52
35
  4.1.1
53
36
  ************
54
37