tinybird-cli 5.1.1.dev2__tar.gz → 5.2.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.
Files changed (46) hide show
  1. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/PKG-INFO +5 -8
  2. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/__cli__.py +2 -2
  3. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/datatypes.py +88 -0
  4. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/feedback_manager.py +5 -0
  5. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/sql_template.py +8 -4
  6. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/pipe.py +18 -1
  7. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird_cli.egg-info/PKG-INFO +5 -8
  8. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/setup.cfg +0 -0
  9. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/ch_utils/constants.py +0 -0
  10. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/ch_utils/engine.py +0 -0
  11. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/check_pypi.py +0 -0
  12. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/client.py +0 -0
  13. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/config.py +0 -0
  14. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/connectors.py +0 -0
  15. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/context.py +0 -0
  16. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/datafile.py +0 -0
  17. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/git_settings.py +0 -0
  18. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/sql.py +0 -0
  19. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/sql_template_fmt.py +0 -0
  20. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/sql_toolset.py +0 -0
  21. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/syncasync.py +0 -0
  22. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli.py +0 -0
  23. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/auth.py +0 -0
  24. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/branch.py +0 -0
  25. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/cicd.py +0 -0
  26. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/cli.py +0 -0
  27. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/common.py +0 -0
  28. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/config.py +0 -0
  29. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/connection.py +0 -0
  30. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/datasource.py +0 -0
  31. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/exceptions.py +0 -0
  32. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/job.py +0 -0
  33. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/regions.py +0 -0
  34. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/telemetry.py +0 -0
  35. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/test.py +0 -0
  36. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  37. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  38. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/token.py +0 -0
  39. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/workspace.py +0 -0
  40. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  41. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird/tornado_template.py +0 -0
  42. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird_cli.egg-info/SOURCES.txt +0 -0
  43. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird_cli.egg-info/dependency_links.txt +0 -0
  44. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird_cli.egg-info/entry_points.txt +0 -0
  45. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.0}/tinybird_cli.egg-info/requires.txt +0 -0
  46. {tinybird-cli-5.1.1.dev2 → tinybird-cli-5.2.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: 5.1.1.dev2
3
+ Version: 5.2.0
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,15 +18,12 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
- 5.1.1.dev2
22
- ************
21
+ 5.2.0
22
+ ******
23
23
 
24
+ - `Added` internal changes
24
25
  - `Added` `tb pipe unlink` command
25
-
26
- 5.1.1.dev1
27
- ***********
28
-
29
- - `Added` internal release
26
+ - `Changed` No need for `--node` param in `tb pipe populate`
30
27
 
31
28
  5.1.0
32
29
  ******
@@ -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.dev2'
8
- __revision__ = '1417339'
7
+ __version__ = '5.2.0'
8
+ __revision__ = '83349b1'
@@ -1,5 +1,7 @@
1
1
  import ast
2
+ import decimal
2
3
  import re
4
+ from decimal import Decimal
3
5
 
4
6
  datetime64_patterns = [
5
7
  r"\d\d\d\d.\d\d.\d\d(T|\s)\d\d:\d\d:\d\d.\d\d\d",
@@ -317,3 +319,89 @@ def type_test(i, t):
317
319
  return True
318
320
  except Exception:
319
321
  return False
322
+
323
+
324
+ def parse_decimal_type(typ):
325
+ """
326
+ >>> parse_decimal_type("decimal")
327
+
328
+ >>> parse_decimal_type('Decimal')
329
+ (64, 10, 0)
330
+ >>> parse_decimal_type('Decimal()')
331
+
332
+ >>> parse_decimal_type('Decimal(2)')
333
+ (32, 2, 0)
334
+ >>> parse_decimal_type('Decimal(5,2)')
335
+ (32, 5, 2)
336
+ >>> parse_decimal_type('Decimal( 9 , 2 )')
337
+ (32, 9, 2)
338
+ >>> parse_decimal_type('Decimal(10,2)')
339
+ (64, 10, 2)
340
+ >>> parse_decimal_type('Decimal(19,2)')
341
+ (128, 19, 2)
342
+ >>> parse_decimal_type('Decimal(39,2)')
343
+ (256, 39, 2)
344
+ >>> parse_decimal_type('Decimal32(9)')
345
+ (32, 9, 9)
346
+ >>> parse_decimal_type('Decimal32(10)')
347
+
348
+ >>> parse_decimal_type('Decimal(10,10)')
349
+ (64, 10, 10)
350
+ >>> parse_decimal_type('Decimal(10,11)')
351
+
352
+ >>> parse_decimal_type('Decimal32(5, 2)')
353
+
354
+ >>> parse_decimal_type('Decimal64(2)')
355
+ (64, 18, 2)
356
+ >>> parse_decimal_type('Decimal128(2)')
357
+ (128, 38, 2)
358
+ >>> parse_decimal_type('Decimal256(2)')
359
+ (256, 76, 2)
360
+ """
361
+ # Obtained from https://clickhouse.com/docs/en/sql-reference/data-types/decimal
362
+ max_digits_by_bit_width = {32: 9, 64: 18, 128: 38, 256: 76}
363
+
364
+ # Check if type is Decimal, Decimal(P), or Decimal(P, S) with whitespace support
365
+ # Regex contains two capturing groups. First capturing P. Second capturing S.
366
+ if m := re.match(r"^Decimal\s*(?:\(\s*(\d+)(?:\s*,\s*(\d+))?\s*\))?$", typ):
367
+ p, s = int(m.group(1) or 10), int(m.group(2) or 0)
368
+ b = min(bit_width for bit_width, max_digits in max_digits_by_bit_width.items() if max_digits >= p)
369
+ if p < s or b is None:
370
+ return None
371
+ # Check if type is Decimal32(S), Decimal64(S), Decimal128(S), or Decimal256(S) with whitespace support.
372
+ # Regex contains 2 capturing groups. First capturing 32, 64, 128 or 256. Second capturing S.
373
+ elif m := re.match(r"^Decimal(32|64|128|256)\s*\(\s*(\d+)\s*\)$", typ):
374
+ b, s = int(m.group(1)), int(m.group(2))
375
+ p = max_digits_by_bit_width[int(b)]
376
+ if p < s:
377
+ return None
378
+ else:
379
+ return None
380
+ return b, p, s
381
+
382
+
383
+ def is_type_decimal(type_to_check):
384
+ """
385
+ >>> is_type_decimal('Decimal')
386
+ True
387
+ >>> is_type_decimal("Decimal(10, 2)")
388
+ True
389
+ >>> is_type_decimal("decimal")
390
+ False
391
+ """
392
+ return parse_decimal_type(type_to_check) is not None
393
+
394
+
395
+ def get_decimal_limits(p, s):
396
+ """
397
+ >>> get_decimal_limits(1, 0)
398
+ (Decimal('-9'), Decimal('9'))
399
+ >>> get_decimal_limits(5, 5)
400
+ (Decimal('-0.99999'), Decimal('0.99999'))
401
+ >>> get_decimal_limits(76, 38)
402
+ (Decimal('-99999999999999999999999999999999999999.99999999999999999999999999999999999999'), Decimal('99999999999999999999999999999999999999.99999999999999999999999999999999999999'))
403
+ """
404
+ with decimal.localcontext(prec=p + 2):
405
+ max_value = Decimal(((10**p) - 1)) / (10**s)
406
+ min_value = -max_value
407
+ return min_value, max_value
@@ -357,6 +357,11 @@ 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
+ )
360
365
  error_unlinking_pipe_not_linked = error_message("** {pipe} is not linked (MV, Copy, or Sink).")
361
366
 
362
367
  info_incl_relative_path = info_message("** Relative path {path} does not exist, skipping.")
@@ -1384,9 +1384,13 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
1384
1384
  if is_test_mode:
1385
1385
  return Symbol("{" + sqlescape(x) + ": String}")
1386
1386
  else:
1387
- 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
+ )
1388
1390
  except Exception:
1389
- 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
+ )
1390
1394
 
1391
1395
  def set_max_threads(x):
1392
1396
  try:
@@ -2115,7 +2119,7 @@ def render_sql_template(
2115
2119
  >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", variables = { 'test': '1234' })
2116
2120
  Traceback (most recent call last):
2117
2121
  ...
2118
- 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.
2119
2123
  >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", test_mode=True)
2120
2124
  ('select * from table where str = {test: String}', {}, [])
2121
2125
  >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = [ 'tb_secret_test' ], test_mode=True)
@@ -2123,7 +2127,7 @@ def render_sql_template(
2123
2127
  >>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = [ 'tb_secret_test2' ])
2124
2128
  Traceback (most recent call last):
2125
2129
  ...
2126
- 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.
2127
2131
  """
2128
2132
  escape_split_to_array = ff_split_to_array_escape.get(False)
2129
2133
  bypass_preprocess_variables = ff_preprocess_parameters_circuit_breaker.get(False)
@@ -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,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird-cli
3
- Version: 5.1.1.dev2
3
+ Version: 5.2.0
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,15 +18,12 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
- 5.1.1.dev2
22
- ************
21
+ 5.2.0
22
+ ******
23
23
 
24
+ - `Added` internal changes
24
25
  - `Added` `tb pipe unlink` command
25
-
26
- 5.1.1.dev1
27
- ***********
28
-
29
- - `Added` internal release
26
+ - `Changed` No need for `--node` param in `tb pipe populate`
30
27
 
31
28
  5.1.0
32
29
  ******