tinybird 4.6.16.dev0__tar.gz → 4.6.17.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.16.dev0 → tinybird-4.6.17.dev0}/PKG-INFO +12 -1
  2. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/ch_utils/engine.py +6 -1
  3. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/config.py +0 -4
  4. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/datafile/common.py +21 -0
  5. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/service_datasources.py +40 -16
  6. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/sql_toolset.py +0 -5
  7. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/__cli__.py +2 -2
  8. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/client.py +2 -2
  9. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/deployment.py +5 -8
  10. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/deployment_common.py +83 -13
  11. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird.egg-info/PKG-INFO +12 -1
  12. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/setup.cfg +0 -0
  13. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/__cli__.py +0 -0
  14. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/ch_utils/constants.py +0 -0
  15. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/check_pypi.py +0 -0
  16. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/client.py +0 -0
  17. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/context.py +0 -0
  18. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/datafile/exceptions.py +0 -0
  19. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/datafile/parse_connection.py +0 -0
  20. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/datafile/parse_datasource.py +0 -0
  21. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/datafile/parse_pipe.py +0 -0
  22. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/datatypes.py +0 -0
  23. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/feedback_manager.py +0 -0
  24. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/git_settings.py +0 -0
  25. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/iterating/__init__.py +0 -0
  26. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/iterating/data_branch_modes.py +0 -0
  27. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/prompts.py +0 -0
  28. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/sql.py +0 -0
  29. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/sql_template.py +0 -0
  30. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/sql_template_fmt.py +0 -0
  31. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/syncasync.py +0 -0
  32. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/check_pypi.py +0 -0
  33. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/cli.py +0 -0
  34. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/config.py +0 -0
  35. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/branch.py +0 -0
  36. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/build.py +0 -0
  37. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/build_common.py +0 -0
  38. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/cicd.py +0 -0
  39. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/cli.py +0 -0
  40. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/common.py +0 -0
  41. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/config.py +0 -0
  42. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/connection.py +0 -0
  43. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/connection_dynamodb.py +0 -0
  44. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/connection_kafka.py +0 -0
  45. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/connection_s3.py +0 -0
  46. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/copy.py +0 -0
  47. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/create.py +0 -0
  48. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/build.py +0 -0
  49. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/build_common.py +0 -0
  50. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
  51. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
  52. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/diff.py +0 -0
  53. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/fixture.py +0 -0
  54. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/format_common.py +0 -0
  55. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/format_connection.py +0 -0
  56. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
  57. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
  58. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
  59. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/playground.py +0 -0
  60. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datafile/pull.py +0 -0
  61. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/datasource.py +0 -0
  62. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/deprecations.py +0 -0
  63. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/endpoint.py +0 -0
  64. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/exceptions.py +0 -0
  65. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/feedback_manager.py +0 -0
  66. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/fmt.py +0 -0
  67. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/info.py +0 -0
  68. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/infra.py +0 -0
  69. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/job.py +0 -0
  70. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/job_common.py +0 -0
  71. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/llm.py +0 -0
  72. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/llm_utils.py +0 -0
  73. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/local.py +0 -0
  74. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/local_common.py +0 -0
  75. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/local_logs.py +0 -0
  76. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/login.py +0 -0
  77. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/login_common.py +0 -0
  78. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/logout.py +0 -0
  79. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/logs.py +0 -0
  80. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/materialization.py +0 -0
  81. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/open.py +0 -0
  82. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/pipe.py +0 -0
  83. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/preview.py +0 -0
  84. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/project.py +0 -0
  85. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/project_commands.py +0 -0
  86. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/py_project.py +0 -0
  87. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/query_output.py +0 -0
  88. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/regions.py +0 -0
  89. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/secret.py +0 -0
  90. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/secret_common.py +0 -0
  91. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/sink.py +0 -0
  92. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/table.py +0 -0
  93. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/telemetry.py +0 -0
  94. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/test.py +0 -0
  95. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/test_common.py +0 -0
  96. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
  97. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/token.py +0 -0
  98. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/ts_project.py +0 -0
  99. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/watch.py +0 -0
  100. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/workspace.py +0 -0
  101. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb/modules/workspace_members.py +0 -0
  102. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli.py +0 -0
  103. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
  104. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/branch.py +0 -0
  105. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/cicd.py +0 -0
  106. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/cli.py +0 -0
  107. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/common.py +0 -0
  108. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/config.py +0 -0
  109. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
  110. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/datasource.py +0 -0
  111. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
  112. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
  113. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/job.py +0 -0
  114. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/pipe.py +0 -0
  115. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
  116. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/tag.py +0 -0
  117. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
  118. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/test.py +0 -0
  119. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  120. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/workspace.py +0 -0
  121. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  122. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird/tornado_template.py +0 -0
  123. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird.egg-info/SOURCES.txt +0 -0
  124. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird.egg-info/dependency_links.txt +0 -0
  125. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird.egg-info/entry_points.txt +0 -0
  126. {tinybird-4.6.16.dev0 → tinybird-4.6.17.dev0}/tinybird.egg-info/requires.txt +0 -0
  127. {tinybird-4.6.16.dev0 → tinybird-4.6.17.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.16.dev0
3
+ Version: 4.6.17.dev0
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,22 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
51
51
 
52
52
  Changelog
53
53
  ----------
54
+
55
+ 4.6.15
56
+ ********
57
+
58
+ - `Fixed` ``tb deploy`` waits for the old deployment to delete to avoid clashing with a new deployment submission.
59
+
54
60
  4.6.14
55
61
  ********
56
62
 
57
63
  - `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
64
 
65
+ 4.6.14
66
+ ********
67
+
68
+ - `Fixed` `tb migrate-to-forward` correctly finds and offers to delete all branches, not just those created by the user running the migration.
69
+
59
70
  4.6.13
60
71
  ********
61
72
 
@@ -476,6 +476,9 @@ def engine_options(columns, options: List[EngineOption], args: Dict):
476
476
  if option_value:
477
477
  if o.sql.lower() == "settings":
478
478
  engine_settings = f"{o.sql} {option_value}"
479
+ # Conditional TTLs fail if we wrap the value in parentheses
480
+ elif o.sql.lower() == "ttl":
481
+ options_values.append(f"{o.sql} {option_value}")
479
482
  else:
480
483
  options_values.append(f"{o.sql} ({option_value})")
481
484
 
@@ -536,7 +539,9 @@ def engine_full_from_dict(
536
539
  >>> engine_full_from_dict('MergeTree', {'sorting_key': 'local_date, cod_store'}, schema=schema)
537
540
  'MergeTree() ORDER BY (local_date, cod_store)'
538
541
  >>> 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 (toDate(local_date) + INTERVAL 1 DAY) SETTINGS index_granularity = 32, index_granularity_bytes = 2048'
542
+ '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'
543
+ >>> engine_full_from_dict('MergeTree', {'sorting_key': 'timestamp', 'ttl': 'timestamp + INTERVAL 1 DAY DELETE WHERE is_deleted = 1'}, schema=schema)
544
+ 'MergeTree() ORDER BY (timestamp) TTL timestamp + INTERVAL 1 DAY DELETE WHERE is_deleted = 1'
540
545
 
541
546
  >>> schema = ''
542
547
  >>> engine_full_from_dict('CollapsingMergeTree', {'sign': 'sign_column'}, schema=schema)
@@ -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
  """
@@ -602,6 +608,13 @@ class Datafile:
602
608
  raise DatafileValidationError(
603
609
  f"Invalid import schedule '{node['import_schedule']}'. Only {sorted(VALID_BLOB_STORAGE_CRON_VALUES)} values are allowed"
604
610
  )
611
+ # Validate Postgres params
612
+ if any(param in node for param in POSTGRES_PARAMS) and (
613
+ missing := [param for param in REQUIRED_POSTGRES_PARAMS if param not in node]
614
+ ):
615
+ raise DatafileValidationError(
616
+ f"Some Postgres params have been provided, but the following required ones are missing: {missing}"
617
+ )
605
618
 
606
619
  else:
607
620
  # We cannot validate a datafile whose kind is unknown
@@ -2068,6 +2081,8 @@ def parse(
2068
2081
  "import_query": assign_var("import_query"), # Deprecated, BQ and SFK
2069
2082
  "import_table_arn": assign_var("import_table_arn"), # Only for DynamoDB
2070
2083
  "import_export_bucket": assign_var("import_export_bucket"), # For DynamoDB
2084
+ "pg_connection_name": assign_var("pg_connection_name"),
2085
+ "pg_table": assign_var("pg_table"),
2071
2086
  "shared_with": shared_with,
2072
2087
  "export_service": export_service, # Deprecated
2073
2088
  "forward_query": forward_query,
@@ -2128,6 +2143,12 @@ def parse(
2128
2143
  "gcs_secret": assign_var("gcs_hmac_secret"),
2129
2144
  "gcs_hmac_access_id": assign_var("gcs_hmac_access_id"),
2130
2145
  "gcs_hmac_secret": assign_var("gcs_hmac_secret"),
2146
+ "pg_host": assign_var("pg_host"),
2147
+ "pg_port": assign_var("pg_port"),
2148
+ "pg_database": assign_var("pg_database"),
2149
+ "pg_user": assign_var("pg_user"),
2150
+ "pg_password": assign_var("pg_password"),
2151
+ "pg_ssl_mode": assign_var("pg_ssl_mode"),
2131
2152
  "include": include,
2132
2153
  },
2133
2154
  }
@@ -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,25 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
333
334
  {"name": "job_metadata", "type": "String"},
334
335
  ],
335
336
  },
337
+ {
338
+ "name": "tinybird.rate_limits_log",
339
+ "description": "Endpoint concurrency limiter transitions in your workspace.",
340
+ "dateColumn": "timestamp",
341
+ "engine": {
342
+ "engine": "MergeTree",
343
+ "sorting_key": "timestamp, pipe_name",
344
+ "partition_key": "toYYYYMM(timestamp)",
345
+ },
346
+ "columns": [
347
+ {"name": "timestamp", "type": "DateTime64(3)"},
348
+ {"name": "workspace_id", "type": "String"},
349
+ {"name": "workspace_name", "type": "String"},
350
+ {"name": "pipe_name", "type": "String"},
351
+ {"name": "rate_limit_type", "type": "LowCardinality(String)"},
352
+ {"name": "action", "type": "LowCardinality(String)"},
353
+ {"name": "limit_metadata", "type": "String"},
354
+ ],
355
+ },
336
356
  {
337
357
  "name": "tinybird.hook_log",
338
358
  "description": "Log of hook executions and their results.",
@@ -518,22 +538,6 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
518
538
  {"name": "origin", "type": "String"},
519
539
  ],
520
540
  },
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
541
  {
538
542
  "name": "organization.datasources_storage",
539
543
  "description": "Similar to tinybird.datasources_storage but with data for all Organization Workspaces.",
@@ -683,6 +687,7 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
683
687
  {"name": "user_agent", "type": "Nullable(String)"},
684
688
  {"name": "resource_tags", "type": "Array(String)"},
685
689
  {"name": "memory_usage", "type": "UInt64"},
690
+ {"name": "replica", "type": "String"},
686
691
  ],
687
692
  },
688
693
  {
@@ -726,6 +731,25 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
726
731
  {"name": "job_metadata", "type": "String"},
727
732
  ],
728
733
  },
734
+ {
735
+ "name": "organization.rate_limits_log",
736
+ "description": "Endpoint concurrency limiter transitions across the organization.",
737
+ "dateColumn": "timestamp",
738
+ "engine": {
739
+ "engine": "MergeTree",
740
+ "sorting_key": "workspace_id, timestamp, pipe_name",
741
+ "partition_key": "toYYYYMM(timestamp)",
742
+ },
743
+ "columns": [
744
+ {"name": "timestamp", "type": "DateTime64(3)"},
745
+ {"name": "workspace_id", "type": "String"},
746
+ {"name": "workspace_name", "type": "String"},
747
+ {"name": "pipe_name", "type": "String"},
748
+ {"name": "rate_limit_type", "type": "LowCardinality(String)"},
749
+ {"name": "action", "type": "LowCardinality(String)"},
750
+ {"name": "limit_metadata", "type": "String"},
751
+ ],
752
+ },
729
753
  {
730
754
  "name": "organization.sinks_ops_log",
731
755
  "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.16.dev0'
8
- __revision__ = '532ee82'
7
+ __version__ = '4.6.17.dev0'
8
+ __revision__ = '026318e'
@@ -833,8 +833,8 @@ class TinyB:
833
833
  def user_workspace_branches(self, version: str = "v0"):
834
834
  return self._req(f"/{version}/user/workspaces/?with_environments=true&only_environments=true")
835
835
 
836
- def branches(self):
837
- return self._req("/v1/environments")
836
+ def branches(self, version: str = "v1"):
837
+ return self._req(f"/{version}/environments")
838
838
 
839
839
  def releases(self, workspace_id):
840
840
  return self._req(f"/v0/workspaces/{workspace_id}/releases")
@@ -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, workspace_id: str) -> list[dict[str, Any]]:
159
- branches: list[dict[str, Any]] = client.user_workspace_branches(version="v0").get("workspaces", [])
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, config: Dict[str, Any]) -> None:
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, workspace_id)
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, config)
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(
@@ -118,23 +118,57 @@ def _get_migrate_to_forward_error_message(result: dict[str, Any]) -> str:
118
118
  def _is_first_deployment_with_seed_live(host: Optional[str], headers: dict) -> bool:
119
119
  """Best-effort check for first real deployment when seed deployment (id=0) is still live."""
120
120
  try:
121
- response = requests.get(f"{host}/v1/deployments", headers=headers)
122
- if response.status_code >= 300:
123
- return False
124
-
125
- result = response.json()
126
- logging.debug(json.dumps(result, indent=2))
127
- deployments = result.get("deployments") or []
128
- if not deployments:
129
- return False
130
-
131
- live_deployment = next((deployment for deployment in deployments if deployment.get("live")), deployments[0])
132
- return str(live_deployment.get("id")) == "0"
121
+ return _get_current_live_deployment_id(host, headers) == "0"
133
122
  except Exception:
134
- # Hint calculation must never break deployment flow.
123
+ logging.exception("Error checking for live seed deployment while deciding first-deployment hint")
135
124
  return False
136
125
 
137
126
 
127
+ def _list_deployments(host: Optional[str], headers: dict) -> list[dict]:
128
+ """Fetch the current deployments. Raises if the lookup fails."""
129
+ response = requests.get(f"{host}/v1/deployments", headers=headers)
130
+ response.raise_for_status()
131
+
132
+ result = response.json()
133
+ logging.debug(json.dumps(result, indent=2))
134
+ return result.get("deployments") or []
135
+
136
+
137
+ def _get_current_live_deployment_id(host: Optional[str], headers: dict) -> Optional[str]:
138
+ deployments = _list_deployments(host, headers)
139
+ if not deployments:
140
+ return None
141
+
142
+ live_deployment = next((deployment for deployment in deployments if deployment.get("live")), deployments[0])
143
+ live_id = live_deployment.get("id")
144
+ return str(live_id) if live_id is not None else None
145
+
146
+
147
+ def _get_lingering_old_deployment_id(host: Optional[str], headers: dict, new_deployment_id: str) -> Optional[str]:
148
+ """Look up a still-active deployment other than `new_deployment_id`, if any."""
149
+ deployments = _list_deployments(host, headers)
150
+ other_deployment = next((d for d in deployments if str(d.get("id")) != new_deployment_id), None)
151
+ return str(other_deployment["id"]) if other_deployment else None
152
+
153
+
154
+ def _wait_for_deployment_deletion(
155
+ host: Optional[str],
156
+ headers: dict,
157
+ deployment_id: str,
158
+ request_from: Optional[str] = None,
159
+ poll_interval: int = 5,
160
+ ) -> bool: # whether the deployment has been deleted successfully
161
+ url = f"{host}/v1/deployments/{deployment_id}"
162
+ while True:
163
+ result = api_fetch(url, headers, request_from=request_from)
164
+ old_deployment = result.get("deployment")
165
+ if not old_deployment or old_deployment.get("status") == "deleted":
166
+ return True
167
+ if old_deployment.get("status") == "failed":
168
+ return False
169
+ time.sleep(poll_interval)
170
+
171
+
138
172
  def _get_deployment_job(client: TinyB, deployment_id: Optional[Union[str, int]]) -> Optional[Dict[str, Any]]:
139
173
  if deployment_id is None:
140
174
  return None
@@ -635,6 +669,42 @@ def create_deployment(
635
669
  click.echo(FeedbackManager.highlight(message="» Waiting for deployment to be promoted..."))
636
670
  click.echo(FeedbackManager.info(message="✓ Deployment promoted"))
637
671
  click.echo(FeedbackManager.success(message=f"✓ Deployment #{deployment.get('id')} is live!"))
672
+
673
+ old_deployment_id: Optional[str] = None
674
+ try:
675
+ old_deployment_id = _get_lingering_old_deployment_id(client.host, HEADERS, str(deployment.get("id")))
676
+ except Exception:
677
+ click.echo(
678
+ FeedbackManager.warning(
679
+ message="Could not confirm if there's a previous deployment to remove. "
680
+ f"If a follow-up `tb deploy` reports one already in progress, check `tb --{env} deployment ls`."
681
+ )
682
+ )
683
+
684
+ if old_deployment_id:
685
+ click.echo(FeedbackManager.highlight(message="» Removing old deployment..."))
686
+ try:
687
+ deleted = _wait_for_deployment_deletion(
688
+ client.host, HEADERS, old_deployment_id, request_from=request_from
689
+ )
690
+ except KeyboardInterrupt:
691
+ click.echo(
692
+ FeedbackManager.warning(
693
+ message=f"\nDeployment is live, but the old deployment is still being removed. "
694
+ f"Check its status with `tb --{env} deployment ls`."
695
+ )
696
+ )
697
+ raise click.Abort()
698
+ if deleted:
699
+ click.echo(FeedbackManager.info(message="✓ Old deployment removed"))
700
+ else:
701
+ click.echo(
702
+ FeedbackManager.warning(
703
+ message="Deployment is live, but the old deployment failed to be removed. "
704
+ f"Check its status with `tb --{env} deployment ls`."
705
+ )
706
+ )
707
+
638
708
  if ingest_hint and len(deployment.get("new_data_connector_ids", [])) == 0 and is_first_deployment:
639
709
  click.echo(
640
710
  FeedbackManager.info(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 4.6.16.dev0
3
+ Version: 4.6.17.dev0
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,22 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
51
51
 
52
52
  Changelog
53
53
  ----------
54
+
55
+ 4.6.15
56
+ ********
57
+
58
+ - `Fixed` ``tb deploy`` waits for the old deployment to delete to avoid clashing with a new deployment submission.
59
+
54
60
  4.6.14
55
61
  ********
56
62
 
57
63
  - `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
64
 
65
+ 4.6.14
66
+ ********
67
+
68
+ - `Fixed` `tb migrate-to-forward` correctly finds and offers to delete all branches, not just those created by the user running the migration.
69
+
59
70
  4.6.13
60
71
  ********
61
72
 
File without changes