tinybird 4.6.16.dev0__tar.gz → 4.6.17__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.16.dev0 → tinybird-4.6.17}/PKG-INFO +22 -1
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/ch_utils/engine.py +13 -13
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/client.py +14 -26
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/config.py +0 -4
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/datafile/common.py +41 -25
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/git_settings.py +1 -3
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/service_datasources.py +42 -16
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/sql_toolset.py +0 -5
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/client.py +5 -2
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/build_common.py +4 -6
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/common.py +2 -2
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/deployment.py +5 -8
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/deployment_common.py +108 -15
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/feedback_manager.py +1 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/job.py +22 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird.egg-info/PKG-INFO +22 -1
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/setup.cfg +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/__cli__.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/check_pypi.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/context.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/datatypes.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/feedback_manager.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/iterating/__init__.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/iterating/data_branch_modes.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/prompts.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/sql.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/sql_template.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/syncasync.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/cli.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/config.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/cli.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/config.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/connection_dynamodb.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/connection_kafka.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/connection_s3.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/create.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/format_connection.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/playground.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/infra.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/logs.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/project.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/token.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird/tornado_template.py +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.6.16.dev0 → tinybird-4.6.17}/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.
|
|
3
|
+
Version: 4.6.17
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -51,11 +51,32 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
51
51
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
|
+
|
|
55
|
+
4.6.17
|
|
56
|
+
********
|
|
57
|
+
|
|
58
|
+
- `Added` ``tb job retry <job_id>`` to retry eligible import and S3/GCS sync jobs in ``error`` or ``cancelled`` status.
|
|
59
|
+
|
|
60
|
+
4.6.16
|
|
61
|
+
********
|
|
62
|
+
|
|
63
|
+
- `Fixed` ``tb deployment promote --wait`` and ``tb deployment discard --wait`` no longer hang forever when the server reports the old/discarded deployment removal as ``failed``; the CLI now detects the failure, prints the deployment errors, and exits non-zero.
|
|
64
|
+
|
|
65
|
+
4.6.15
|
|
66
|
+
********
|
|
67
|
+
|
|
68
|
+
- `Fixed` ``tb deploy`` waits for the old deployment to delete to avoid clashing with a new deployment submission.
|
|
69
|
+
|
|
54
70
|
4.6.14
|
|
55
71
|
********
|
|
56
72
|
|
|
57
73
|
- `Changed` ``tb datasource append`` and ``tb datasource replace`` submit local CSV, NDJSON, and Parquet files through the v1 import endpoint by default. ``tb datasource append --events`` also submits its request body through v1. These asynchronous imports print the queued job ID; pass ``--wait`` to wait for completion. Remote URL imports continue to use their existing route.
|
|
58
74
|
|
|
75
|
+
4.6.14
|
|
76
|
+
********
|
|
77
|
+
|
|
78
|
+
- `Fixed` `tb migrate-to-forward` correctly finds and offers to delete all branches, not just those created by the user running the migration.
|
|
79
|
+
|
|
59
80
|
4.6.13
|
|
60
81
|
********
|
|
61
82
|
|
|
@@ -111,8 +111,7 @@ class TableDetails:
|
|
|
111
111
|
|
|
112
112
|
@property
|
|
113
113
|
def version(self):
|
|
114
|
-
|
|
115
|
-
return _version
|
|
114
|
+
return self.details.get("version", None)
|
|
116
115
|
|
|
117
116
|
def is_replicated(self) -> bool:
|
|
118
117
|
engine: Optional[str] = self.details.get("engine", None)
|
|
@@ -183,6 +182,7 @@ class TableDetails:
|
|
|
183
182
|
settings = self.details.get("settings", None)
|
|
184
183
|
if settings and settings.strip().lower() != "index_granularity = 8192":
|
|
185
184
|
return settings
|
|
185
|
+
return None
|
|
186
186
|
|
|
187
187
|
@property
|
|
188
188
|
def ttl(self):
|
|
@@ -190,23 +190,19 @@ class TableDetails:
|
|
|
190
190
|
|
|
191
191
|
@property
|
|
192
192
|
def ver(self):
|
|
193
|
-
|
|
194
|
-
return _ver
|
|
193
|
+
return self.details.get("ver", None)
|
|
195
194
|
|
|
196
195
|
@property
|
|
197
196
|
def is_deleted(self):
|
|
198
|
-
|
|
199
|
-
return _is_deleted
|
|
197
|
+
return self.details.get("is_deleted", None)
|
|
200
198
|
|
|
201
199
|
@property
|
|
202
200
|
def columns(self):
|
|
203
|
-
|
|
204
|
-
return _columns
|
|
201
|
+
return self.details.get("columns", None)
|
|
205
202
|
|
|
206
203
|
@property
|
|
207
204
|
def sign(self):
|
|
208
|
-
|
|
209
|
-
return _sign
|
|
205
|
+
return self.details.get("sign", None)
|
|
210
206
|
|
|
211
207
|
@property
|
|
212
208
|
def statistics(self) -> Dict[str, Any]:
|
|
@@ -476,6 +472,9 @@ def engine_options(columns, options: List[EngineOption], args: Dict):
|
|
|
476
472
|
if option_value:
|
|
477
473
|
if o.sql.lower() == "settings":
|
|
478
474
|
engine_settings = f"{o.sql} {option_value}"
|
|
475
|
+
# Conditional TTLs fail if we wrap the value in parentheses
|
|
476
|
+
elif o.sql.lower() == "ttl":
|
|
477
|
+
options_values.append(f"{o.sql} {option_value}")
|
|
479
478
|
else:
|
|
480
479
|
options_values.append(f"{o.sql} ({option_value})")
|
|
481
480
|
|
|
@@ -536,7 +535,9 @@ def engine_full_from_dict(
|
|
|
536
535
|
>>> engine_full_from_dict('MergeTree', {'sorting_key': 'local_date, cod_store'}, schema=schema)
|
|
537
536
|
'MergeTree() ORDER BY (local_date, cod_store)'
|
|
538
537
|
>>> engine_full_from_dict('MergeTree', {'partition_key': 'toDate(timestamp)', 'sorting_key': 'local_date, cod_store', 'settings': 'index_granularity = 32, index_granularity_bytes = 2048', 'ttl': 'toDate(local_date) + INTERVAL 1 DAY'}, schema=schema)
|
|
539
|
-
'MergeTree() PARTITION BY (toDate(timestamp)) ORDER BY (local_date, cod_store) TTL
|
|
538
|
+
'MergeTree() PARTITION BY (toDate(timestamp)) ORDER BY (local_date, cod_store) TTL toDate(local_date) + INTERVAL 1 DAY SETTINGS index_granularity = 32, index_granularity_bytes = 2048'
|
|
539
|
+
>>> engine_full_from_dict('MergeTree', {'sorting_key': 'timestamp', 'ttl': 'timestamp + INTERVAL 1 DAY DELETE WHERE is_deleted = 1'}, schema=schema)
|
|
540
|
+
'MergeTree() ORDER BY (timestamp) TTL timestamp + INTERVAL 1 DAY DELETE WHERE is_deleted = 1'
|
|
540
541
|
|
|
541
542
|
>>> schema = ''
|
|
542
543
|
>>> engine_full_from_dict('CollapsingMergeTree', {'sign': 'sign_column'}, schema=schema)
|
|
@@ -694,8 +695,7 @@ def ttl_from_engine(engine: str) -> Optional[str]:
|
|
|
694
695
|
return None
|
|
695
696
|
settings_array = engine.split(" SETTINGS ")
|
|
696
697
|
settings = " SETTINGS " + settings_array[1] if len(settings_array) > 1 else None
|
|
697
|
-
|
|
698
|
-
return ttl
|
|
698
|
+
return ttl_array[1][: -(len(settings))] if settings else ttl_array[1]
|
|
699
699
|
|
|
700
700
|
|
|
701
701
|
def ttl_condition_from_engine_full(engine_full: Optional[str]) -> Optional[str]:
|
|
@@ -266,14 +266,13 @@ class TinyB:
|
|
|
266
266
|
|
|
267
267
|
async def alter_tokens(self, name: str, scopes: List[str]):
|
|
268
268
|
if not scopes:
|
|
269
|
-
return
|
|
269
|
+
return None
|
|
270
270
|
scopes_url: str = "&".join([f"scope={scope}" for scope in scopes])
|
|
271
271
|
url = f"/v0/tokens/{name}"
|
|
272
272
|
if len(url + "?" + scopes_url) > TinyB.MAX_GET_LENGTH:
|
|
273
273
|
return await self._req(url, method="PUT", data=scopes_url)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
return await self._req(url, method="PUT", data="")
|
|
274
|
+
url = url + "?" + scopes_url
|
|
275
|
+
return await self._req(url, method="PUT", data="")
|
|
277
276
|
|
|
278
277
|
async def datasources(self, branch: Optional[str] = None, used_by: bool = False) -> List[Dict[str, Any]]:
|
|
279
278
|
params = {}
|
|
@@ -294,16 +293,13 @@ class TinyB:
|
|
|
294
293
|
return await self._req(f"/v0/variables/{name}")
|
|
295
294
|
|
|
296
295
|
async def create_secret(self, name: str, value: str):
|
|
297
|
-
|
|
298
|
-
return response
|
|
296
|
+
return await self._req("/v0/variables", method="POST", data={"name": name, "value": value})
|
|
299
297
|
|
|
300
298
|
async def update_secret(self, name: str, value: str):
|
|
301
|
-
|
|
302
|
-
return response
|
|
299
|
+
return await self._req(f"/v0/variables/{name}", method="PUT", data={"value": value})
|
|
303
300
|
|
|
304
301
|
async def delete_secret(self, name: str):
|
|
305
|
-
|
|
306
|
-
return response
|
|
302
|
+
return await self._req(f"/v0/variables/{name}", method="DELETE")
|
|
307
303
|
|
|
308
304
|
async def get_connections(self, service: Optional[str] = None):
|
|
309
305
|
params = {}
|
|
@@ -577,8 +573,7 @@ class TinyB:
|
|
|
577
573
|
node_name = node["params"]["name"] if node.get("params", None) else node["name"]
|
|
578
574
|
if datasource_name:
|
|
579
575
|
params["datasource"] = datasource_name
|
|
580
|
-
|
|
581
|
-
return response
|
|
576
|
+
return await self._req(f"/v0/pipes/{pipe_name}/nodes/{node_name}/analysis?{urlencode(params)}")
|
|
582
577
|
|
|
583
578
|
async def populate_node(
|
|
584
579
|
self,
|
|
@@ -600,10 +595,7 @@ class TinyB:
|
|
|
600
595
|
params.update({"populate_condition": populate_condition})
|
|
601
596
|
if on_demand_compute:
|
|
602
597
|
params.update({"on_demand_compute": "true"})
|
|
603
|
-
|
|
604
|
-
f"/v0/pipes/{pipe_name}/nodes/{node_name}/population?{urlencode(params)}", method="POST"
|
|
605
|
-
)
|
|
606
|
-
return response
|
|
598
|
+
return await self._req(f"/v0/pipes/{pipe_name}/nodes/{node_name}/population?{urlencode(params)}", method="POST")
|
|
607
599
|
|
|
608
600
|
async def pipes(self, branch=None, dependencies: bool = False, node_attrs=None, attrs=None) -> List[Dict[str, Any]]:
|
|
609
601
|
params = {
|
|
@@ -635,9 +627,8 @@ class TinyB:
|
|
|
635
627
|
query_string = urlencode(params)
|
|
636
628
|
if len(url + "?" + query_string) > TinyB.MAX_GET_LENGTH:
|
|
637
629
|
return await self._req(f"/v0/pipes/{pipe_name_or_uid}.{format}", method="POST", data=params)
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return await self._req(url)
|
|
630
|
+
url = url + "?" + query_string
|
|
631
|
+
return await self._req(url)
|
|
641
632
|
|
|
642
633
|
async def pipe_create(self, pipe_name: str, sql: str):
|
|
643
634
|
return await self._req(
|
|
@@ -726,8 +717,7 @@ class TinyB:
|
|
|
726
717
|
|
|
727
718
|
if len(sql) > TinyB.MAX_GET_LENGTH:
|
|
728
719
|
return await self._req(f"/v0/sql?{urlencode(params)}", data=sql, method="POST")
|
|
729
|
-
|
|
730
|
-
return await self._req(f"/v0/sql?q={quote(sql, safe='')}&{urlencode(params)}")
|
|
720
|
+
return await self._req(f"/v0/sql?q={quote(sql, safe='')}&{urlencode(params)}")
|
|
731
721
|
|
|
732
722
|
async def jobs(self, status=None):
|
|
733
723
|
jobs = (await self._req("/v0/jobs"))["jobs"]
|
|
@@ -922,7 +912,7 @@ class TinyB:
|
|
|
922
912
|
|
|
923
913
|
async def add_workspaces_to_organization(self, organization_id: str, workspace_ids: List[str]):
|
|
924
914
|
if not workspace_ids:
|
|
925
|
-
return
|
|
915
|
+
return None
|
|
926
916
|
return await self._req(
|
|
927
917
|
f"/v0/organizations/{organization_id}/workspaces",
|
|
928
918
|
method="PUT",
|
|
@@ -1105,8 +1095,7 @@ class TinyB:
|
|
|
1105
1095
|
from tinybird.sql_toolset import format_sql
|
|
1106
1096
|
|
|
1107
1097
|
return format_sql(sql)
|
|
1108
|
-
|
|
1109
|
-
return await self._sql_get_format_remote(sql, with_clickhouse_format)
|
|
1098
|
+
return await self._sql_get_format_remote(sql, with_clickhouse_format)
|
|
1110
1099
|
except ModuleNotFoundError:
|
|
1111
1100
|
return await self._sql_get_format_remote(sql, with_clickhouse_format)
|
|
1112
1101
|
|
|
@@ -1168,8 +1157,7 @@ class TinyB:
|
|
|
1168
1157
|
return next((connector for connector in result["connectors"] if connector_equals(connector, kwargs)), None)
|
|
1169
1158
|
|
|
1170
1159
|
async def regions(self):
|
|
1171
|
-
|
|
1172
|
-
return regions
|
|
1160
|
+
return await self._req("/v0/regions")
|
|
1173
1161
|
|
|
1174
1162
|
async def datasource_query_copy(self, datasource_name: str, sql_query: str):
|
|
1175
1163
|
params = {"copy_to": datasource_name}
|
|
@@ -49,11 +49,7 @@ LEGACY_HOSTS = {
|
|
|
49
49
|
"https://ui.europe-west2.gcp.tinybird.co": "https://cloud.tinybird.co/gcp/europe-west2",
|
|
50
50
|
"https://ui.ap-east.aws.tinybird.co": "https://app.tinybird.co/aws/ap-east-1",
|
|
51
51
|
"https://ui.ap-east-1.aws.tinybird.co": "https://app.tinybird.co/aws/ap-east-1",
|
|
52
|
-
"https://ui.split.tinybird.co": "https://app.tinybird.co/aws/split-us-east",
|
|
53
|
-
"https://ui.split.us-west-2.aws.tinybird.co": "https://app.tinybird.co/aws/split-us-west-2",
|
|
54
52
|
"https://ui.northamerica-northeast2.gcp.tinybird.co": "https://app.tinybird.co/gcp/northamerica-northeast2",
|
|
55
|
-
"https://api.split.tinybird.co": "https://app.tinybird.co/aws/split-us-east",
|
|
56
|
-
"https://api.split.us-west-2.aws.tinybird.co": "https://app.tinybird.co/aws/split-us-west-2",
|
|
57
53
|
"https://ui.wadus1.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus1",
|
|
58
54
|
"https://ui.wadus2.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus2",
|
|
59
55
|
"https://ui.wadus3.gcp.tinybird.co": "https://app.wadus.tinybird.co/gcp/wadus3",
|
|
@@ -278,6 +278,12 @@ REQUIRED_DYNAMODB_PARAMS = {
|
|
|
278
278
|
}
|
|
279
279
|
DYNAMODB_PARAMS = REQUIRED_DYNAMODB_PARAMS
|
|
280
280
|
|
|
281
|
+
REQUIRED_POSTGRES_PARAMS = {
|
|
282
|
+
"pg_connection_name",
|
|
283
|
+
"pg_table",
|
|
284
|
+
}
|
|
285
|
+
POSTGRES_PARAMS = REQUIRED_POSTGRES_PARAMS
|
|
286
|
+
|
|
281
287
|
|
|
282
288
|
def extract_column_names_from_sorting_key_part(part: str) -> List[str]:
|
|
283
289
|
"""
|
|
@@ -496,13 +502,12 @@ class Datafile:
|
|
|
496
502
|
f"For Kafka sinks, provide 'export_kafka_topic'. "
|
|
497
503
|
f"For S3/GCS sinks, provide 'export_bucket_uri' and 'export_file_template'."
|
|
498
504
|
)
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
)
|
|
505
|
+
# There are some export parameters, but they don't match known patterns
|
|
506
|
+
raise DatafileValidationError(
|
|
507
|
+
f"Sink node {repr(node['name'])} has unrecognized export parameters: {export_params}. "
|
|
508
|
+
f"For Kafka sinks, use 'export_kafka_topic'. "
|
|
509
|
+
f"For S3/GCS sinks, use 'export_bucket_uri' and 'export_file_template'."
|
|
510
|
+
)
|
|
506
511
|
|
|
507
512
|
# Validate schedule format (common for both Kafka and S3/GCS)
|
|
508
513
|
export_schedule = node.get("export_schedule")
|
|
@@ -602,6 +607,13 @@ class Datafile:
|
|
|
602
607
|
raise DatafileValidationError(
|
|
603
608
|
f"Invalid import schedule '{node['import_schedule']}'. Only {sorted(VALID_BLOB_STORAGE_CRON_VALUES)} values are allowed"
|
|
604
609
|
)
|
|
610
|
+
# Validate Postgres params
|
|
611
|
+
if any(param in node for param in POSTGRES_PARAMS) and (
|
|
612
|
+
missing := [param for param in REQUIRED_POSTGRES_PARAMS if param not in node]
|
|
613
|
+
):
|
|
614
|
+
raise DatafileValidationError(
|
|
615
|
+
f"Some Postgres params have been provided, but the following required ones are missing: {missing}"
|
|
616
|
+
)
|
|
605
617
|
|
|
606
618
|
else:
|
|
607
619
|
# We cannot validate a datafile whose kind is unknown
|
|
@@ -1060,8 +1072,7 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
1060
1072
|
# Find the first SyntaxExpr in lookup that matches the schema at the current offset
|
|
1061
1073
|
def lookahead_matches(lookup: Iterable) -> Optional[SyntaxExpr]:
|
|
1062
1074
|
s = schema[i:]
|
|
1063
|
-
|
|
1064
|
-
return match
|
|
1075
|
+
return next((x for x in lookup if x.regex.match(s)), None)
|
|
1065
1076
|
|
|
1066
1077
|
def advance_single_char() -> None:
|
|
1067
1078
|
nonlocal i, line, pos
|
|
@@ -1109,10 +1120,9 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
1109
1120
|
)
|
|
1110
1121
|
advance_single_char()
|
|
1111
1122
|
return schema[begin:i]
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
return get_backticked()
|
|
1123
|
+
# backticked name
|
|
1124
|
+
advance_single_char()
|
|
1125
|
+
return get_backticked()
|
|
1116
1126
|
|
|
1117
1127
|
def parse_expr(lookup: Iterable[SyntaxExpr], attribute: str) -> str:
|
|
1118
1128
|
"""Parse an expression for an attribute.
|
|
@@ -1283,10 +1293,9 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
1283
1293
|
or "incompatible data types between aggregate function" in str(e).lower()
|
|
1284
1294
|
):
|
|
1285
1295
|
raise SchemaSyntaxError(message=str(e), lineno=line, pos=type_start_pos)
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
raise SchemaSyntaxError(f"Error parsing type: {e}", lineno=line, pos=type_start_pos)
|
|
1296
|
+
# TODO(eclbg): The resulting error message is a bit confusing, as the clickhouse error contains some
|
|
1297
|
+
# references to positions that don't match the position in the schema.
|
|
1298
|
+
raise SchemaSyntaxError(f"Error parsing type: {e}", lineno=line, pos=type_start_pos)
|
|
1290
1299
|
except ModuleNotFoundError:
|
|
1291
1300
|
pass
|
|
1292
1301
|
_type = detected_type
|
|
@@ -1677,8 +1686,9 @@ def parse(
|
|
|
1677
1686
|
|
|
1678
1687
|
if severity == "error":
|
|
1679
1688
|
return raise_deprecation_error
|
|
1680
|
-
|
|
1689
|
+
if severity == "warning":
|
|
1681
1690
|
return add_deprecation_warning
|
|
1691
|
+
return None
|
|
1682
1692
|
|
|
1683
1693
|
return inner
|
|
1684
1694
|
|
|
@@ -2068,6 +2078,8 @@ def parse(
|
|
|
2068
2078
|
"import_query": assign_var("import_query"), # Deprecated, BQ and SFK
|
|
2069
2079
|
"import_table_arn": assign_var("import_table_arn"), # Only for DynamoDB
|
|
2070
2080
|
"import_export_bucket": assign_var("import_export_bucket"), # For DynamoDB
|
|
2081
|
+
"pg_connection_name": assign_var("pg_connection_name"),
|
|
2082
|
+
"pg_table": assign_var("pg_table"),
|
|
2071
2083
|
"shared_with": shared_with,
|
|
2072
2084
|
"export_service": export_service, # Deprecated
|
|
2073
2085
|
"forward_query": forward_query,
|
|
@@ -2128,6 +2140,12 @@ def parse(
|
|
|
2128
2140
|
"gcs_secret": assign_var("gcs_hmac_secret"),
|
|
2129
2141
|
"gcs_hmac_access_id": assign_var("gcs_hmac_access_id"),
|
|
2130
2142
|
"gcs_hmac_secret": assign_var("gcs_hmac_secret"),
|
|
2143
|
+
"pg_host": assign_var("pg_host"),
|
|
2144
|
+
"pg_port": assign_var("pg_port"),
|
|
2145
|
+
"pg_database": assign_var("pg_database"),
|
|
2146
|
+
"pg_user": assign_var("pg_user"),
|
|
2147
|
+
"pg_password": assign_var("pg_password"),
|
|
2148
|
+
"pg_ssl_mode": assign_var("pg_ssl_mode"),
|
|
2131
2149
|
"include": include,
|
|
2132
2150
|
},
|
|
2133
2151
|
}
|
|
@@ -2217,12 +2235,11 @@ def parse(
|
|
|
2217
2235
|
except IndexError as e:
|
|
2218
2236
|
if "node" in line.lower():
|
|
2219
2237
|
raise click.ClickException(FeedbackManager.error_missing_node_name())
|
|
2220
|
-
|
|
2238
|
+
if "sql" in line.lower():
|
|
2221
2239
|
raise click.ClickException(FeedbackManager.error_missing_sql_command())
|
|
2222
|
-
|
|
2240
|
+
if "datasource" in line.lower():
|
|
2223
2241
|
raise click.ClickException(FeedbackManager.error_missing_datasource_name())
|
|
2224
|
-
|
|
2225
|
-
raise ValidationException(f"Validation error, found {line} in line {str(lineno)}: {str(e)}", lineno=lineno)
|
|
2242
|
+
raise ValidationException(f"Validation error, found {line} in line {str(lineno)}: {str(e)}", lineno=lineno)
|
|
2226
2243
|
except IncludeFileNotFoundException as e:
|
|
2227
2244
|
raise IncludeFileNotFoundException(str(e), lineno=lineno)
|
|
2228
2245
|
except Exception as e:
|
|
@@ -2556,12 +2573,11 @@ def get_name_version(ds: str) -> Dict[str, Any]:
|
|
|
2556
2573
|
tk = ds.rsplit("__", 2)
|
|
2557
2574
|
if len(tk) == 1:
|
|
2558
2575
|
return {"name": tk[0], "version": None}
|
|
2559
|
-
|
|
2576
|
+
if len(tk) == 2:
|
|
2560
2577
|
if len(tk[1]):
|
|
2561
2578
|
if tk[1][0] == "v" and _PATTERN_VERSION_NUMBER.match(tk[1][1:]):
|
|
2562
2579
|
return {"name": tk[0], "version": int(tk[1][1:])}
|
|
2563
|
-
|
|
2564
|
-
return {"name": tk[0] + "__" + tk[1], "version": None}
|
|
2580
|
+
return {"name": tk[0] + "__" + tk[1], "version": None}
|
|
2565
2581
|
elif len(tk) == 3 and len(tk[2]):
|
|
2566
2582
|
if tk[2] == "checker":
|
|
2567
2583
|
return {"name": tk[0] + "__" + tk[1] + "__" + tk[2], "version": None}
|
|
@@ -137,9 +137,7 @@ def bump_version(version: str, next_version: Optional[str]) -> str:
|
|
|
137
137
|
|
|
138
138
|
|
|
139
139
|
def get_default_init_files_deploy(workspace_name: str) -> Dict[str, str]:
|
|
140
|
-
|
|
140
|
+
return {
|
|
141
141
|
path.replace("tinybird_", f"tinybird_{workspace_name.lower()}_"): content
|
|
142
142
|
for path, content in DEFAULT_INIT_FILES_DEPLOY.items()
|
|
143
143
|
}
|
|
144
|
-
|
|
145
|
-
return modified_files
|
|
@@ -48,6 +48,7 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
48
48
|
{"name": "client_ip", "type": "Nullable(String)"},
|
|
49
49
|
{"name": "resource_tags", "type": "Array(String)"},
|
|
50
50
|
{"name": "memory_usage", "type": "UInt64"},
|
|
51
|
+
{"name": "replica", "type": "String"},
|
|
51
52
|
],
|
|
52
53
|
},
|
|
53
54
|
{
|
|
@@ -333,6 +334,26 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
333
334
|
{"name": "job_metadata", "type": "String"},
|
|
334
335
|
],
|
|
335
336
|
},
|
|
337
|
+
{
|
|
338
|
+
"name": "tinybird.cluster_control_log",
|
|
339
|
+
"description": "Actions applied by cluster control in your workspace to keep the load of your cluster under control: one row every time cluster control applies, updates, or clears the concurrency limit of an endpoint. rate_limit_type is the control family, currently always endpoint_concurrency. action is the transition: applied, updated, or cleared. limit_metadata is a JSON object with the inputs of the decision and the resulting limit, read it with JSONExtract functions; its keys are max_concurrent_queries (UInt64, the limit in force after the transition), change_reason (String), analysis_window_seconds (UInt64), and the nullable estimated_qps, request_count, observed_qps, error_count, success_count, error_to_success_ratio, rate_limited_request_count, degradation_reason, pipe_cpu_time, total_cpu_time, pipe_cpu_ratio and max_cpu_ratio. This data source has a TTL of 6 months.",
|
|
340
|
+
"dateColumn": "timestamp",
|
|
341
|
+
"engine": {
|
|
342
|
+
"engine": "MergeTree",
|
|
343
|
+
"sorting_key": "timestamp, pipe_name",
|
|
344
|
+
"partition_key": "toYYYYMM(timestamp)",
|
|
345
|
+
"ttl": "toStartOfMonth(toDateTime(timestamp)) + toIntervalMonth(6)",
|
|
346
|
+
},
|
|
347
|
+
"columns": [
|
|
348
|
+
{"name": "timestamp", "type": "DateTime64(3)"},
|
|
349
|
+
{"name": "workspace_id", "type": "String"},
|
|
350
|
+
{"name": "workspace_name", "type": "String"},
|
|
351
|
+
{"name": "pipe_name", "type": "String"},
|
|
352
|
+
{"name": "rate_limit_type", "type": "LowCardinality(String)"},
|
|
353
|
+
{"name": "action", "type": "LowCardinality(String)"},
|
|
354
|
+
{"name": "limit_metadata", "type": "String"},
|
|
355
|
+
],
|
|
356
|
+
},
|
|
336
357
|
{
|
|
337
358
|
"name": "tinybird.hook_log",
|
|
338
359
|
"description": "Log of hook executions and their results.",
|
|
@@ -518,22 +539,6 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
518
539
|
{"name": "origin", "type": "String"},
|
|
519
540
|
],
|
|
520
541
|
},
|
|
521
|
-
{
|
|
522
|
-
"name": "organization.processed_data",
|
|
523
|
-
"description": "Information related to all processed data per day per workspace.",
|
|
524
|
-
"dateColumn": "date",
|
|
525
|
-
"engine": {
|
|
526
|
-
"engine": "SummingMergeTree",
|
|
527
|
-
"sorting_key": "database, date",
|
|
528
|
-
"partition_key": "toYYYYMM(date)",
|
|
529
|
-
},
|
|
530
|
-
"columns": [
|
|
531
|
-
{"name": "date", "type": "Date"},
|
|
532
|
-
{"name": "database", "type": "String"},
|
|
533
|
-
{"name": "read_bytes", "type": "UInt64"},
|
|
534
|
-
{"name": "written_bytes", "type": "UInt64"},
|
|
535
|
-
],
|
|
536
|
-
},
|
|
537
542
|
{
|
|
538
543
|
"name": "organization.datasources_storage",
|
|
539
544
|
"description": "Similar to tinybird.datasources_storage but with data for all Organization Workspaces.",
|
|
@@ -683,6 +688,7 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
683
688
|
{"name": "user_agent", "type": "Nullable(String)"},
|
|
684
689
|
{"name": "resource_tags", "type": "Array(String)"},
|
|
685
690
|
{"name": "memory_usage", "type": "UInt64"},
|
|
691
|
+
{"name": "replica", "type": "String"},
|
|
686
692
|
],
|
|
687
693
|
},
|
|
688
694
|
{
|
|
@@ -726,6 +732,26 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
726
732
|
{"name": "job_metadata", "type": "String"},
|
|
727
733
|
],
|
|
728
734
|
},
|
|
735
|
+
{
|
|
736
|
+
"name": "organization.cluster_control_log",
|
|
737
|
+
"description": "Actions applied by cluster control across all the workspaces in your organization to keep the load of your cluster under control: one row every time cluster control applies, updates, or clears the concurrency limit of an endpoint. workspace_id and workspace_name identify the affected workspace. rate_limit_type is the control family, currently always endpoint_concurrency. action is the transition: applied, updated, or cleared. limit_metadata is a JSON object with the inputs of the decision and the resulting limit, read it with JSONExtract functions; its keys are max_concurrent_queries (UInt64, the limit in force after the transition), change_reason (String), analysis_window_seconds (UInt64), and the nullable estimated_qps, request_count, observed_qps, error_count, success_count, error_to_success_ratio, rate_limited_request_count, degradation_reason, pipe_cpu_time, total_cpu_time, pipe_cpu_ratio and max_cpu_ratio. This data source has a TTL of 6 months.",
|
|
738
|
+
"dateColumn": "timestamp",
|
|
739
|
+
"engine": {
|
|
740
|
+
"engine": "MergeTree",
|
|
741
|
+
"sorting_key": "workspace_id, timestamp, pipe_name",
|
|
742
|
+
"partition_key": "toYYYYMM(timestamp)",
|
|
743
|
+
"ttl": "toStartOfMonth(toDateTime(timestamp)) + toIntervalMonth(6)",
|
|
744
|
+
},
|
|
745
|
+
"columns": [
|
|
746
|
+
{"name": "timestamp", "type": "DateTime64(3)"},
|
|
747
|
+
{"name": "workspace_id", "type": "String"},
|
|
748
|
+
{"name": "workspace_name", "type": "String"},
|
|
749
|
+
{"name": "pipe_name", "type": "String"},
|
|
750
|
+
{"name": "rate_limit_type", "type": "LowCardinality(String)"},
|
|
751
|
+
{"name": "action", "type": "LowCardinality(String)"},
|
|
752
|
+
{"name": "limit_metadata", "type": "String"},
|
|
753
|
+
],
|
|
754
|
+
},
|
|
729
755
|
{
|
|
730
756
|
"name": "organization.sinks_ops_log",
|
|
731
757
|
"description": "Historic Logs for all Sink job executions across the organization",
|
|
@@ -493,7 +493,6 @@ def replace_tables_chquery_cached(
|
|
|
493
493
|
sorted_replacements: Optional[tuple] = None,
|
|
494
494
|
default_database: str = "",
|
|
495
495
|
output_one_line: bool = False,
|
|
496
|
-
timestamp: Optional[datetime] = None,
|
|
497
496
|
function_allow_list: Optional[FrozenSet[str]] = None,
|
|
498
497
|
settings_allow_list: Optional[FrozenSet[str]] = None,
|
|
499
498
|
) -> str:
|
|
@@ -536,7 +535,6 @@ def replace_tables(
|
|
|
536
535
|
sql,
|
|
537
536
|
None,
|
|
538
537
|
output_one_line=output_one_line,
|
|
539
|
-
timestamp=timestamp,
|
|
540
538
|
function_allow_list=hashable_list,
|
|
541
539
|
settings_allow_list=hashable_settings_list,
|
|
542
540
|
)
|
|
@@ -610,7 +608,6 @@ def replace_tables(
|
|
|
610
608
|
sql,
|
|
611
609
|
None,
|
|
612
610
|
output_one_line=output_one_line,
|
|
613
|
-
timestamp=timestamp,
|
|
614
611
|
function_allow_list=hashable_list,
|
|
615
612
|
settings_allow_list=hashable_settings_list,
|
|
616
613
|
)
|
|
@@ -649,7 +646,6 @@ def replace_tables(
|
|
|
649
646
|
r,
|
|
650
647
|
default_database=default_database,
|
|
651
648
|
output_one_line=output_one_line,
|
|
652
|
-
timestamp=timestamp,
|
|
653
649
|
function_allow_list=hashable_list,
|
|
654
650
|
settings_allow_list=hashable_settings_list,
|
|
655
651
|
)
|
|
@@ -658,7 +654,6 @@ def replace_tables(
|
|
|
658
654
|
sql,
|
|
659
655
|
None,
|
|
660
656
|
output_one_line=output_one_line,
|
|
661
|
-
timestamp=timestamp,
|
|
662
657
|
function_allow_list=hashable_list,
|
|
663
658
|
settings_allow_list=hashable_settings_list,
|
|
664
659
|
)
|
|
@@ -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.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '4.6.17'
|
|
8
|
+
__revision__ = '92350bf'
|
|
@@ -811,6 +811,9 @@ class TinyB:
|
|
|
811
811
|
def job_cancel(self, job_id: str):
|
|
812
812
|
return self._req(f"/v0/jobs/{job_id}/cancel", method="POST", data=b"")
|
|
813
813
|
|
|
814
|
+
def job_retry(self, job_id: str) -> Dict[str, Any]:
|
|
815
|
+
return self._req(f"/v0/jobs/{job_id}/retry", method="POST", data=b"")
|
|
816
|
+
|
|
814
817
|
def user_workspaces(self, version: str = "v0"):
|
|
815
818
|
data = self._req(f"/{version}/user/workspaces/?with_environments=false")
|
|
816
819
|
# TODO: this is repeated in local_common.py but I'm avoiding circular imports
|
|
@@ -833,8 +836,8 @@ class TinyB:
|
|
|
833
836
|
def user_workspace_branches(self, version: str = "v0"):
|
|
834
837
|
return self._req(f"/{version}/user/workspaces/?with_environments=true&only_environments=true")
|
|
835
838
|
|
|
836
|
-
def branches(self):
|
|
837
|
-
return self._req("/
|
|
839
|
+
def branches(self, version: str = "v1"):
|
|
840
|
+
return self._req(f"/{version}/environments")
|
|
838
841
|
|
|
839
842
|
def releases(self, workspace_id):
|
|
840
843
|
return self._req(f"/v0/workspaces/{workspace_id}/releases")
|
|
@@ -44,7 +44,7 @@ def process(
|
|
|
44
44
|
|
|
45
45
|
# Ensure SHARED_WITH workspaces exist before build
|
|
46
46
|
if not is_branch:
|
|
47
|
-
build_shared_with_workspaces(project=project, tb_client=tb_client
|
|
47
|
+
build_shared_with_workspaces(project=project, tb_client=tb_client)
|
|
48
48
|
|
|
49
49
|
build_failed = False
|
|
50
50
|
build_error: Optional[str] = None
|
|
@@ -90,9 +90,7 @@ def process(
|
|
|
90
90
|
click.echo(FeedbackManager.error(message=f"✗ {rebuild_str} failed"))
|
|
91
91
|
if not watch and exit_on_error:
|
|
92
92
|
sys_exit("build_error", build_error or "Unknown error")
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return build_error
|
|
93
|
+
return build_error or "Unknown error"
|
|
96
94
|
|
|
97
95
|
if not silent:
|
|
98
96
|
if build_result == False: # noqa: E712
|
|
@@ -250,7 +248,7 @@ def build_project(
|
|
|
250
248
|
if with_connections:
|
|
251
249
|
echo_dynamodb_local_backfill_feedback(build)
|
|
252
250
|
return True
|
|
253
|
-
|
|
251
|
+
if build_result == "failed":
|
|
254
252
|
error = format_build_errors(result.get("errors", []))
|
|
255
253
|
else:
|
|
256
254
|
error = f"Unknown build result. Error: {result.get('error')}"
|
|
@@ -614,7 +612,7 @@ def build_vendored_workspaces(project: Project, tb_client: TinyB, config: dict[s
|
|
|
614
612
|
click.echo(FeedbackManager.error_exception(error=e))
|
|
615
613
|
|
|
616
614
|
|
|
617
|
-
def build_shared_with_workspaces(project: Project, tb_client: TinyB
|
|
615
|
+
def build_shared_with_workspaces(project: Project, tb_client: TinyB) -> None:
|
|
618
616
|
"""Scan project for .datasource files and ensure SHARED_WITH workspaces exist."""
|
|
619
617
|
|
|
620
618
|
try:
|
|
@@ -18,7 +18,7 @@ from copy import deepcopy
|
|
|
18
18
|
from enum import Enum
|
|
19
19
|
from os import getcwd, getenv
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
from typing import Any, Callable, Dict, Iterable, List, Literal, Optional, Set, Tuple, TypedDict, Union
|
|
21
|
+
from typing import Any, Callable, Dict, Iterable, List, Literal, NoReturn, Optional, Set, Tuple, TypedDict, Union
|
|
22
22
|
from urllib.parse import urlparse
|
|
23
23
|
|
|
24
24
|
import click
|
|
@@ -2370,7 +2370,7 @@ def ask_for_organization(
|
|
|
2370
2370
|
event_error_separator = "__error__"
|
|
2371
2371
|
|
|
2372
2372
|
|
|
2373
|
-
def sys_exit(event: str, msg: str) ->
|
|
2373
|
+
def sys_exit(event: str, msg: str) -> NoReturn:
|
|
2374
2374
|
sys.exit(f"{event}{event_error_separator}{msg}")
|
|
2375
2375
|
|
|
2376
2376
|
|
|
@@ -155,16 +155,13 @@ def api_fetch(url: str, headers: dict, request_from: Optional[str] = None) -> di
|
|
|
155
155
|
return {}
|
|
156
156
|
|
|
157
157
|
|
|
158
|
-
def _get_classic_workspace_branches(client: TinyB
|
|
159
|
-
|
|
160
|
-
return [branch for branch in branches if str(branch.get("main")) == workspace_id]
|
|
158
|
+
def _get_classic_workspace_branches(client: TinyB) -> list[dict[str, Any]]:
|
|
159
|
+
return client.branches(version="v0").get("environments", [])
|
|
161
160
|
|
|
162
161
|
|
|
163
|
-
def _cleanup_classic_migration_blockers(client: TinyB
|
|
164
|
-
workspace_id = str(config["id"])
|
|
165
|
-
|
|
162
|
+
def _cleanup_classic_migration_blockers(client: TinyB) -> None:
|
|
166
163
|
try:
|
|
167
|
-
branches = _get_classic_workspace_branches(client
|
|
164
|
+
branches = _get_classic_workspace_branches(client)
|
|
168
165
|
if not branches:
|
|
169
166
|
return
|
|
170
167
|
|
|
@@ -488,7 +485,7 @@ def migrate_to_forward(ctx: click.Context, allow_destructive_operations: bool) -
|
|
|
488
485
|
click.echo(FeedbackManager.info(message="Migration cancelled."))
|
|
489
486
|
return
|
|
490
487
|
|
|
491
|
-
_cleanup_classic_migration_blockers(client
|
|
488
|
+
_cleanup_classic_migration_blockers(client)
|
|
492
489
|
_persist_migrate_to_forward_config(project)
|
|
493
490
|
migrate_to_forward_workspace(client=client, output=output, dry_run=False)
|
|
494
491
|
create_deployment(
|