tinybird-cli 5.1.1.dev1__tar.gz → 5.1.1.dev3__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.1.1.dev1 → tinybird-cli-5.1.1.dev3}/PKG-INFO +11 -1
  2. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/__cli__.py +2 -2
  3. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/feedback_manager.py +10 -1
  4. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/sql_template.py +38 -27
  5. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/pipe.py +87 -2
  6. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/workspace.py +1 -1
  7. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird_cli.egg-info/PKG-INFO +11 -1
  8. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/setup.cfg +0 -0
  9. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/ch_utils/constants.py +0 -0
  10. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/ch_utils/engine.py +0 -0
  11. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/check_pypi.py +0 -0
  12. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/client.py +0 -0
  13. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/config.py +0 -0
  14. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/connectors.py +0 -0
  15. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/context.py +0 -0
  16. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/datafile.py +0 -0
  17. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/datatypes.py +0 -0
  18. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/git_settings.py +0 -0
  19. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/sql.py +0 -0
  20. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/sql_template_fmt.py +0 -0
  21. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/sql_toolset.py +0 -0
  22. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/syncasync.py +0 -0
  23. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli.py +0 -0
  24. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/auth.py +0 -0
  25. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/branch.py +0 -0
  26. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/cicd.py +0 -0
  27. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/cli.py +0 -0
  28. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/common.py +0 -0
  29. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/config.py +0 -0
  30. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/connection.py +0 -0
  31. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/datasource.py +0 -0
  32. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/exceptions.py +0 -0
  33. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/job.py +0 -0
  34. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/regions.py +0 -0
  35. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/telemetry.py +0 -0
  36. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/test.py +0 -0
  37. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  38. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  39. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/token.py +0 -0
  40. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  41. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird/tornado_template.py +0 -0
  42. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird_cli.egg-info/SOURCES.txt +0 -0
  43. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird_cli.egg-info/dependency_links.txt +0 -0
  44. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird_cli.egg-info/entry_points.txt +0 -0
  45. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/tinybird_cli.egg-info/requires.txt +0 -0
  46. {tinybird-cli-5.1.1.dev1 → tinybird-cli-5.1.1.dev3}/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.1.1.dev1
3
+ Version: 5.1.1.dev3
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,6 +18,16 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
+ 5.1.1.dev3
22
+ ***********
23
+
24
+ - `Improved` No need for `--node` param in `tb pipe populate`
25
+
26
+ 5.1.1.dev2
27
+ ************
28
+
29
+ - `Added` `tb pipe unlink` command
30
+
21
31
  5.1.1.dev1
22
32
  ***********
23
33
 
@@ -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.1.1.dev1'
8
- __revision__ = '2922d6f'
7
+ __version__ = '5.1.1.dev3'
8
+ __revision__ = '7908f0f'
@@ -357,6 +357,12 @@ class FeedbackManager:
357
357
  error_number_of_fixed_params_and_resources_mismatch = error_message(
358
358
  "The number of --fixed-params options must not exceed the number of --scope and --resource options."
359
359
  )
360
+ error_pipe_not_materialized = error_message("Pipe {pipe} is not materialized.")
361
+ error_populate_no_materialized_in_pipe = error_message("No materialized nodes in pipe {pipe}. Use --node param.")
362
+ error_populate_several_materialized_in_pipe = error_message(
363
+ "Several materialized nodes in pipe {pipe}. Use --node param."
364
+ )
365
+ error_unlinking_pipe_not_linked = error_message("** {pipe} is not linked (MV, Copy, or Sink).")
360
366
 
361
367
  info_incl_relative_path = info_message("** Relative path {path} does not exist, skipping.")
362
368
  info_ignoring_incl_file = info_message(
@@ -670,7 +676,9 @@ Ready? """
670
676
  info_materialized_datasource_used = info_message(
671
677
  "** Materialized pipe '{pipe}' using the Data Source '{datasource}'"
672
678
  )
673
- info_materialized_unlinking_pipe = info_message("** Unlinking materialized pipe {pipe}")
679
+ info_unlinking_materialized_pipe = info_message("** Unlinking materialized pipe {pipe}")
680
+ info_unlinking_copy_pipe = info_message("** Unlinking copy pipe {pipe}")
681
+ info_unlinking_sink_pipe = info_message("** Unlinking sink pipe {pipe}")
674
682
  info_materialized_unlinking_pipe_not_found = info_message("** {pipe} not found")
675
683
  info_materialized_dry_unlinking_pipe = info_message("** [DRY RUN] Unlinking materialized pipe {pipe}")
676
684
  info_copy_datasource_created = info_message("** Copy pipe '{pipe}' created the Data Source '{datasource}'")
@@ -839,6 +847,7 @@ Ready? """
839
847
  ** Pipe URL: {host}/v0/pipes/{pipe}
840
848
  """
841
849
  )
850
+ success_pipe_unlinked = success_message("""** Pipe {pipe} unlinked""")
842
851
  success_node_copy = success_message(
843
852
  """** Node set to be used to copy data!
844
853
  ** Pipe URL: {host}/v0/pipes/{pipe}
@@ -7,7 +7,7 @@ from datetime import datetime
7
7
  from functools import lru_cache
8
8
  from io import StringIO
9
9
  from json import loads
10
- from typing import Any, Dict, List, Optional, Tuple, Union
10
+ from typing import Any, List, Optional, Tuple, Union
11
11
 
12
12
  from tornado import escape
13
13
  from tornado.util import ObjectDict, exec_in, unicode_type
@@ -33,15 +33,19 @@ def is_secret_template_key(key: str) -> bool:
33
33
  class TemplateExecutionResults(dict):
34
34
  def __init__(self, *args, **kwargs):
35
35
  super(TemplateExecutionResults, self).__init__(*args, **kwargs)
36
+ self.template_params = set()
37
+ self.ch_params = set()
36
38
 
37
- def subdict(self, key: str) -> Dict[str, Any]:
38
- return {k: v for k, v in self.items() if k.startswith(key)}
39
+ def add_template_param(self, param: str):
40
+ self.template_params.add(param)
39
41
 
40
- def get_params(self) -> Dict[str, Any]:
41
- return self.subdict(CH_PARAM_PREFIX)
42
+ def add_ch_param(self, param: str):
43
+ self.ch_params.add(param)
42
44
 
43
- def get_params_keys(self) -> List[str]:
44
- return [key.split(CH_PARAM_PREFIX)[-1] for key in list(self.get_params().keys())]
45
+ def update_all(self, other: "TemplateExecutionResults"):
46
+ self.update(other)
47
+ self.ch_params.update(other.ch_params)
48
+ self.template_params.update(other.template_params)
45
49
 
46
50
 
47
51
  class SQLTemplateCustomError(Exception):
@@ -1363,25 +1367,30 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
1363
1367
  """Generate this template with the given arguments."""
1364
1368
  namespace = {}
1365
1369
  template_execution_results = TemplateExecutionResults()
1366
- for key in kwargs:
1370
+ for key in kwargs.get("tb_secrets", []):
1367
1371
  if is_secret_template_key(key):
1368
- template_execution_results[key] = kwargs[key]
1372
+ template_execution_results.add_template_param(key)
1373
+ if TB_SECRET_IN_TEST_MODE in kwargs:
1374
+ template_execution_results[TB_SECRET_IN_TEST_MODE] = None
1369
1375
 
1370
1376
  def set_tb_secret(x):
1371
1377
  try:
1372
1378
  key = secret_template_key(x)
1373
- if key in template_execution_results:
1374
- val = template_execution_results[key]
1375
- template_execution_results[f"{CH_PARAM_PREFIX}{x}"] = val
1379
+ if key in template_execution_results.template_params:
1380
+ template_execution_results.add_ch_param(x)
1376
1381
  return Symbol("{" + sqlescape(x) + ": String}")
1377
1382
  else:
1378
1383
  is_test_mode = TB_SECRET_IN_TEST_MODE in template_execution_results
1379
1384
  if is_test_mode:
1380
1385
  return Symbol("{" + sqlescape(x) + ": String}")
1381
1386
  else:
1382
- raise SQLTemplateException(f"Secret '{x}' does not exist in Workspace")
1387
+ raise SQLTemplateException(
1388
+ f"Cannot access secret '{x}'. Check the secret exists in the Workspace and the token has the required scope."
1389
+ )
1383
1390
  except Exception:
1384
- raise SQLTemplateException(f"Secret '{x}' does not exist in Workspace")
1391
+ raise SQLTemplateException(
1392
+ f"Cannot access secret '{x}'. Check the secret exists in the Workspace and the token has the required scope."
1393
+ )
1385
1394
 
1386
1395
  def set_max_threads(x):
1387
1396
  try:
@@ -1902,7 +1911,7 @@ def preprocess_variables(variables: dict, t: Template):
1902
1911
  def render_sql_template(
1903
1912
  sql: str,
1904
1913
  variables: Optional[dict] = None,
1905
- secrets: Optional[dict] = None,
1914
+ secrets: Optional[List[str]] = None,
1906
1915
  test_mode: bool = False,
1907
1916
  name: Optional[str] = None,
1908
1917
  ) -> Tuple[str, TemplateExecutionResults, list]:
@@ -2105,20 +2114,20 @@ def render_sql_template(
2105
2114
  tinybird.tornado_template.UnClosedIfError: Missing {% end %} block for if at line 1
2106
2115
  >>> render_sql_template("select * from table where str = {{pipeline}}", { 'pipeline': 'test' })
2107
2116
  ("select * from table where str = 'test'", {}, ['pipeline'])
2108
- >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = { 'tb_secret_test': '1234' })
2109
- ('select * from table where str = {test: String}', {'param_test': '1234'}, [])
2117
+ >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = [ 'tb_secret_test' ])
2118
+ ('select * from table where str = {test: String}', {}, [])
2110
2119
  >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", variables = { 'test': '1234' })
2111
2120
  Traceback (most recent call last):
2112
2121
  ...
2113
- tinybird.sql_template.SQLTemplateException: Template Syntax Error: Secret 'test' does not exist in Workspace
2122
+ tinybird.sql_template.SQLTemplateException: Template Syntax Error: Cannot access secret 'test'. Check the secret exists in the Workspace and the token has the required scope.
2114
2123
  >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", test_mode=True)
2115
2124
  ('select * from table where str = {test: String}', {}, [])
2116
- >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = { 'tb_secret_test': '1234' }, test_mode=True)
2117
- ('select * from table where str = {test: String}', {'param_test': '1234'}, [])
2118
- >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = { 'tb_secret_test2': '1234' })
2125
+ >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = [ 'tb_secret_test' ], test_mode=True)
2126
+ ('select * from table where str = {test: String}', {}, [])
2127
+ >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = [ 'tb_secret_test2' ])
2119
2128
  Traceback (most recent call last):
2120
2129
  ...
2121
- tinybird.sql_template.SQLTemplateException: Template Syntax Error: Secret 'test' does not exist in Workspace
2130
+ tinybird.sql_template.SQLTemplateException: Template Syntax Error: Cannot access secret 'test'. Check the secret exists in the Workspace and the token has the required scope.
2122
2131
  """
2123
2132
  escape_split_to_array = ff_split_to_array_escape.get(False)
2124
2133
  bypass_preprocess_variables = ff_preprocess_parameters_circuit_breaker.get(False)
@@ -2143,7 +2152,7 @@ def render_sql_template(
2143
2152
  v.update(variables)
2144
2153
 
2145
2154
  if secrets:
2146
- v.update(secrets)
2155
+ v.update({"tb_secrets": secrets})
2147
2156
 
2148
2157
  if is_tb_secret:
2149
2158
  v.update({TB_SECRET_IN_TEST_MODE: None})
@@ -2163,14 +2172,16 @@ def render_sql_template(
2163
2172
  v.update(variables)
2164
2173
 
2165
2174
  if secrets:
2166
- v.update(secrets)
2175
+ v.update({"tb_secrets": secrets})
2167
2176
  v.update(type_fns)
2168
2177
 
2169
2178
  try:
2170
2179
  sql, template_execution_results = generate(t, **v)
2171
- for key in list(template_execution_results.keys()):
2172
- if is_secret_template_key(key) and key in template_execution_results:
2173
- del template_execution_results[key]
2180
+ try:
2181
+ if TB_SECRET_IN_TEST_MODE in template_execution_results:
2182
+ del template_execution_results[TB_SECRET_IN_TEST_MODE]
2183
+ except Exception:
2184
+ pass
2174
2185
  return sql, template_execution_results, variable_warnings
2175
2186
  except NameError as e:
2176
2187
  raise SQLTemplateException(e, documentation="/cli/advanced-templates.html#defined")
@@ -16,7 +16,7 @@ from click import Context
16
16
  import tinybird.context as context
17
17
  from tinybird.client import DoesNotExistException, TinyB
18
18
  from tinybird.config import DEFAULT_API_HOST, FeatureFlags
19
- from tinybird.datafile import folder_push, get_name_version, process_file, wait_job
19
+ from tinybird.datafile import PipeTypes, folder_push, get_name_version, process_file, wait_job
20
20
  from tinybird.feedback_manager import FeedbackManager
21
21
  from tinybird.tb_cli_modules.branch import warn_if_in_live
22
22
  from tinybird.tb_cli_modules.cli import cli
@@ -212,7 +212,7 @@ async def pipe_ls(ctx: Context, match: str, format_: str):
212
212
 
213
213
  @pipe.command(name="populate")
214
214
  @click.argument("pipe_name")
215
- @click.option("--node", type=str, help="Name of the materialized node.", required=True)
215
+ @click.option("--node", type=str, help="Name of the materialized node.", default=None, required=False)
216
216
  @click.option(
217
217
  "--sql-condition",
218
218
  type=str,
@@ -247,6 +247,23 @@ async def pipe_populate(
247
247
  ):
248
248
  """Populate the result of a Materialized Node into the target Materialized View"""
249
249
  cl = create_tb_client(ctx)
250
+
251
+ pipe = await cl.pipe(pipe_name)
252
+
253
+ if pipe["type"] != PipeTypes.MATERIALIZED:
254
+ raise CLIPipeException(FeedbackManager.error_pipe_not_materialized(pipe=pipe_name))
255
+
256
+ if not node:
257
+ materialized_ids = [pipe_node["id"] for pipe_node in pipe["nodes"] if pipe_node.get("materialized") is not None]
258
+
259
+ if not materialized_ids:
260
+ raise CLIPipeException(FeedbackManager.error_populate_no_materialized_in_pipe(pipe=pipe_name))
261
+
262
+ elif len(materialized_ids) > 1:
263
+ raise CLIPipeException(FeedbackManager.error_populate_several_materialized_in_pipe(pipe=pipe_name))
264
+
265
+ node = materialized_ids[0]
266
+
250
267
  response = await cl.populate_node(
251
268
  pipe_name,
252
269
  node,
@@ -267,6 +284,74 @@ async def pipe_populate(
267
284
  await wait_job(cl, job_id, job_url, "Populating")
268
285
 
269
286
 
287
+ @pipe.command(name="unlink")
288
+ @click.argument("pipe_name_or_id")
289
+ @click.argument("node_uid", default=None, required=False)
290
+ @click.pass_context
291
+ @coro
292
+ async def pipe_unlink_output_node(
293
+ ctx: click.Context,
294
+ pipe_name_or_id: str,
295
+ node_uid: Optional[str] = None,
296
+ ):
297
+ """Unlink the output of a pipe. Works for Materialized Views, Copy Pipes, and Sinks."""
298
+ client: TinyB = ctx.ensure_object(dict)["client"]
299
+
300
+ try:
301
+ pipe = await client.pipe(pipe_name_or_id)
302
+
303
+ if pipe["type"] not in [PipeTypes.MATERIALIZED, PipeTypes.COPY, PipeTypes.DATA_SINK]:
304
+ raise CLIPipeException(FeedbackManager.error_unlinking_pipe_not_linked(pipe=pipe_name_or_id))
305
+
306
+ if pipe["type"] == PipeTypes.MATERIALIZED:
307
+ click.echo(FeedbackManager.info_unlinking_materialized_pipe(pipe=pipe["name"]))
308
+
309
+ if not node_uid:
310
+ for node in pipe["nodes"]:
311
+ if "materialized" in node and node["materialized"] is not None:
312
+ node_uid = node["id"]
313
+ break
314
+
315
+ if not node_uid:
316
+ raise CLIPipeException(FeedbackManager.error_unlinking_pipe_not_linked(pipe=pipe_name_or_id))
317
+ else:
318
+ await client.pipe_unlink_materialized(pipe["name"], node_uid)
319
+ click.echo(FeedbackManager.success_pipe_unlinked(pipe=pipe["name"]))
320
+
321
+ if pipe["type"] == PipeTypes.COPY:
322
+ click.echo(FeedbackManager.info_unlinking_copy_pipe(pipe=pipe["name"]))
323
+
324
+ if not node_uid:
325
+ for node in pipe["nodes"]:
326
+ if node["node_type"] == "copy":
327
+ node_uid = node["id"]
328
+ break
329
+
330
+ if not node_uid:
331
+ raise CLIPipeException(FeedbackManager.error_unlinking_pipe_not_linked(pipe=pipe_name_or_id))
332
+ else:
333
+ await client.pipe_remove_copy(pipe["name"], node_uid)
334
+ click.echo(FeedbackManager.success_pipe_unlinked(pipe=pipe["name"]))
335
+
336
+ if pipe["type"] == PipeTypes.DATA_SINK:
337
+ click.echo(FeedbackManager.info_unlinking_sink_pipe(pipe=pipe["name"]))
338
+
339
+ if not node_uid:
340
+ for node in pipe["nodes"]:
341
+ if node["node_type"] == "sink":
342
+ node_uid = node["id"]
343
+ break
344
+
345
+ if not node_uid:
346
+ raise CLIPipeException(FeedbackManager.error_unlinking_pipe_not_linked(pipe=pipe_name_or_id))
347
+ else:
348
+ await client.pipe_remove_sink(pipe["name"], node_uid)
349
+ click.echo(FeedbackManager.success_pipe_unlinked(pipe=pipe["name"]))
350
+
351
+ except Exception as e:
352
+ raise CLIPipeException(FeedbackManager.error_exception(error=e))
353
+
354
+
270
355
  @pipe.command(name="append")
271
356
  @click.argument("pipe_name_or_uid")
272
357
  @click.argument("sql")
@@ -151,7 +151,7 @@ async def clear_workspace(ctx: Context, yes: bool, dry_run: bool) -> None:
151
151
  break
152
152
 
153
153
  if node_id:
154
- click.echo(FeedbackManager.info_materialized_unlinking_pipe(pipe=pipe["name"]))
154
+ click.echo(FeedbackManager.info_unlinking_materialized_pipe(pipe=pipe["name"]))
155
155
  try:
156
156
  await client.pipe_unlink_materialized(pipe["name"], node_id)
157
157
  except DoesNotExistException:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird-cli
3
- Version: 5.1.1.dev1
3
+ Version: 5.1.1.dev3
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,6 +18,16 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
+ 5.1.1.dev3
22
+ ***********
23
+
24
+ - `Improved` No need for `--node` param in `tb pipe populate`
25
+
26
+ 5.1.1.dev2
27
+ ************
28
+
29
+ - `Added` `tb pipe unlink` command
30
+
21
31
  5.1.1.dev1
22
32
  ***********
23
33