tinybird 4.6.20__tar.gz → 4.6.20.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.
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/PKG-INFO +1 -16
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/ch_utils/constants.py +0 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/ch_utils/engine.py +32 -49
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/client.py +0 -41
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/datafile/common.py +1 -9
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/datatypes.py +12 -34
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/feedback_manager.py +0 -5
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/service_datasources.py +8 -7
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/sql.py +6 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/sql_template.py +2 -8
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/sql_toolset.py +0 -59
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/client.py +0 -41
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/common.py +77 -15
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/copy.py +1 -33
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/build.py +0 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/format_pipe.py +0 -4
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/playground.py +0 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/feedback_manager.py +0 -5
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/infra.py +2 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/logs.py +2 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/materialization.py +1 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/project.py +4 -4
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/tinyunit/tinyunit.py +4 -4
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/token.py +5 -2
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/watch.py +1 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/branch.py +2 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/cicd.py +0 -2
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/cli.py +9 -5
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/common.py +94 -27
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/config.py +2 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/datasource.py +1 -1
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/pipe.py +34 -49
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +4 -4
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/workspace.py +13 -11
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tornado_template.py +17 -216
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird.egg-info/PKG-INFO +1 -16
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird.egg-info/SOURCES.txt +1 -4
- tinybird-4.6.20/pyproject.toml +0 -239
- tinybird-4.6.20/tinybird/utils/__init__.py +0 -0
- tinybird-4.6.20/tinybird/utils/bools.py +0 -19
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/setup.cfg +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/__cli__.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/check_pypi.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/config.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/context.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/git_settings.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/iterating/__init__.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/iterating/data_branch_modes.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/prompts.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/syncasync.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/cli.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/config.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/build_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/cli.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/config.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/connection_dynamodb.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/connection_kafka.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/connection_s3.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/create.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/format_connection.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/deployment_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/job.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.6.20 → tinybird-4.6.20.dev0}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird
|
|
3
|
-
Version: 4.6.20
|
|
3
|
+
Version: 4.6.20.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -52,16 +52,6 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
54
|
|
|
55
|
-
4.6.20
|
|
56
|
-
********
|
|
57
|
-
|
|
58
|
-
- `Added` Copy pipes accept ``ON_DEMAND_COMPUTE true`` so scheduled runs use on-demand compute. Manual ``tb copy run`` still requires ``--on-demand-compute``, and asks for confirmation when the local datafile does not enable it (skip it with ``--yes``).
|
|
59
|
-
|
|
60
|
-
4.6.19
|
|
61
|
-
********
|
|
62
|
-
|
|
63
|
-
- `Changed` ``tb datasource append`` and ``tb datasource replace`` submit remote CSV, NDJSON, and Parquet URLs through the v1 import endpoint by default.
|
|
64
|
-
|
|
65
55
|
4.6.18
|
|
66
56
|
********
|
|
67
57
|
|
|
@@ -72,11 +62,6 @@ Changelog
|
|
|
72
62
|
|
|
73
63
|
- `Added` ``tb job retry <job_id>`` to retry eligible import and S3/GCS sync jobs in ``error`` or ``cancelled`` status.
|
|
74
64
|
|
|
75
|
-
4.6.18
|
|
76
|
-
********
|
|
77
|
-
|
|
78
|
-
- `Added` ``Markdown`` is now a valid ``FORMAT`` for SQL queries (for example ``tb sql "SELECT 1 FORMAT Markdown"``), returned as a Markdown table.
|
|
79
|
-
|
|
80
65
|
4.6.16
|
|
81
66
|
********
|
|
82
67
|
|
|
@@ -440,64 +440,35 @@ def get_engine_config(engine: str):
|
|
|
440
440
|
)
|
|
441
441
|
|
|
442
442
|
|
|
443
|
-
def
|
|
444
|
-
|
|
445
|
-
) -> None:
|
|
446
|
-
if schema is not None and columns is not None:
|
|
447
|
-
raise ValueError("You can not use 'schema' and 'columns' at the same time")
|
|
448
|
-
_, (params, options) = get_engine_config(engine)
|
|
449
|
-
schema_columns = parse_table_structure(schema) if schema is not None else (columns or [])
|
|
450
|
-
engine_settings = {key.replace("engine_", ""): value for key, value in args.items()}
|
|
451
|
-
|
|
452
|
-
for arg in engine_settings:
|
|
453
|
-
if not hasattr(TableDetails, arg):
|
|
454
|
-
raise ValueError(f"engine_{arg} is not a valid option")
|
|
455
|
-
|
|
443
|
+
def engine_params(columns, params: List[EngineParam], args: Dict):
|
|
444
|
+
params_values = []
|
|
456
445
|
for p in params:
|
|
457
|
-
if p.required and p.name not in
|
|
446
|
+
if p.required and p.name not in args:
|
|
458
447
|
raise ValueError(f"Missing required parameter '{p.name}'")
|
|
459
|
-
param_value =
|
|
448
|
+
param_value = args.get(p.name, None) or p.default_value
|
|
460
449
|
if not param_value:
|
|
461
450
|
continue
|
|
462
451
|
if p.is_valid:
|
|
463
452
|
check_is_valid(
|
|
464
|
-
valid_check=p.is_valid,
|
|
465
|
-
check_type="parameter",
|
|
466
|
-
columns=schema_columns,
|
|
467
|
-
tb_param=p.tb_param,
|
|
468
|
-
value=param_value,
|
|
453
|
+
valid_check=p.is_valid, check_type="parameter", columns=columns, tb_param=p.tb_param, value=param_value
|
|
469
454
|
)
|
|
470
|
-
|
|
471
|
-
for o in options:
|
|
472
|
-
if o.required and o.name not in engine_settings:
|
|
473
|
-
raise ValueError(f"Missing required option '{o.name}'")
|
|
474
|
-
option_value = engine_settings.get(o.name) or o.default_value
|
|
475
|
-
if o.is_valid:
|
|
476
|
-
check_is_valid(
|
|
477
|
-
valid_check=o.is_valid,
|
|
478
|
-
check_type="option",
|
|
479
|
-
columns=schema_columns,
|
|
480
|
-
tb_param=o.tb_param,
|
|
481
|
-
value=option_value,
|
|
482
|
-
)
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
def engine_params(params: List[EngineParam], args: Dict) -> List[str]:
|
|
486
|
-
params_values = []
|
|
487
|
-
for p in params:
|
|
488
|
-
param_value = args.get(p.name, None) or p.default_value
|
|
489
|
-
if not param_value:
|
|
490
|
-
continue
|
|
491
455
|
params_values.append(param_value)
|
|
492
456
|
return params_values
|
|
493
457
|
|
|
494
458
|
|
|
495
|
-
def engine_options(options: List[EngineOption], args: Dict)
|
|
459
|
+
def engine_options(columns, options: List[EngineOption], args: Dict):
|
|
496
460
|
options_values = []
|
|
497
461
|
engine_settings = ""
|
|
498
462
|
|
|
499
463
|
for o in options:
|
|
464
|
+
if o.required and o.name not in args:
|
|
465
|
+
raise ValueError(f"Missing required option '{o.name}'")
|
|
500
466
|
option_value = args.get(o.name) or o.default_value
|
|
467
|
+
if o.is_valid:
|
|
468
|
+
check_is_valid(
|
|
469
|
+
valid_check=o.is_valid, check_type="option", columns=columns, tb_param=o.tb_param, value=option_value
|
|
470
|
+
)
|
|
471
|
+
|
|
501
472
|
if option_value:
|
|
502
473
|
if o.sql.lower() == "settings":
|
|
503
474
|
engine_settings = f"{o.sql} {option_value}"
|
|
@@ -519,7 +490,7 @@ def check_is_valid(
|
|
|
519
490
|
columns: List[Dict[str, Any]],
|
|
520
491
|
tb_param: str,
|
|
521
492
|
value: str,
|
|
522
|
-
)
|
|
493
|
+
):
|
|
523
494
|
"""
|
|
524
495
|
>>> check_is_valid(sorting_key_is_valid, 'option', ['column-name'], 'sorting_key', 'date')
|
|
525
496
|
|
|
@@ -536,13 +507,15 @@ def check_is_valid(
|
|
|
536
507
|
raise ValueError(f"Invalid value '{value}' for {check_type} '{tb_param}', reason: {e}")
|
|
537
508
|
|
|
538
509
|
|
|
539
|
-
def build_engine(
|
|
540
|
-
|
|
510
|
+
def build_engine(
|
|
511
|
+
engine: str, columns: Optional[List], params: List[EngineParam], options: List[EngineOption], args: Dict
|
|
512
|
+
):
|
|
513
|
+
return f"{engine}({', '.join(engine_params(columns, params, args))}) {' '.join(engine_options(columns, options, args))}".strip()
|
|
541
514
|
|
|
542
515
|
|
|
543
516
|
def engine_full_from_dict(
|
|
544
517
|
engine: str, args: dict, schema: Optional[str] = None, columns: Optional[List[Dict[str, Any]]] = None
|
|
545
|
-
)
|
|
518
|
+
):
|
|
546
519
|
"""
|
|
547
520
|
>>> schema = ''
|
|
548
521
|
>>> engine_full_from_dict('wadus', {}, schema=schema)
|
|
@@ -633,10 +606,20 @@ def engine_full_from_dict(
|
|
|
633
606
|
'ReplacingMergeTree(updated_at) PARTITION BY (tuple()) ORDER BY (project_id) SETTINGS index_granularity = 32'
|
|
634
607
|
"""
|
|
635
608
|
|
|
636
|
-
|
|
637
|
-
|
|
609
|
+
if schema is not None and columns is not None:
|
|
610
|
+
raise ValueError("You can not use 'schema' and 'columns' at the same time")
|
|
611
|
+
engine_config = get_engine_config(engine)
|
|
612
|
+
name, (params, options) = engine_config
|
|
613
|
+
if columns is None and schema is not None:
|
|
614
|
+
columns = parse_table_structure(schema)
|
|
615
|
+
|
|
638
616
|
engine_settings = {key.replace("engine_", ""): value for key, value in args.items()}
|
|
639
|
-
|
|
617
|
+
|
|
618
|
+
for arg in engine_settings:
|
|
619
|
+
if not hasattr(TableDetails, arg):
|
|
620
|
+
raise ValueError(f"engine_{arg} is not a valid option")
|
|
621
|
+
|
|
622
|
+
return build_engine(name, columns, params, options, engine_settings)
|
|
640
623
|
|
|
641
624
|
|
|
642
625
|
def engine_params_from_engine_full(engine_full: str) -> Dict[str, Any]:
|
|
@@ -408,16 +408,6 @@ class TinyB:
|
|
|
408
408
|
format: str = "csv",
|
|
409
409
|
replace_options: Optional[Set[str]] = None,
|
|
410
410
|
) -> Dict[str, Any]:
|
|
411
|
-
if mode in ("append", "replace"):
|
|
412
|
-
return await self.datasource_append_url(
|
|
413
|
-
table_name,
|
|
414
|
-
url,
|
|
415
|
-
mode=mode,
|
|
416
|
-
sql_condition=sql_condition,
|
|
417
|
-
format=format,
|
|
418
|
-
replace_options=replace_options,
|
|
419
|
-
)
|
|
420
|
-
|
|
421
411
|
params = {"name": table_name, "url": url, "mode": mode, "debug": "blocks_block_log", "format": format}
|
|
422
412
|
|
|
423
413
|
if sql_condition:
|
|
@@ -434,33 +424,6 @@ class TinyB:
|
|
|
434
424
|
|
|
435
425
|
return await self.wait_for_job(res["id"], status_callback, backoff_multiplier=1.5, maximum_backoff_seconds=20)
|
|
436
426
|
|
|
437
|
-
async def datasource_append_url(
|
|
438
|
-
self,
|
|
439
|
-
datasource_name: str,
|
|
440
|
-
url: str,
|
|
441
|
-
mode: str = "append",
|
|
442
|
-
sql_condition: Optional[str] = None,
|
|
443
|
-
format: str = "csv",
|
|
444
|
-
replace_options: Optional[Set[str]] = None,
|
|
445
|
-
) -> Dict[str, Any]:
|
|
446
|
-
params = {"format": format, "url": url}
|
|
447
|
-
if sql_condition:
|
|
448
|
-
params["replace_condition"] = sql_condition
|
|
449
|
-
if replace_options:
|
|
450
|
-
for option in replace_options:
|
|
451
|
-
params[option] = "true"
|
|
452
|
-
|
|
453
|
-
res = await self._req(
|
|
454
|
-
f"/v1/datasources/{quote(datasource_name, safe='')}/{mode}?{urlencode(params, safe='')}",
|
|
455
|
-
method="POST",
|
|
456
|
-
data=b"",
|
|
457
|
-
)
|
|
458
|
-
if not isinstance(res, dict):
|
|
459
|
-
raise RuntimeError("We couldn't confirm that your import started. Please try again.")
|
|
460
|
-
if "error" in res:
|
|
461
|
-
raise Exception(res["error"])
|
|
462
|
-
return res
|
|
463
|
-
|
|
464
427
|
async def datasource_delete(self, datasource_name: str, force: bool = False, dry_run: bool = False):
|
|
465
428
|
params = {"force": "true" if force else "false", "dry_run": "true" if dry_run else "false"}
|
|
466
429
|
return await self._req(f"/v0/datasources/{datasource_name}?{urlencode(params)}", method="DELETE")
|
|
@@ -691,7 +654,6 @@ class TinyB:
|
|
|
691
654
|
target_datasource: Optional[str] = None,
|
|
692
655
|
schedule_cron: Optional[str] = None,
|
|
693
656
|
mode: Optional[str] = None,
|
|
694
|
-
on_demand_compute: Optional[bool] = None,
|
|
695
657
|
):
|
|
696
658
|
data = {"schedule_cron": schedule_cron}
|
|
697
659
|
|
|
@@ -701,9 +663,6 @@ class TinyB:
|
|
|
701
663
|
if mode:
|
|
702
664
|
data["mode"] = mode
|
|
703
665
|
|
|
704
|
-
if on_demand_compute is not None:
|
|
705
|
-
data["on_demand_compute"] = "true" if on_demand_compute else "false"
|
|
706
|
-
|
|
707
666
|
return await self._req(f"/v0/pipes/{pipe_name_or_id}/nodes/{node_id}/copy", method="PUT", data=data)
|
|
708
667
|
|
|
709
668
|
async def pipe_remove_copy(self, pipe_name_or_id: str, node_id: str):
|
|
@@ -28,7 +28,6 @@ from tinybird.ch_utils.engine import VALID_ENGINE_PARAMS, EngineParam
|
|
|
28
28
|
from tinybird.datafile.exceptions import IncludeFileNotFoundException, ParseException, ValidationException
|
|
29
29
|
from tinybird.tb.modules.exceptions import CLIPipeException
|
|
30
30
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
31
|
-
from tinybird.utils.bools import parse_optional_bool
|
|
32
31
|
|
|
33
32
|
# Code from sql.py has been duplicated so I can change it without breaking absolutely everything in the app
|
|
34
33
|
# I'll try not to make logic changes, just error reporting changes
|
|
@@ -180,10 +179,9 @@ class CopyParameters(Parameters):
|
|
|
180
179
|
COPY_SCHEDULE = "copy_schedule"
|
|
181
180
|
COPY_MODE = "copy_mode"
|
|
182
181
|
COPY_MODE_ALIAS = "mode" # we need this because bot MODE and COPY_MODE go to `mode` variable inside the node
|
|
183
|
-
ON_DEMAND_COMPUTE = "on_demand_compute"
|
|
184
182
|
MANDATORY_ATTRIBUTES = PipeParameters.MANDATORY_ATTRIBUTES.union({TARGET_DATASOURCE})
|
|
185
183
|
ACCEPTED_ATTRIBUTES = PipeParameters.ACCEPTED_ATTRIBUTES.union(MANDATORY_ATTRIBUTES).union(
|
|
186
|
-
{COPY_SCHEDULE, COPY_MODE_ALIAS
|
|
184
|
+
{COPY_SCHEDULE, COPY_MODE_ALIAS}
|
|
187
185
|
)
|
|
188
186
|
|
|
189
187
|
|
|
@@ -418,11 +416,6 @@ class Datafile:
|
|
|
418
416
|
)
|
|
419
417
|
if not croniter.is_valid(copy_schedule):
|
|
420
418
|
raise DatafileValidationError("COPY node schedule must be @on-demand or a valid cron expression.")
|
|
421
|
-
if CopyParameters.ON_DEMAND_COMPUTE in node:
|
|
422
|
-
try:
|
|
423
|
-
node[CopyParameters.ON_DEMAND_COMPUTE] = parse_optional_bool(node[CopyParameters.ON_DEMAND_COMPUTE])
|
|
424
|
-
except ValueError:
|
|
425
|
-
raise DatafileValidationError("ON_DEMAND_COMPUTE must be true or false")
|
|
426
419
|
for key in node.keys():
|
|
427
420
|
if key not in CopyParameters.valid_params():
|
|
428
421
|
raise DatafileValidationError(
|
|
@@ -2104,7 +2097,6 @@ def parse(
|
|
|
2104
2097
|
"copy_schedule": assign_node_var(CopyParameters.COPY_SCHEDULE),
|
|
2105
2098
|
"copy_mode": assign_node_var("mode"),
|
|
2106
2099
|
"mode": assign_node_var("mode"),
|
|
2107
|
-
"on_demand_compute": assign_node_var(CopyParameters.ON_DEMAND_COMPUTE),
|
|
2108
2100
|
"filter": assign_node_var("filter"),
|
|
2109
2101
|
"token": add_token,
|
|
2110
2102
|
"include": include,
|
|
@@ -120,74 +120,52 @@ def datetime_test(x: str) -> bool:
|
|
|
120
120
|
return any(p.match(x) for p in datetime_patterns)
|
|
121
121
|
|
|
122
122
|
|
|
123
|
-
def bounded_integer(x: str, pattern: re.Pattern[str]) -> Optional[int]:
|
|
124
|
-
if pattern.match(x) is None:
|
|
125
|
-
return None
|
|
126
|
-
digits = x.lstrip("+-").lstrip("0")
|
|
127
|
-
# 256-bit unsigned integers have at most 78 decimal digits.
|
|
128
|
-
if len(digits) > 78:
|
|
129
|
-
return None
|
|
130
|
-
return int(x) if len(x) <= 78 else int(digits or "0") * (-1 if x.startswith("-") else 1)
|
|
131
|
-
|
|
132
|
-
|
|
133
123
|
def int_8_test(x: str) -> bool:
|
|
134
|
-
|
|
135
|
-
return value is not None and -int_8_max <= value < int_8_max
|
|
124
|
+
return intx_re.match(x) is not None and -int_8_max <= int(x) < int_8_max
|
|
136
125
|
|
|
137
126
|
|
|
138
127
|
def int16_test(x: str) -> bool:
|
|
139
|
-
|
|
140
|
-
return value is not None and -int16_max <= value < int16_max
|
|
128
|
+
return intx_re.match(x) is not None and -int16_max <= int(x) < int16_max
|
|
141
129
|
|
|
142
130
|
|
|
143
131
|
def int32_test(x: str) -> bool:
|
|
144
|
-
|
|
145
|
-
return value is not None and -int32_max <= value < int32_max
|
|
132
|
+
return intx_re.match(x) is not None and -int32_max <= int(x) < int32_max
|
|
146
133
|
|
|
147
134
|
|
|
148
135
|
def int64_test(x: str) -> bool:
|
|
149
|
-
|
|
150
|
-
return value is not None and -int64_max <= value < int64_max
|
|
136
|
+
return intx_re.match(x) is not None and -int64_max <= int(x) < int64_max
|
|
151
137
|
|
|
152
138
|
|
|
153
139
|
def int128_test(x: str) -> bool:
|
|
154
|
-
|
|
155
|
-
return value is not None and -int128_max <= value < int128_max
|
|
140
|
+
return intx_re.match(x) is not None and -int128_max <= int(x) < int128_max
|
|
156
141
|
|
|
157
142
|
|
|
158
143
|
def int256_test(x: str) -> bool:
|
|
159
|
-
|
|
160
|
-
return value is not None and -int256_max <= value < int256_max
|
|
144
|
+
return intx_re.match(x) is not None and -int256_max <= int(x) < int256_max
|
|
161
145
|
|
|
162
146
|
|
|
163
147
|
def uint_8_test(x: str) -> bool:
|
|
164
|
-
|
|
165
|
-
return value is not None and 0 <= value < uint_8_max
|
|
148
|
+
return uintx_re.match(x) is not None and 0 <= int(x) < uint_8_max
|
|
166
149
|
|
|
167
150
|
|
|
168
151
|
def uint16_test(x: str) -> bool:
|
|
169
|
-
|
|
170
|
-
return value is not None and 0 <= value < uint16_max
|
|
152
|
+
return uintx_re.match(x) is not None and 0 <= int(x) < uint16_max
|
|
171
153
|
|
|
172
154
|
|
|
173
155
|
def uint32_test(x: str) -> bool:
|
|
174
|
-
|
|
175
|
-
return value is not None and 0 <= value < uint32_max
|
|
156
|
+
return uintx_re.match(x) is not None and 0 <= int(x) < uint32_max
|
|
176
157
|
|
|
177
158
|
|
|
178
159
|
def uint64_test(x: str) -> bool:
|
|
179
|
-
|
|
180
|
-
return value is not None and 0 <= value < uint64_max
|
|
160
|
+
return uintx_re.match(x) is not None and 0 <= int(x) < uint64_max
|
|
181
161
|
|
|
182
162
|
|
|
183
163
|
def uint128_test(x: str) -> bool:
|
|
184
|
-
|
|
185
|
-
return value is not None and 0 <= value < uint128_max
|
|
164
|
+
return intx_re.match(x) is not None and 0 <= int(x) < uint128_max
|
|
186
165
|
|
|
187
166
|
|
|
188
167
|
def uint256_test(x: str) -> bool:
|
|
189
|
-
|
|
190
|
-
return value is not None and 0 <= value < uint256_max
|
|
168
|
+
return intx_re.match(x) is not None and 0 <= int(x) < uint256_max
|
|
191
169
|
|
|
192
170
|
|
|
193
171
|
def float_test(x: str) -> bool:
|
|
@@ -572,11 +572,6 @@ class FeedbackManager:
|
|
|
572
572
|
"You can read more about the pricing at https://www.tinybird.co/docs/classic/work-with-data/process-and-copy/materialized-views#compute-compute-separation-for-populates\n\n"
|
|
573
573
|
"Do you want to proceed with on-demand compute?"
|
|
574
574
|
)
|
|
575
|
-
warning_confirm_on_demand_compute_differs_from_datafile = warning_message(
|
|
576
|
-
"The local datafile of pipe '{pipe}' does not set ON_DEMAND_COMPUTE true, but --on-demand-compute was passed.\n"
|
|
577
|
-
"On-demand compute uses dedicated resources that are billed separately from your regular usage.\n\n"
|
|
578
|
-
"Do you want to proceed?"
|
|
579
|
-
)
|
|
580
575
|
|
|
581
576
|
warning_confirm_delete_token = prompt_message("Do you want to delete Token {token}?")
|
|
582
577
|
warning_confirm_refresh_token = prompt_message("Do you want to refresh Token {token}?")
|
|
@@ -39,7 +39,6 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
39
39
|
{"name": "result_rows", "type": "UInt64"},
|
|
40
40
|
{"name": "url", "type": "Nullable(String)"},
|
|
41
41
|
{"name": "error", "type": "UInt8"},
|
|
42
|
-
{"name": "error_message", "type": "Nullable(String)"},
|
|
43
42
|
{"name": "status_code", "type": "Int32"},
|
|
44
43
|
{"name": "request_id", "type": "String"},
|
|
45
44
|
{"name": "parameters", "type": "Map(String, String)"},
|
|
@@ -444,21 +443,25 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
444
443
|
"dateColumn": "run_validation",
|
|
445
444
|
"engine": {
|
|
446
445
|
"engine": "MergeTree",
|
|
447
|
-
"sorting_key": "
|
|
446
|
+
"sorting_key": "database, host, run_validation, query_hash",
|
|
448
447
|
"partition_key": "toYYYYMM(run_validation)",
|
|
449
448
|
},
|
|
450
449
|
"columns": [
|
|
450
|
+
{"name": "host", "type": "LowCardinality(String)"},
|
|
451
451
|
{"name": "version", "type": "LowCardinality(String)"},
|
|
452
452
|
{"name": "stable_version", "type": "LowCardinality(String)"},
|
|
453
453
|
{"name": "query_hash", "type": "UInt64"},
|
|
454
454
|
{"name": "query_last_execution", "type": "DateTime"},
|
|
455
|
-
{"name": "
|
|
456
|
-
{"name": "
|
|
455
|
+
{"name": "region", "type": "String"},
|
|
456
|
+
{"name": "workspace", "type": "String"},
|
|
457
|
+
{"name": "database", "type": "String"},
|
|
458
|
+
{"name": "pipe_name", "type": "String"},
|
|
457
459
|
{"name": "query_id", "type": "String"},
|
|
458
460
|
{"name": "query", "type": "String"},
|
|
459
461
|
{"name": "error_code", "type": "Int16"},
|
|
460
462
|
{"name": "error", "type": "String"},
|
|
461
463
|
{"name": "fix_suggestion", "type": "String"},
|
|
464
|
+
{"name": "fix_suggestion_ai", "type": "String"},
|
|
462
465
|
{"name": "run_validation", "type": "DateTime"},
|
|
463
466
|
],
|
|
464
467
|
},
|
|
@@ -677,7 +680,6 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
677
680
|
{"name": "result_rows", "type": "UInt64"},
|
|
678
681
|
{"name": "url", "type": "Nullable(String)"},
|
|
679
682
|
{"name": "error", "type": "UInt8"},
|
|
680
|
-
{"name": "error_message", "type": "Nullable(String)"},
|
|
681
683
|
{"name": "status_code", "type": "Int32"},
|
|
682
684
|
{"name": "request_id", "type": "String"},
|
|
683
685
|
{"name": "parameters", "type": "Map(String, String)"},
|
|
@@ -782,7 +784,7 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
782
784
|
},
|
|
783
785
|
{
|
|
784
786
|
"name": "organization.metrics_logs",
|
|
785
|
-
"description": "Metrics of your organization's dedicated
|
|
787
|
+
"description": "Metrics of your organization's dedicated clusters",
|
|
786
788
|
"dateColumn": "timestamp",
|
|
787
789
|
"engine": {
|
|
788
790
|
"engine": "MergeTree",
|
|
@@ -796,7 +798,6 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
796
798
|
{"name": "metric", "type": "LowCardinality(String)"},
|
|
797
799
|
{"name": "value", "type": "String"},
|
|
798
800
|
{"name": "description", "type": "LowCardinality(String)"},
|
|
799
|
-
{"name": "organization_id", "type": "String"},
|
|
800
801
|
],
|
|
801
802
|
},
|
|
802
803
|
{
|
|
@@ -129,9 +129,15 @@ class TableProjection:
|
|
|
129
129
|
def add_projection_sql(self):
|
|
130
130
|
return f"ADD {self.to_sql()}"
|
|
131
131
|
|
|
132
|
+
def drop_projection_sql(self):
|
|
133
|
+
return f"DROP PROJECTION IF EXISTS {self.name}"
|
|
134
|
+
|
|
132
135
|
def materialize_projection_sql(self):
|
|
133
136
|
return f"MATERIALIZE PROJECTION IF EXISTS {self.name}"
|
|
134
137
|
|
|
138
|
+
def clear_projection_sql(self):
|
|
139
|
+
return f"CLEAR PROJECTION IF EXISTS {self.name}"
|
|
140
|
+
|
|
135
141
|
|
|
136
142
|
def as_subquery(sql: str) -> str:
|
|
137
143
|
return f"""(\n{sql}\n)"""
|
|
@@ -18,7 +18,7 @@ from tinybird.context import (
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
from .datatypes import testers
|
|
21
|
-
from .tornado_template import
|
|
21
|
+
from .tornado_template import VALID_CUSTOM_FUNCTION_NAMES, SecurityException, Template
|
|
22
22
|
|
|
23
23
|
VALID_ACTIVATE_FEATURES = frozenset(["analyzer", "parallel_replicas", "optimize_aggregation_in_order"])
|
|
24
24
|
|
|
@@ -84,7 +84,6 @@ class SQLTemplateException(ValueError):
|
|
|
84
84
|
JOB_TIMESTAMP_PARAM = "job_timestamp"
|
|
85
85
|
DEFAULT_PARAM_NAMES = ["format", "q"]
|
|
86
86
|
RESERVED_PARAM_NAMES = [
|
|
87
|
-
"__tb__csv_header",
|
|
88
87
|
"__tb__semver",
|
|
89
88
|
"debug_source_tables",
|
|
90
89
|
"debug",
|
|
@@ -1375,7 +1374,7 @@ _namespace = {
|
|
|
1375
1374
|
# they raise a pretty non understandable error but if someone
|
|
1376
1375
|
# is using them they know what they are trying to do
|
|
1377
1376
|
# read https://anee.me/escaping-python-jails-849c65cf306e on how to escape from python jails
|
|
1378
|
-
"
|
|
1377
|
+
"__buildins__": {},
|
|
1379
1378
|
"__import__": {},
|
|
1380
1379
|
"__debug__": {},
|
|
1381
1380
|
"__doc__": {},
|
|
@@ -1385,9 +1384,6 @@ _namespace = {
|
|
|
1385
1384
|
"close": None,
|
|
1386
1385
|
"print": None,
|
|
1387
1386
|
"input": None,
|
|
1388
|
-
# Keep customer parameters named `type`/`dir` usable without restoring the unsafe builtins.
|
|
1389
|
-
"type": None,
|
|
1390
|
-
"dir": None,
|
|
1391
1387
|
}
|
|
1392
1388
|
|
|
1393
1389
|
|
|
@@ -1481,8 +1477,6 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1481
1477
|
# the generated source code.
|
|
1482
1478
|
"__name__": self.name.replace(".", "_"),
|
|
1483
1479
|
"__loader__": ObjectDict(get_source=lambda name: self.code),
|
|
1484
|
-
# Set again after kwargs so request parameters can't override it
|
|
1485
|
-
"__builtins__": SAFE_BUILTINS,
|
|
1486
1480
|
"max_threads": set_max_threads,
|
|
1487
1481
|
"tb_secret": set_tb_secret,
|
|
1488
1482
|
"tb_var": set_tb_secret,
|
|
@@ -699,62 +699,3 @@ def is_invalid_resource_from_current_workspace(
|
|
|
699
699
|
valid_tables: Optional[Set[Tuple[str, str]]],
|
|
700
700
|
) -> bool:
|
|
701
701
|
return bool(database == default_database and valid_tables and r not in valid_tables and r not in _replaced_with)
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
def validate_ttl_expression(
|
|
705
|
-
columns: list[dict[str, str]],
|
|
706
|
-
ttl: Optional[str],
|
|
707
|
-
sorting_key: str,
|
|
708
|
-
primary_key: Optional[str] = None,
|
|
709
|
-
partition_key: Optional[str] = None,
|
|
710
|
-
) -> Optional[str]:
|
|
711
|
-
if not ttl:
|
|
712
|
-
return None
|
|
713
|
-
|
|
714
|
-
kwargs = {"partition_key": partition_key} if partition_key else {}
|
|
715
|
-
error = chquery.validate_ttl(
|
|
716
|
-
ttl=ttl,
|
|
717
|
-
columns=columns,
|
|
718
|
-
sorting_key=sorting_key,
|
|
719
|
-
primary_key=primary_key or sorting_key,
|
|
720
|
-
**kwargs,
|
|
721
|
-
)
|
|
722
|
-
if error is None:
|
|
723
|
-
return None
|
|
724
|
-
return error.removeprefix("DB::Exception: ")
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
TTL_ONLY_DROP_PARTS_SETTING = "ttl_only_drop_parts"
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
def should_default_ttl_only_drop_parts(
|
|
731
|
-
columns: list[dict[str, str]],
|
|
732
|
-
ttl: Optional[str],
|
|
733
|
-
sorting_key: str,
|
|
734
|
-
partition_key: Optional[str],
|
|
735
|
-
primary_key: Optional[str] = None,
|
|
736
|
-
) -> bool:
|
|
737
|
-
"""Whether ``ttl_only_drop_parts = 1`` should be defaulted for this table."""
|
|
738
|
-
if not ttl or not partition_key:
|
|
739
|
-
return False
|
|
740
|
-
result = chquery.check_ttl_partition_compatibility(
|
|
741
|
-
columns=columns,
|
|
742
|
-
ttl=ttl,
|
|
743
|
-
sorting_key=sorting_key,
|
|
744
|
-
primary_key=primary_key or sorting_key,
|
|
745
|
-
partition_key=partition_key,
|
|
746
|
-
)
|
|
747
|
-
return result["checked"] and result["error"] is None
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
def validate_partition_key_expression(
|
|
751
|
-
columns: list[dict[str, str]],
|
|
752
|
-
partition_key: Optional[str],
|
|
753
|
-
) -> Optional[str]:
|
|
754
|
-
if not partition_key:
|
|
755
|
-
return None
|
|
756
|
-
|
|
757
|
-
error = chquery.validate_partition_key(columns=columns, partition_key=partition_key)
|
|
758
|
-
if error is None:
|
|
759
|
-
return None
|
|
760
|
-
return error.removeprefix("DB::Exception: ")
|
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/forward/commands'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '4.6.20'
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '4.6.20.dev0'
|
|
8
|
+
__revision__ = 'fee8cae'
|
|
@@ -432,16 +432,6 @@ class TinyB:
|
|
|
432
432
|
format: str = "csv",
|
|
433
433
|
replace_options: Optional[Set[str]] = None,
|
|
434
434
|
) -> Dict[str, Any]:
|
|
435
|
-
if mode in ("append", "replace"):
|
|
436
|
-
return self.datasource_append_url(
|
|
437
|
-
table_name,
|
|
438
|
-
url,
|
|
439
|
-
mode=mode,
|
|
440
|
-
sql_condition=sql_condition,
|
|
441
|
-
format=format,
|
|
442
|
-
replace_options=replace_options,
|
|
443
|
-
)
|
|
444
|
-
|
|
445
435
|
params = {"name": table_name, "url": url, "mode": mode, "debug": "blocks_block_log", "format": format}
|
|
446
436
|
|
|
447
437
|
if sql_condition:
|
|
@@ -458,33 +448,6 @@ class TinyB:
|
|
|
458
448
|
|
|
459
449
|
return self.wait_for_job(res["id"], status_callback, backoff_multiplier=1.5, maximum_backoff_seconds=20)
|
|
460
450
|
|
|
461
|
-
def datasource_append_url(
|
|
462
|
-
self,
|
|
463
|
-
datasource_name: str,
|
|
464
|
-
url: str,
|
|
465
|
-
mode: str = "append",
|
|
466
|
-
sql_condition: Optional[str] = None,
|
|
467
|
-
format: str = "csv",
|
|
468
|
-
replace_options: Optional[Set[str]] = None,
|
|
469
|
-
) -> Dict[str, Any]:
|
|
470
|
-
params = {"format": format, "url": url}
|
|
471
|
-
if sql_condition:
|
|
472
|
-
params["replace_condition"] = sql_condition
|
|
473
|
-
if replace_options:
|
|
474
|
-
for option in replace_options:
|
|
475
|
-
params[option] = "true"
|
|
476
|
-
|
|
477
|
-
res = self._req(
|
|
478
|
-
f"/v1/datasources/{quote(datasource_name, safe='')}/{mode}?{urlencode(params, safe='')}",
|
|
479
|
-
method="POST",
|
|
480
|
-
data=b"",
|
|
481
|
-
)
|
|
482
|
-
if not isinstance(res, dict):
|
|
483
|
-
raise RuntimeError("We couldn't confirm that your import started. Please try again.")
|
|
484
|
-
if "error" in res:
|
|
485
|
-
raise Exception(res["error"])
|
|
486
|
-
return res
|
|
487
|
-
|
|
488
451
|
def datasource_delete(self, datasource_name: str, force: bool = False, dry_run: bool = False):
|
|
489
452
|
params = {"force": "true" if force else "false", "dry_run": "true" if dry_run else "false"}
|
|
490
453
|
return self._req(f"/v0/datasources/{datasource_name}?{urlencode(params)}", method="DELETE")
|
|
@@ -743,7 +706,6 @@ class TinyB:
|
|
|
743
706
|
target_datasource: Optional[str] = None,
|
|
744
707
|
schedule_cron: Optional[str] = None,
|
|
745
708
|
mode: Optional[str] = None,
|
|
746
|
-
on_demand_compute: Optional[bool] = None,
|
|
747
709
|
):
|
|
748
710
|
data = {"schedule_cron": schedule_cron}
|
|
749
711
|
|
|
@@ -753,9 +715,6 @@ class TinyB:
|
|
|
753
715
|
if mode:
|
|
754
716
|
data["mode"] = mode
|
|
755
717
|
|
|
756
|
-
if on_demand_compute is not None:
|
|
757
|
-
data["on_demand_compute"] = "true" if on_demand_compute else "false"
|
|
758
|
-
|
|
759
718
|
return self._req(f"/v0/pipes/{pipe_name_or_id}/nodes/{node_id}/copy", method="PUT", data=data)
|
|
760
719
|
|
|
761
720
|
def pipe_remove_copy(self, pipe_name_or_id: str, node_id: str):
|