tinybird-cli 5.20.1.dev4__tar.gz → 5.21.1.dev1__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 (48) hide show
  1. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/PKG-INFO +4 -13
  2. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/__cli__.py +2 -2
  3. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/client.py +3 -0
  4. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/datafile_common.py +7 -0
  5. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/sql_template.py +8 -1
  6. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/sql_toolset.py +4 -0
  7. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/cli.py +8 -0
  8. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/pipe.py +8 -0
  9. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/token.py +32 -12
  10. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird_cli.egg-info/PKG-INFO +4 -13
  11. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/setup.cfg +0 -0
  12. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/ch_utils/constants.py +0 -0
  13. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/ch_utils/engine.py +0 -0
  14. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/check_pypi.py +0 -0
  15. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/config.py +0 -0
  16. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/connectors.py +0 -0
  17. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/context.py +0 -0
  18. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/datatypes.py +0 -0
  19. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/feedback_manager.py +0 -0
  20. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/git_settings.py +0 -0
  21. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/sql.py +0 -0
  22. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/sql_template_fmt.py +0 -0
  23. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/syncasync.py +0 -0
  24. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli.py +0 -0
  25. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/auth.py +0 -0
  26. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/branch.py +0 -0
  27. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/cicd.py +0 -0
  28. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/common.py +0 -0
  29. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/config.py +0 -0
  30. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/connection.py +0 -0
  31. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/datasource.py +0 -0
  32. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/exceptions.py +0 -0
  33. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/fmt.py +0 -0
  34. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/job.py +0 -0
  35. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/regions.py +0 -0
  36. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/tag.py +0 -0
  37. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/telemetry.py +0 -0
  38. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/test.py +0 -0
  39. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  40. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  41. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/workspace.py +0 -0
  42. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  43. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird/tornado_template.py +0 -0
  44. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird_cli.egg-info/SOURCES.txt +0 -0
  45. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird_cli.egg-info/dependency_links.txt +0 -0
  46. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird_cli.egg-info/entry_points.txt +0 -0
  47. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird_cli.egg-info/requires.txt +0 -0
  48. {tinybird_cli-5.20.1.dev4 → tinybird_cli-5.21.1.dev1}/tinybird_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird_cli
3
- Version: 5.20.1.dev4
3
+ Version: 5.21.1.dev1
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli
6
6
  Author: Tinybird
@@ -61,24 +61,15 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
61
61
  Changelog
62
62
  ----------
63
63
 
64
- 5.20.1.dev4
64
+ 5.21.1.dev1
65
65
  ***********
66
66
 
67
67
  - Internal changes.
68
68
 
69
- 5.20.1.dev3
70
- ***********
71
-
72
- - `Fixed` Mypy errors in base infrastructure and analytics modules.
73
-
74
- 5.20.1.dev2
75
- ***********
76
-
77
- - `Fixed` Templating when using `id` parameter and the value was not provided.
78
-
79
- 5.20.1.dev1
69
+ 5.21.0
80
70
  ***********
81
71
 
72
+ - `Added` `tb pipe populate` and `tb push <PIPE> --populate` has a new `--on-demand-compute` flag to enable Compute-Compute Separation in populates.
82
73
  - `Added` When trying to push a materialized view with an unoptimized join, the CLI will now warn the user.
83
74
 
84
75
  5.19.0
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
4
4
  __url__ = 'https://www.tinybird.co/docs/cli'
5
5
  __author__ = 'Tinybird'
6
6
  __author_email__ = 'support@tinybird.co'
7
- __version__ = '5.20.1.dev4'
8
- __revision__ = 'bb9222e'
7
+ __version__ = '5.21.1.dev1'
8
+ __revision__ = '39c9264'
@@ -569,6 +569,7 @@ class TinyB:
569
569
  populate_condition: Optional[str] = None,
570
570
  truncate: bool = True,
571
571
  unlink_on_populate_error: bool = False,
572
+ on_demand_compute: bool = False,
572
573
  ):
573
574
  params: Dict[str, Any] = {
574
575
  "truncate": "true" if truncate else "false",
@@ -578,6 +579,8 @@ class TinyB:
578
579
  params.update({"populate_subset": populate_subset})
579
580
  if populate_condition:
580
581
  params.update({"populate_condition": populate_condition})
582
+ if on_demand_compute:
583
+ params.update({"on_demand_compute": "true"})
581
584
  response = await self._req(
582
585
  f"/v0/pipes/{pipe_name}/nodes/{node_name}/population?{urlencode(params)}", method="POST"
583
586
  )
@@ -2894,6 +2894,7 @@ async def new_pipe(
2894
2894
  config: Any = None,
2895
2895
  fork_downstream: Optional[bool] = False,
2896
2896
  fork: Optional[bool] = False,
2897
+ on_demand_compute: bool = False,
2897
2898
  ):
2898
2899
  # TODO use tb_client instead of calling the urls directly.
2899
2900
  host = tb_client.host
@@ -2981,6 +2982,8 @@ async def new_pipe(
2981
2982
  params["force"] = "true"
2982
2983
  if populate:
2983
2984
  params["populate"] = "true"
2985
+ if on_demand_compute:
2986
+ params["on_demand_compute"] = "true"
2984
2987
  if populate_condition:
2985
2988
  params["populate_condition"] = populate_condition
2986
2989
  if populate_subset:
@@ -3600,6 +3603,7 @@ async def exec_file(
3600
3603
  fork_downstream: Optional[bool] = False,
3601
3604
  fork: Optional[bool] = False,
3602
3605
  git_release: Optional[bool] = False,
3606
+ on_demand_compute: bool = False,
3603
3607
  ):
3604
3608
  if debug:
3605
3609
  click.echo(FeedbackManager.debug_running_file(file=pp.pformat(r)))
@@ -3629,6 +3633,7 @@ async def exec_file(
3629
3633
  tests_check_requests_from_branch=tests_check_requests_from_branch,
3630
3634
  fork_downstream=fork_downstream,
3631
3635
  fork=fork,
3636
+ on_demand_compute=on_demand_compute,
3632
3637
  )
3633
3638
  await update_tags_in_resource(r, "pipe", tb_client)
3634
3639
  elif r["resource"] == "datasources":
@@ -4239,6 +4244,7 @@ async def folder_push(
4239
4244
  use_main: bool = False,
4240
4245
  check_outdated: bool = True,
4241
4246
  hide_folders: bool = False,
4247
+ on_demand_compute: bool = False,
4242
4248
  ):
4243
4249
  workspaces: List[Dict[str, Any]] = (await tb_client.user_workspaces_and_branches()).get("workspaces", [])
4244
4250
  current_ws: Dict[str, Any] = next(
@@ -4423,6 +4429,7 @@ async def folder_push(
4423
4429
  fork_downstream,
4424
4430
  fork,
4425
4431
  git_release,
4432
+ on_demand_compute,
4426
4433
  )
4427
4434
  if not run_tests:
4428
4435
  click.echo(
@@ -74,7 +74,7 @@ class SQLTemplateException(ValueError):
74
74
  # replace_vars_smart(t)
75
75
  # print(generate(t, **{x: '' for x in names}))
76
76
 
77
-
77
+ JOB_TIMESTAMP_PARAM = "job_timestamp"
78
78
  DEFAULT_PARAM_NAMES = ["format", "q"]
79
79
  RESERVED_PARAM_NAMES = [
80
80
  "__tb__semver",
@@ -93,6 +93,7 @@ RESERVED_PARAM_NAMES = [
93
93
  "tag",
94
94
  "template_parameters",
95
95
  "token",
96
+ JOB_TIMESTAMP_PARAM,
96
97
  ]
97
98
 
98
99
  parameter_types = [
@@ -2002,6 +2003,7 @@ def format_SQLTemplateException_message(e: SQLTemplateException, vars_and_types:
2002
2003
  item.get("default") is None
2003
2004
  and item.get("used_in", None) is None
2004
2005
  and item.get("name") not in vars_with_default_none
2006
+ and item.get("name") is not JOB_TIMESTAMP_PARAM
2005
2007
  ):
2006
2008
  vars_with_default_none.append(item["name"])
2007
2009
 
@@ -2294,6 +2296,11 @@ def render_sql_template(
2294
2296
  processed_variables = preprocess_variables(variables, template_variables_with_types)
2295
2297
  variables.update(processed_variables)
2296
2298
 
2299
+ # Handle job_timestamp special case providing the default value if not provided
2300
+ if any(var["name"] == JOB_TIMESTAMP_PARAM for var in template_variables_with_types):
2301
+ variables = variables or {}
2302
+ variables.setdefault(JOB_TIMESTAMP_PARAM, datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
2303
+
2297
2304
  if test_mode:
2298
2305
 
2299
2306
  def dummy(*args, **kwargs):
@@ -456,6 +456,10 @@ def replace_tables(
456
456
  sql, None, output_one_line=output_one_line, timestamp=timestamp, function_allow_list=hashable_list
457
457
  )
458
458
 
459
+ # Fix for empty database names in JOINs - remove empty backticks like ``.table_name
460
+ # that are generated when chquery.replace_tables processes tuples with empty database names
461
+ sql = sql.replace("``.", "")
462
+
459
463
  return sql
460
464
 
461
465
 
@@ -602,6 +602,12 @@ def check(filenames: List[str], debug: bool) -> None:
602
602
  help="The user token is required for sharing a datasource that contains the SHARED_WITH entry.",
603
603
  type=click.types.STRING,
604
604
  )
605
+ @click.option(
606
+ "--on-demand-compute",
607
+ is_flag=True,
608
+ default=False,
609
+ help="Use on-demand compute instances for populate jobs. Only effective when used with --populate.",
610
+ )
605
611
  @click.pass_context
606
612
  @coro
607
613
  async def push(
@@ -633,6 +639,7 @@ async def push(
633
639
  check_requests_from_main: bool,
634
640
  folder: str,
635
641
  user_token: Optional[str],
642
+ on_demand_compute: bool,
636
643
  ) -> None:
637
644
  """Push files to Tinybird."""
638
645
 
@@ -674,6 +681,7 @@ async def push(
674
681
  config=CLIConfig.get_project_config(),
675
682
  user_token=user_token,
676
683
  is_internal=is_internal,
684
+ on_demand_compute=on_demand_compute,
677
685
  )
678
686
 
679
687
 
@@ -234,6 +234,12 @@ async def pipe_ls(ctx: Context, match: str, format_: str):
234
234
  default=False,
235
235
  help="Waits for populate jobs to finish, showing a progress bar. Disabled by default.",
236
236
  )
237
+ @click.option(
238
+ "--on-demand-compute",
239
+ is_flag=True,
240
+ default=False,
241
+ help="Use on-demand compute instances for the populate job.",
242
+ )
237
243
  @click.pass_context
238
244
  @coro
239
245
  async def pipe_populate(
@@ -244,6 +250,7 @@ async def pipe_populate(
244
250
  truncate: bool,
245
251
  unlink_on_populate_error: bool,
246
252
  wait: bool,
253
+ on_demand_compute: bool,
247
254
  ):
248
255
  """Populate the result of a Materialized Node into the target Materialized View"""
249
256
  cl = create_tb_client(ctx)
@@ -270,6 +277,7 @@ async def pipe_populate(
270
277
  populate_condition=sql_condition,
271
278
  truncate=truncate,
272
279
  unlink_on_populate_error=unlink_on_populate_error,
280
+ on_demand_compute=on_demand_compute,
273
281
  )
274
282
  if "job" not in response:
275
283
  raise CLIPipeException(response)
@@ -167,7 +167,7 @@ def create(ctx: Context) -> None:
167
167
 
168
168
  You can create two types of tokens: JWT or Static.
169
169
 
170
- * JWT tokens have a TTL and can only have the PIPES:READ scope.Their main use case is allow your users to call your endpoints without exposing your API key.
170
+ * JWT tokens have a TTL and can have PIPES:READ and DATASOURCES:READ scopes. Their main use case is allow your users to call your endpoints or read datasources without exposing your API key.
171
171
 
172
172
  * Static Tokens do not have a TTL and can have any valid scope (DATASOURCES:READ, DATASOURCES:APPEND, DATASOURCES:CREATE, DATASOURCES:DROP, PIPES:CREATE, PIPES:READ, PIPES:DROP).
173
173
 
@@ -175,6 +175,8 @@ def create(ctx: Context) -> None:
175
175
 
176
176
  tb token create jwt my_jwt_token --ttl 1h --scope PIPES:READ --resource my_pipe
177
177
 
178
+ tb token create jwt my_jwt_token --ttl 1h --scope DATASOURCES:READ --resource my_datasource --filter "column = 'value'"
179
+
178
180
  tb token create static my_static_token --scope PIPES:READ --resource my_pipe
179
181
 
180
182
  tb token create static my_static_token --scope DATASOURCES:READ --resource my_datasource
@@ -192,17 +194,22 @@ def create(ctx: Context) -> None:
192
194
  @click.option(
193
195
  "--scope",
194
196
  multiple=True,
195
- type=click.Choice(["PIPES:READ"]),
197
+ type=click.Choice(["PIPES:READ", "DATASOURCES:READ"]),
196
198
  required=True,
197
- help="Scope of the token (only PIPES:READ is allowed for JWT tokens)",
199
+ help="Scope of the token (only PIPES:READ and DATASOURCES:READ are allowed for JWT tokens)",
198
200
  )
199
201
  @click.option("--resource", multiple=True, required=True, help="Resource associated with the scope")
200
202
  @click.option(
201
203
  "--fixed-params", multiple=True, help="Fixed parameters in key=value format, multiple values separated by commas"
202
204
  )
205
+ @click.option(
206
+ "--filter",
207
+ multiple=True,
208
+ help="SQL filter to apply when reading a datasource (only applicable for DATASOURCES:READ scope)",
209
+ )
203
210
  @click.pass_context
204
211
  @coro
205
- async def create_jwt_token(ctx: Context, name: str, ttl: timedelta, scope, resource, fixed_params) -> None:
212
+ async def create_jwt_token(ctx: Context, name: str, ttl: timedelta, scope, resource, fixed_params, filter) -> None:
206
213
  """Create a JWT token with a TTL specify."""
207
214
 
208
215
  obj: Dict[str, Any] = ctx.ensure_object(dict)
@@ -216,6 +223,10 @@ async def create_jwt_token(ctx: Context, name: str, ttl: timedelta, scope, resou
216
223
  if fixed_params and len(fixed_params) > len(scope):
217
224
  raise CLITokenException(FeedbackManager.error_number_of_fixed_params_and_resources_mismatch())
218
225
 
226
+ # Ensure the number of filters does not exceed the number of scope/resource pairs
227
+ if filter and len(filter) > len(scope):
228
+ raise CLITokenException("The number of SQL filters must match the number of scopes")
229
+
219
230
  # Parse fixed params
220
231
  parsed_fixed_params = parse_fixed_params(fixed_params) if fixed_params else []
221
232
 
@@ -224,15 +235,24 @@ async def create_jwt_token(ctx: Context, name: str, ttl: timedelta, scope, resou
224
235
  for i, params in enumerate(parsed_fixed_params):
225
236
  fixed_params_list[i] = params
226
237
 
238
+ # Create a list of filters for each scope/resource pair, defaulting to None if not provided
239
+ filters_list: List[Optional[str]] = [None] * len(scope)
240
+ for i, f in enumerate(filter):
241
+ filters_list[i] = f
242
+
227
243
  scopes = []
228
- for sc, res, fparams in zip(scope, resource, fixed_params_list):
229
- scopes.append(
230
- {
231
- "type": sc,
232
- "resource": res,
233
- "fixed_params": fparams,
234
- }
235
- )
244
+ for sc, res, fparams, filter in zip(scope, resource, fixed_params_list, filters_list):
245
+ scope_data = {
246
+ "type": sc,
247
+ "resource": res,
248
+ }
249
+
250
+ if sc == "PIPES:READ" and fparams:
251
+ scope_data["fixed_params"] = fparams
252
+ elif sc == "DATASOURCES:READ" and filter:
253
+ scope_data["filter"] = filter
254
+
255
+ scopes.append(scope_data)
236
256
 
237
257
  try:
238
258
  response = await client.create_jwt_token(name, expiration_time, scopes)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird_cli
3
- Version: 5.20.1.dev4
3
+ Version: 5.21.1.dev1
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli
6
6
  Author: Tinybird
@@ -61,24 +61,15 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
61
61
  Changelog
62
62
  ----------
63
63
 
64
- 5.20.1.dev4
64
+ 5.21.1.dev1
65
65
  ***********
66
66
 
67
67
  - Internal changes.
68
68
 
69
- 5.20.1.dev3
70
- ***********
71
-
72
- - `Fixed` Mypy errors in base infrastructure and analytics modules.
73
-
74
- 5.20.1.dev2
75
- ***********
76
-
77
- - `Fixed` Templating when using `id` parameter and the value was not provided.
78
-
79
- 5.20.1.dev1
69
+ 5.21.0
80
70
  ***********
81
71
 
72
+ - `Added` `tb pipe populate` and `tb push <PIPE> --populate` has a new `--on-demand-compute` flag to enable Compute-Compute Separation in populates.
82
73
  - `Added` When trying to push a materialized view with an unoptimized join, the CLI will now warn the user.
83
74
 
84
75
  5.19.0