tinybird 4.6.17.dev0__tar.gz → 4.6.18__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.17.dev0 → tinybird-4.6.18}/PKG-INFO +16 -1
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/ch_utils/engine.py +7 -12
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/client.py +14 -26
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/datafile/common.py +20 -25
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/git_settings.py +1 -3
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/service_datasources.py +6 -4
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/sql.py +3 -4
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/sql_template.py +52 -71
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/sql_template_fmt.py +8 -13
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/sql_toolset.py +3 -5
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/syncasync.py +9 -11
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/client.py +17 -23
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/build_common.py +4 -6
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/cicd.py +1 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/cli.py +4 -2
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/common.py +10 -14
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/config.py +1 -2
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/connection_kafka.py +1 -2
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/connection_s3.py +13 -18
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/create.py +3 -6
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/build.py +2 -3
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/build_pipe.py +1 -4
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/diff.py +2 -1
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/format_common.py +9 -10
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/format_connection.py +1 -2
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/format_datasource.py +1 -2
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/format_pipe.py +1 -2
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/pipe_checker.py +6 -7
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/playground.py +3 -4
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datasource.py +7 -8
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/deployment_common.py +28 -7
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/feedback_manager.py +1 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/job.py +22 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird.egg-info/PKG-INFO +16 -1
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/setup.cfg +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/__cli__.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/check_pypi.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/config.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/context.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/datatypes.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/feedback_manager.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/iterating/__init__.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/iterating/data_branch_modes.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/prompts.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/cli.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/config.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/connection_dynamodb.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/infra.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/logs.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/project.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/token.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird/tornado_template.py +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.6.17.dev0 → tinybird-4.6.18}/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.18
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -52,6 +52,21 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
54
|
|
|
55
|
+
4.6.18
|
|
56
|
+
********
|
|
57
|
+
|
|
58
|
+
- `Fixed` CLI commands (for example ``tb migrate-to-forward``) no longer abort on startup when the best-effort refresh of the cached workspace id/name fails for a reason other than authentication.
|
|
59
|
+
|
|
60
|
+
4.6.17
|
|
61
|
+
********
|
|
62
|
+
|
|
63
|
+
- `Added` ``tb job retry <job_id>`` to retry eligible import and S3/GCS sync jobs in ``error`` or ``cancelled`` status.
|
|
64
|
+
|
|
65
|
+
4.6.16
|
|
66
|
+
********
|
|
67
|
+
|
|
68
|
+
- `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.
|
|
69
|
+
|
|
55
70
|
4.6.15
|
|
56
71
|
********
|
|
57
72
|
|
|
@@ -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]:
|
|
@@ -699,8 +695,7 @@ def ttl_from_engine(engine: str) -> Optional[str]:
|
|
|
699
695
|
return None
|
|
700
696
|
settings_array = engine.split(" SETTINGS ")
|
|
701
697
|
settings = " SETTINGS " + settings_array[1] if len(settings_array) > 1 else None
|
|
702
|
-
|
|
703
|
-
return ttl
|
|
698
|
+
return ttl_array[1][: -(len(settings))] if settings else ttl_array[1]
|
|
704
699
|
|
|
705
700
|
|
|
706
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}
|
|
@@ -502,13 +502,12 @@ class Datafile:
|
|
|
502
502
|
f"For Kafka sinks, provide 'export_kafka_topic'. "
|
|
503
503
|
f"For S3/GCS sinks, provide 'export_bucket_uri' and 'export_file_template'."
|
|
504
504
|
)
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
)
|
|
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
|
+
)
|
|
512
511
|
|
|
513
512
|
# Validate schedule format (common for both Kafka and S3/GCS)
|
|
514
513
|
export_schedule = node.get("export_schedule")
|
|
@@ -1073,8 +1072,7 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
1073
1072
|
# Find the first SyntaxExpr in lookup that matches the schema at the current offset
|
|
1074
1073
|
def lookahead_matches(lookup: Iterable) -> Optional[SyntaxExpr]:
|
|
1075
1074
|
s = schema[i:]
|
|
1076
|
-
|
|
1077
|
-
return match
|
|
1075
|
+
return next((x for x in lookup if x.regex.match(s)), None)
|
|
1078
1076
|
|
|
1079
1077
|
def advance_single_char() -> None:
|
|
1080
1078
|
nonlocal i, line, pos
|
|
@@ -1122,10 +1120,9 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
1122
1120
|
)
|
|
1123
1121
|
advance_single_char()
|
|
1124
1122
|
return schema[begin:i]
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
return get_backticked()
|
|
1123
|
+
# backticked name
|
|
1124
|
+
advance_single_char()
|
|
1125
|
+
return get_backticked()
|
|
1129
1126
|
|
|
1130
1127
|
def parse_expr(lookup: Iterable[SyntaxExpr], attribute: str) -> str:
|
|
1131
1128
|
"""Parse an expression for an attribute.
|
|
@@ -1296,10 +1293,9 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
1296
1293
|
or "incompatible data types between aggregate function" in str(e).lower()
|
|
1297
1294
|
):
|
|
1298
1295
|
raise SchemaSyntaxError(message=str(e), lineno=line, pos=type_start_pos)
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
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)
|
|
1303
1299
|
except ModuleNotFoundError:
|
|
1304
1300
|
pass
|
|
1305
1301
|
_type = detected_type
|
|
@@ -1690,8 +1686,9 @@ def parse(
|
|
|
1690
1686
|
|
|
1691
1687
|
if severity == "error":
|
|
1692
1688
|
return raise_deprecation_error
|
|
1693
|
-
|
|
1689
|
+
if severity == "warning":
|
|
1694
1690
|
return add_deprecation_warning
|
|
1691
|
+
return None
|
|
1695
1692
|
|
|
1696
1693
|
return inner
|
|
1697
1694
|
|
|
@@ -2238,12 +2235,11 @@ def parse(
|
|
|
2238
2235
|
except IndexError as e:
|
|
2239
2236
|
if "node" in line.lower():
|
|
2240
2237
|
raise click.ClickException(FeedbackManager.error_missing_node_name())
|
|
2241
|
-
|
|
2238
|
+
if "sql" in line.lower():
|
|
2242
2239
|
raise click.ClickException(FeedbackManager.error_missing_sql_command())
|
|
2243
|
-
|
|
2240
|
+
if "datasource" in line.lower():
|
|
2244
2241
|
raise click.ClickException(FeedbackManager.error_missing_datasource_name())
|
|
2245
|
-
|
|
2246
|
-
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)
|
|
2247
2243
|
except IncludeFileNotFoundException as e:
|
|
2248
2244
|
raise IncludeFileNotFoundException(str(e), lineno=lineno)
|
|
2249
2245
|
except Exception as e:
|
|
@@ -2577,12 +2573,11 @@ def get_name_version(ds: str) -> Dict[str, Any]:
|
|
|
2577
2573
|
tk = ds.rsplit("__", 2)
|
|
2578
2574
|
if len(tk) == 1:
|
|
2579
2575
|
return {"name": tk[0], "version": None}
|
|
2580
|
-
|
|
2576
|
+
if len(tk) == 2:
|
|
2581
2577
|
if len(tk[1]):
|
|
2582
2578
|
if tk[1][0] == "v" and _PATTERN_VERSION_NUMBER.match(tk[1][1:]):
|
|
2583
2579
|
return {"name": tk[0], "version": int(tk[1][1:])}
|
|
2584
|
-
|
|
2585
|
-
return {"name": tk[0] + "__" + tk[1], "version": None}
|
|
2580
|
+
return {"name": tk[0] + "__" + tk[1], "version": None}
|
|
2586
2581
|
elif len(tk) == 3 and len(tk[2]):
|
|
2587
2582
|
if tk[2] == "checker":
|
|
2588
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
|
|
@@ -335,13 +335,14 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
335
335
|
],
|
|
336
336
|
},
|
|
337
337
|
{
|
|
338
|
-
"name": "tinybird.
|
|
339
|
-
"description": "
|
|
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
340
|
"dateColumn": "timestamp",
|
|
341
341
|
"engine": {
|
|
342
342
|
"engine": "MergeTree",
|
|
343
343
|
"sorting_key": "timestamp, pipe_name",
|
|
344
344
|
"partition_key": "toYYYYMM(timestamp)",
|
|
345
|
+
"ttl": "toStartOfMonth(toDateTime(timestamp)) + toIntervalMonth(6)",
|
|
345
346
|
},
|
|
346
347
|
"columns": [
|
|
347
348
|
{"name": "timestamp", "type": "DateTime64(3)"},
|
|
@@ -732,13 +733,14 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
732
733
|
],
|
|
733
734
|
},
|
|
734
735
|
{
|
|
735
|
-
"name": "organization.
|
|
736
|
-
"description": "
|
|
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.",
|
|
737
738
|
"dateColumn": "timestamp",
|
|
738
739
|
"engine": {
|
|
739
740
|
"engine": "MergeTree",
|
|
740
741
|
"sorting_key": "workspace_id, timestamp, pipe_name",
|
|
741
742
|
"partition_key": "toYYYYMM(timestamp)",
|
|
743
|
+
"ttl": "toStartOfMonth(toDateTime(timestamp)) + toIntervalMonth(6)",
|
|
742
744
|
},
|
|
743
745
|
"columns": [
|
|
744
746
|
{"name": "timestamp", "type": "DateTime64(3)"},
|
|
@@ -675,10 +675,9 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
675
675
|
)
|
|
676
676
|
advance_single_char()
|
|
677
677
|
return schema[begin:i]
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
return get_backticked()
|
|
678
|
+
# backticked name
|
|
679
|
+
advance_single_char()
|
|
680
|
+
return get_backticked()
|
|
682
681
|
|
|
683
682
|
def parse_expr(lookup: Iterable[SyntaxExpr]) -> str:
|
|
684
683
|
nonlocal i, line, pos
|
|
@@ -142,8 +142,7 @@ def transform_type(
|
|
|
142
142
|
if x is None:
|
|
143
143
|
if defined:
|
|
144
144
|
raise SQLTemplateException(REQUIRED_PARAM_NOT_DEFINED, documentation="/cli/advanced-templates.html")
|
|
145
|
-
|
|
146
|
-
return None
|
|
145
|
+
return None
|
|
147
146
|
if tester == "String":
|
|
148
147
|
if x is not None:
|
|
149
148
|
return transform(x)
|
|
@@ -167,12 +166,11 @@ def _and(*args, **kwargs):
|
|
|
167
166
|
tk = k.rsplit("__", 1)
|
|
168
167
|
if len(tk) == 1:
|
|
169
168
|
return "="
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
)
|
|
169
|
+
if tk[1] in operands:
|
|
170
|
+
return operands[tk[1]]
|
|
171
|
+
raise SQLTemplateException(
|
|
172
|
+
f"operand {tk[1]} not supported", documentation="/cli/advanced-templates.html#sql_and"
|
|
173
|
+
)
|
|
176
174
|
|
|
177
175
|
return Expression(
|
|
178
176
|
" and ".join([f"{_name(k)} {_op(k)} {expression_wrapper(v, k)}" for k, v in kwargs.items() if v is not None])
|
|
@@ -277,8 +275,7 @@ def columns(x, default=None, fn=None):
|
|
|
277
275
|
|
|
278
276
|
if fn:
|
|
279
277
|
return Expression(",".join(f"{fn}({str(column(c, c))}) as {c}" for c in _columns))
|
|
280
|
-
|
|
281
|
-
return Expression(",".join(str(column(c, c)) for c in _columns))
|
|
278
|
+
return Expression(",".join(str(column(c, c)) for c in _columns))
|
|
282
279
|
|
|
283
280
|
|
|
284
281
|
def column(x, default=None):
|
|
@@ -368,11 +365,10 @@ def boolean(x, default=None):
|
|
|
368
365
|
if default is None:
|
|
369
366
|
return 0
|
|
370
367
|
return boolean(default)
|
|
371
|
-
|
|
368
|
+
if isinstance(x, Placeholder):
|
|
372
369
|
return boolean(default)
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
return 0
|
|
370
|
+
if isinstance(x, str) and (x == "0" or x.lower() == "false"):
|
|
371
|
+
return 0
|
|
376
372
|
|
|
377
373
|
return int(bool(x))
|
|
378
374
|
|
|
@@ -403,8 +399,7 @@ def array_type(types):
|
|
|
403
399
|
raise SQLTemplateException(
|
|
404
400
|
REQUIRED_PARAM_NOT_DEFINED, documentation="/cli/advanced-templates.html"
|
|
405
401
|
)
|
|
406
|
-
|
|
407
|
-
return None
|
|
402
|
+
return None
|
|
408
403
|
values = []
|
|
409
404
|
list_values = x if type(x) == list else x.split(",") # noqa: E721
|
|
410
405
|
for i, t in enumerate(list_values):
|
|
@@ -744,12 +739,11 @@ def __date_diff(
|
|
|
744
739
|
|
|
745
740
|
if unit == "days":
|
|
746
741
|
return int(diff / 86400)
|
|
747
|
-
|
|
742
|
+
if unit == "hours":
|
|
748
743
|
return int(diff / 3600)
|
|
749
|
-
|
|
744
|
+
if unit == "minutes":
|
|
750
745
|
return int(diff / 60)
|
|
751
|
-
|
|
752
|
-
return int(diff)
|
|
746
|
+
return int(diff)
|
|
753
747
|
except Exception:
|
|
754
748
|
if none_if_error:
|
|
755
749
|
return None
|
|
@@ -1348,9 +1342,9 @@ def escape_single_quote_str(s):
|
|
|
1348
1342
|
def expression_wrapper(x, name, escape_arrays: bool = False):
|
|
1349
1343
|
if type(x) in (unicode_type, bytes, str):
|
|
1350
1344
|
return "'" + sqlescape_for_string_expression(x) + "'"
|
|
1351
|
-
|
|
1345
|
+
if isinstance(x, Placeholder):
|
|
1352
1346
|
return "'__no_value__'"
|
|
1353
|
-
|
|
1347
|
+
if isinstance(x, Comment):
|
|
1354
1348
|
return "-- {x} \n"
|
|
1355
1349
|
if x is None:
|
|
1356
1350
|
truncated_name = name[:20] + "..." if len(name) > 20 else name
|
|
@@ -1361,10 +1355,7 @@ def expression_wrapper(x, name, escape_arrays: bool = False):
|
|
|
1361
1355
|
logging.warning(f"expression_wrapper -> list :{x}:")
|
|
1362
1356
|
|
|
1363
1357
|
try:
|
|
1364
|
-
|
|
1365
|
-
f"[{','.join(escape_single_quote_str(item) if isinstance(item, str) else str(item) for item in x)}]"
|
|
1366
|
-
)
|
|
1367
|
-
return result
|
|
1358
|
+
return f"[{','.join(escape_single_quote_str(item) if isinstance(item, str) else str(item) for item in x)}]"
|
|
1368
1359
|
except Exception as e:
|
|
1369
1360
|
logging.error(f"Error escaping array: {e}")
|
|
1370
1361
|
return x
|
|
@@ -1425,20 +1416,18 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1425
1416
|
# secret available: Always use workspace secret regardless of test mode
|
|
1426
1417
|
template_execution_results.add_ch_param(x)
|
|
1427
1418
|
return Symbol("{" + sqlescape(x) + ": String}")
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
f"Cannot access secret '{x}'. Check the secret exists in the Workspace and the token has the required scope."
|
|
1441
|
-
)
|
|
1419
|
+
# secret not available: Check test mode and defaults
|
|
1420
|
+
is_test_mode = TB_SECRET_IN_TEST_MODE in template_execution_results
|
|
1421
|
+
if default is not None:
|
|
1422
|
+
# Use provided default value
|
|
1423
|
+
return default
|
|
1424
|
+
if is_test_mode:
|
|
1425
|
+
# In test mode without default - return placeholder
|
|
1426
|
+
return Symbol("{" + sqlescape(x) + ": String}")
|
|
1427
|
+
# Not in test mode, no secret, no default - raise error
|
|
1428
|
+
raise SQLTemplateException(
|
|
1429
|
+
f"Cannot access secret '{x}'. Check the secret exists in the Workspace and the token has the required scope."
|
|
1430
|
+
)
|
|
1442
1431
|
except Exception:
|
|
1443
1432
|
raise SQLTemplateException(
|
|
1444
1433
|
f"Cannot access secret '{x}'. Check the secret exists in the Workspace and the token has the required scope."
|
|
@@ -1522,14 +1511,12 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1522
1511
|
|
|
1523
1512
|
if line:
|
|
1524
1513
|
raise SQLTemplateException(f"{message.strip()} line {line[0]}")
|
|
1525
|
-
|
|
1526
|
-
raise SQLTemplateException(f"{message.strip()}")
|
|
1514
|
+
raise SQLTemplateException(f"{message.strip()}")
|
|
1527
1515
|
except Exception as e:
|
|
1528
1516
|
if isinstance(e, SQLTemplateException):
|
|
1529
1517
|
raise e
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
raise ValueError(str(e))
|
|
1518
|
+
logging.exception(f"Error on unbound local error: {e}")
|
|
1519
|
+
raise ValueError(str(e))
|
|
1533
1520
|
except TypeError as e:
|
|
1534
1521
|
error = str(e)
|
|
1535
1522
|
if "not supported between instances of 'Placeholder' and " in str(e):
|
|
@@ -1960,29 +1947,27 @@ def get_var_data(content, node_id=None):
|
|
|
1960
1947
|
# ast.Constant nodes, so .value holds str/bytes/int/float/bool/None.
|
|
1961
1948
|
if type(x) == ast.Constant: # noqa: E721
|
|
1962
1949
|
return x.value
|
|
1963
|
-
|
|
1950
|
+
if type(x) == ast.Name: # noqa: E721
|
|
1964
1951
|
return x.id
|
|
1965
|
-
|
|
1952
|
+
if type(x) == ast.List: # noqa: E721
|
|
1966
1953
|
# List can hold different types
|
|
1967
1954
|
return _get_list_var_data(x)
|
|
1968
|
-
|
|
1955
|
+
if type(x) == ast.BinOp: # noqa: E721
|
|
1969
1956
|
# in this case there could be several variables
|
|
1970
1957
|
# if that's the case the left one is the main
|
|
1971
1958
|
r = node_to_value(x.left)
|
|
1972
1959
|
if not r:
|
|
1973
1960
|
r = node_to_value(x.right)
|
|
1974
1961
|
return r
|
|
1975
|
-
|
|
1962
|
+
if type(x) == ast.UnaryOp and type(x.operand) == ast.Constant: # noqa: E721
|
|
1976
1963
|
if type(x.op) == ast.USub: # noqa: E721
|
|
1977
1964
|
return x.operand.value * -1
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
# don't let this ruin the parsing
|
|
1985
|
-
pass
|
|
1965
|
+
return x.operand.value
|
|
1966
|
+
try:
|
|
1967
|
+
return x.id
|
|
1968
|
+
except Exception:
|
|
1969
|
+
# don't let this ruin the parsing
|
|
1970
|
+
pass
|
|
1986
1971
|
return None
|
|
1987
1972
|
|
|
1988
1973
|
def _get_list_var_data(x):
|
|
@@ -1994,7 +1979,7 @@ def get_var_data(content, node_id=None):
|
|
|
1994
1979
|
# ast.Bytes/ast.Str/ast.Num/ast.NameConstant (removed in 3.14).
|
|
1995
1980
|
if type(first_elem) == ast.Constant: # noqa: E721
|
|
1996
1981
|
return [elem.value for elem in x.elts]
|
|
1997
|
-
|
|
1982
|
+
if type(first_elem) == ast.Name: # noqa: E721
|
|
1998
1983
|
return [elem.id for elem in x.elts]
|
|
1999
1984
|
|
|
2000
1985
|
return []
|
|
@@ -2013,8 +1998,7 @@ def get_var_data(content, node_id=None):
|
|
|
2013
1998
|
# to just `ast.parse(content)` once we confirm all environments use patched Python versions.
|
|
2014
1999
|
def parse_content(content, retries=0):
|
|
2015
2000
|
try:
|
|
2016
|
-
|
|
2017
|
-
return parsed
|
|
2001
|
+
return ast.parse(content)
|
|
2018
2002
|
except Exception as e:
|
|
2019
2003
|
if "AST constructor recursion depth mismatch" not in str(e):
|
|
2020
2004
|
raise e
|
|
@@ -2042,8 +2026,7 @@ def get_var_data(content, node_id=None):
|
|
|
2042
2026
|
if type(x) == ast.Call: # noqa: E721
|
|
2043
2027
|
# Nested calls are traversed via `ast.iter_child_nodes` below.
|
|
2044
2028
|
continue
|
|
2045
|
-
|
|
2046
|
-
args.append(node_to_value(x))
|
|
2029
|
+
args.append(node_to_value(x))
|
|
2047
2030
|
|
|
2048
2031
|
kwargs = {}
|
|
2049
2032
|
for x in node.keywords:
|
|
@@ -2531,8 +2514,7 @@ def format_SQLTemplateException_message(e: SQLTemplateException, vars_and_types:
|
|
|
2531
2514
|
f"{REQUIRED_PARAM_NOT_DEFINED}. Check the parameters {join_with_different_last_separator(vars_with_default_none)}. Please provide a value or set a default value in the pipe code.",
|
|
2532
2515
|
e.documentation,
|
|
2533
2516
|
)
|
|
2534
|
-
|
|
2535
|
-
raise e
|
|
2517
|
+
raise e
|
|
2536
2518
|
|
|
2537
2519
|
|
|
2538
2520
|
def render_sql_template(
|
|
@@ -2913,12 +2895,12 @@ def render_sql_template(
|
|
|
2913
2895
|
# https://gitlab.com/tinybird/analytics/-/issues/943
|
|
2914
2896
|
if "length" in v and not v["length"]:
|
|
2915
2897
|
raise SQLTemplateException("length cannot be used as a variable name or as a function inside of a template")
|
|
2916
|
-
|
|
2898
|
+
if "missing 1 required positional argument" in str(e):
|
|
2917
2899
|
raise SQLTemplateException(
|
|
2918
2900
|
"one of the transform type functions is missing an argument",
|
|
2919
2901
|
documentation="/cli/advanced-templates.html#transform-types-functions",
|
|
2920
2902
|
)
|
|
2921
|
-
|
|
2903
|
+
if "not callable" in str(e) or "unhashable type" in str(e):
|
|
2922
2904
|
raise SQLTemplateException(
|
|
2923
2905
|
"wrong syntax, you might be using a not valid function inside a control block",
|
|
2924
2906
|
documentation="/cli/advanced-templates.html",
|
|
@@ -3063,7 +3045,7 @@ def render_template_with_secrets(
|
|
|
3063
3045
|
)
|
|
3064
3046
|
return '""'
|
|
3065
3047
|
return value
|
|
3066
|
-
|
|
3048
|
+
if default is not None:
|
|
3067
3049
|
if isinstance(default, str) and len(default) == 0:
|
|
3068
3050
|
if empty_secret_raises:
|
|
3069
3051
|
raise SQLTemplateException(
|
|
@@ -3071,10 +3053,9 @@ def render_template_with_secrets(
|
|
|
3071
3053
|
)
|
|
3072
3054
|
return '""'
|
|
3073
3055
|
return default
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
)
|
|
3056
|
+
raise SQLTemplateException(
|
|
3057
|
+
f"Cannot access secret '{secret_name}'. Check the secret exists in the Workspace and the token has the required scope."
|
|
3058
|
+
)
|
|
3078
3059
|
|
|
3079
3060
|
# Create the template
|
|
3080
3061
|
t = Template(content, name=name, autoescape=None)
|