tinybird 4.6.18.dev0__tar.gz → 4.6.19.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.
Files changed (127) hide show
  1. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/PKG-INFO +6 -1
  2. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/ch_utils/engine.py +7 -12
  3. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/client.py +14 -26
  4. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/datafile/common.py +20 -25
  5. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/git_settings.py +1 -3
  6. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/service_datasources.py +6 -4
  7. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/__cli__.py +2 -2
  8. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/client.py +3 -0
  9. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/build_common.py +4 -6
  10. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/feedback_manager.py +1 -0
  11. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/job.py +22 -0
  12. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird.egg-info/PKG-INFO +6 -1
  13. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/setup.cfg +0 -0
  14. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/__cli__.py +0 -0
  15. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/ch_utils/constants.py +0 -0
  16. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/check_pypi.py +0 -0
  17. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/config.py +0 -0
  18. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/context.py +0 -0
  19. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/datafile/exceptions.py +0 -0
  20. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/datafile/parse_connection.py +0 -0
  21. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/datafile/parse_datasource.py +0 -0
  22. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/datafile/parse_pipe.py +0 -0
  23. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/datatypes.py +0 -0
  24. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/feedback_manager.py +0 -0
  25. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/iterating/__init__.py +0 -0
  26. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/iterating/data_branch_modes.py +0 -0
  27. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/prompts.py +0 -0
  28. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/sql.py +0 -0
  29. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/sql_template.py +0 -0
  30. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/sql_template_fmt.py +0 -0
  31. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/sql_toolset.py +0 -0
  32. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/syncasync.py +0 -0
  33. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/check_pypi.py +0 -0
  34. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/cli.py +0 -0
  35. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/config.py +0 -0
  36. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/branch.py +0 -0
  37. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/build.py +0 -0
  38. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/cicd.py +0 -0
  39. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/cli.py +0 -0
  40. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/common.py +0 -0
  41. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/config.py +0 -0
  42. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/connection.py +0 -0
  43. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/connection_dynamodb.py +0 -0
  44. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/connection_kafka.py +0 -0
  45. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/connection_s3.py +0 -0
  46. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/copy.py +0 -0
  47. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/create.py +0 -0
  48. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/build.py +0 -0
  49. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/build_common.py +0 -0
  50. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
  51. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
  52. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/diff.py +0 -0
  53. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/fixture.py +0 -0
  54. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/format_common.py +0 -0
  55. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/format_connection.py +0 -0
  56. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
  57. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
  58. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
  59. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/playground.py +0 -0
  60. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datafile/pull.py +0 -0
  61. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/datasource.py +0 -0
  62. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/deployment.py +0 -0
  63. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/deployment_common.py +0 -0
  64. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/deprecations.py +0 -0
  65. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/endpoint.py +0 -0
  66. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/exceptions.py +0 -0
  67. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/fmt.py +0 -0
  68. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/info.py +0 -0
  69. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/infra.py +0 -0
  70. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/job_common.py +0 -0
  71. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/llm.py +0 -0
  72. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/llm_utils.py +0 -0
  73. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/local.py +0 -0
  74. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/local_common.py +0 -0
  75. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/local_logs.py +0 -0
  76. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/login.py +0 -0
  77. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/login_common.py +0 -0
  78. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/logout.py +0 -0
  79. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/logs.py +0 -0
  80. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/materialization.py +0 -0
  81. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/open.py +0 -0
  82. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/pipe.py +0 -0
  83. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/preview.py +0 -0
  84. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/project.py +0 -0
  85. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/project_commands.py +0 -0
  86. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/py_project.py +0 -0
  87. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/query_output.py +0 -0
  88. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/regions.py +0 -0
  89. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/secret.py +0 -0
  90. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/secret_common.py +0 -0
  91. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/sink.py +0 -0
  92. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/table.py +0 -0
  93. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/telemetry.py +0 -0
  94. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/test.py +0 -0
  95. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/test_common.py +0 -0
  96. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
  97. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/token.py +0 -0
  98. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/ts_project.py +0 -0
  99. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/watch.py +0 -0
  100. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/workspace.py +0 -0
  101. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb/modules/workspace_members.py +0 -0
  102. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli.py +0 -0
  103. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
  104. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/branch.py +0 -0
  105. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/cicd.py +0 -0
  106. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/cli.py +0 -0
  107. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/common.py +0 -0
  108. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/config.py +0 -0
  109. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
  110. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/datasource.py +0 -0
  111. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
  112. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
  113. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/job.py +0 -0
  114. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/pipe.py +0 -0
  115. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
  116. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/tag.py +0 -0
  117. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
  118. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/test.py +0 -0
  119. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  120. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/workspace.py +0 -0
  121. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  122. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird/tornado_template.py +0 -0
  123. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird.egg-info/SOURCES.txt +0 -0
  124. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird.egg-info/dependency_links.txt +0 -0
  125. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird.egg-info/entry_points.txt +0 -0
  126. {tinybird-4.6.18.dev0 → tinybird-4.6.19.dev0}/tinybird.egg-info/requires.txt +0 -0
  127. {tinybird-4.6.18.dev0 → tinybird-4.6.19.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.18.dev0
3
+ Version: 4.6.19.dev0
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,11 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
52
52
  Changelog
53
53
  ----------
54
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
+
55
60
  4.6.16
56
61
  ********
57
62
 
@@ -111,8 +111,7 @@ class TableDetails:
111
111
 
112
112
  @property
113
113
  def version(self):
114
- _version = self.details.get("version", None)
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
- _ver = self.details.get("ver", None)
194
- return _ver
193
+ return self.details.get("ver", None)
195
194
 
196
195
  @property
197
196
  def is_deleted(self):
198
- _is_deleted = self.details.get("is_deleted", None)
199
- return _is_deleted
197
+ return self.details.get("is_deleted", None)
200
198
 
201
199
  @property
202
200
  def columns(self):
203
- _columns = self.details.get("columns", None)
204
- return _columns
201
+ return self.details.get("columns", None)
205
202
 
206
203
  @property
207
204
  def sign(self):
208
- _sign = self.details.get("sign", None)
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
- ttl = ttl_array[1][: -(len(settings))] if settings else ttl_array[1]
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
- else:
275
- url = url + "?" + scopes_url
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
- response = await self._req("/v0/variables", method="POST", data={"name": name, "value": value})
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
- response = await self._req(f"/v0/variables/{name}", method="PUT", data={"value": value})
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
- response = await self._req(f"/v0/variables/{name}", method="DELETE")
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
- response = await self._req(f"/v0/pipes/{pipe_name}/nodes/{node_name}/analysis?{urlencode(params)}")
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
- response = await self._req(
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
- else:
639
- url = url + "?" + query_string
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
- else:
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
- else:
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
- regions = await self._req("/v0/regions")
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
- else:
506
- # There are some export parameters, but they don't match known patterns
507
- raise DatafileValidationError(
508
- f"Sink node {repr(node['name'])} has unrecognized export parameters: {export_params}. "
509
- f"For Kafka sinks, use 'export_kafka_topic'. "
510
- f"For S3/GCS sinks, use 'export_bucket_uri' and 'export_file_template'."
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
- match = next((x for x in lookup if x.regex.match(s)), None)
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
- else:
1126
- # backticked name
1127
- advance_single_char()
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
- else:
1300
- # TODO(eclbg): The resulting error message is a bit confusing, as the clickhouse error contains some
1301
- # references to positions that don't match the position in the schema.
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
- elif severity == "warning":
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
- elif "sql" in line.lower():
2238
+ if "sql" in line.lower():
2242
2239
  raise click.ClickException(FeedbackManager.error_missing_sql_command())
2243
- elif "datasource" in line.lower():
2240
+ if "datasource" in line.lower():
2244
2241
  raise click.ClickException(FeedbackManager.error_missing_datasource_name())
2245
- else:
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
- elif len(tk) == 2:
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
- else:
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
- modified_files = {
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.rate_limits_log",
339
- "description": "Endpoint concurrency limiter transitions in your workspace.",
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.rate_limits_log",
736
- "description": "Endpoint concurrency limiter transitions across the organization.",
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)"},
@@ -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.18.dev0'
8
- __revision__ = '0bbef5c'
7
+ __version__ = '4.6.19.dev0'
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
@@ -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, config=config)
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
- build_error = build_error or "Unknown error"
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
- elif build_result == "failed":
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, config: dict[str, Any]) -> None:
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:
@@ -1129,6 +1129,7 @@ STEP 3: ADD KEY TO SERVICE ACCOUNT
1129
1129
  success_job_cancellation_cancelling = success_message(
1130
1130
  "** Job with id '{job_id}' is now in cancelling status and will be cancelled eventually"
1131
1131
  )
1132
+ success_job_retried = success_message("** Job '{job_id}' retried as '{retried_job_id}'")
1132
1133
  success_datasource_alter = success_message("** The Data Source has been correctly updated.")
1133
1134
  success_datasource_kafka_connected = success_message(
1134
1135
  "** Data Source '{id}' created\n** Kafka streaming connection configured successfully!"
@@ -87,3 +87,25 @@ def job_cancel(ctx: Context, job_id: str) -> None:
87
87
  else:
88
88
  raise CLIException(FeedbackManager.error_job_cancelled_but_status_unknown(job_id=job_id))
89
89
  click.echo("\n")
90
+
91
+
92
+ @job.command(name="retry")
93
+ @click.argument("job_id")
94
+ @click.pass_context
95
+ def job_retry(ctx: Context, job_id: str) -> None:
96
+ client: TinyB = ctx.ensure_object(dict)["client"]
97
+
98
+ try:
99
+ retried_job = client.job_retry(job_id)
100
+ except DoesNotExistException:
101
+ raise CLIException(FeedbackManager.error_job_does_not_exist(job_id=job_id))
102
+ except Exception as e:
103
+ raise CLIException(FeedbackManager.error_exception(error=e))
104
+
105
+ click.echo(
106
+ FeedbackManager.success_job_retried(
107
+ job_id=job_id,
108
+ retried_job_id=retried_job["id"],
109
+ )
110
+ )
111
+ click.echo("\n")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 4.6.18.dev0
3
+ Version: 4.6.19.dev0
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,11 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
52
52
  Changelog
53
53
  ----------
54
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
+
55
60
  4.6.16
56
61
  ********
57
62
 
File without changes