tinybird 4.6.8.dev0__py3-none-any.whl → 4.6.13.dev0__py3-none-any.whl
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/ch_utils/engine.py +6 -0
- tinybird/datafile/common.py +27 -14
- tinybird/service_datasources.py +1 -88
- tinybird/sql_template.py +39 -2
- tinybird/sql_toolset.py +25 -6
- tinybird/tb/__cli__.py +2 -2
- tinybird/tb/client.py +20 -4
- tinybird/tb/modules/cli.py +5 -2
- tinybird/tb/modules/common.py +13 -6
- tinybird/tb/modules/connection_dynamodb.py +1 -0
- tinybird/tb/modules/connection_s3.py +1 -0
- tinybird/tb/modules/datasource.py +60 -8
- tinybird/tb/modules/local.py +25 -12
- tinybird/tb/modules/local_common.py +6 -1
- tinybird/tb/modules/logs.py +1 -13
- {tinybird-4.6.8.dev0.dist-info → tinybird-4.6.13.dev0.dist-info}/METADATA +29 -2
- {tinybird-4.6.8.dev0.dist-info → tinybird-4.6.13.dev0.dist-info}/RECORD +20 -20
- {tinybird-4.6.8.dev0.dist-info → tinybird-4.6.13.dev0.dist-info}/WHEEL +0 -0
- {tinybird-4.6.8.dev0.dist-info → tinybird-4.6.13.dev0.dist-info}/entry_points.txt +0 -0
- {tinybird-4.6.8.dev0.dist-info → tinybird-4.6.13.dev0.dist-info}/top_level.txt +0 -0
tinybird/ch_utils/engine.py
CHANGED
|
@@ -121,6 +121,12 @@ class TableDetails:
|
|
|
121
121
|
def is_mergetree_family(self) -> bool:
|
|
122
122
|
return self.engine is not None and "mergetree" in self.engine.lower()
|
|
123
123
|
|
|
124
|
+
def is_view(self) -> bool:
|
|
125
|
+
return self.original_engine == "View"
|
|
126
|
+
|
|
127
|
+
def is_merge_final_engine(self) -> bool:
|
|
128
|
+
return self.original_engine == "MergeFinal"
|
|
129
|
+
|
|
124
130
|
def supports_alter_add_column(self) -> bool:
|
|
125
131
|
return self.is_mergetree_family() or (self.engine is not None and self.engine.lower() == "null")
|
|
126
132
|
|
tinybird/datafile/common.py
CHANGED
|
@@ -221,8 +221,6 @@ INTERNAL_TABLES: Tuple[str, ...] = (
|
|
|
221
221
|
"kafka_ops_log",
|
|
222
222
|
"datasources_storage",
|
|
223
223
|
"endpoint_errors",
|
|
224
|
-
"bi_stats_rt",
|
|
225
|
-
"bi_stats",
|
|
226
224
|
)
|
|
227
225
|
|
|
228
226
|
PREVIEW_CONNECTOR_SERVICES = ["s3", "s3_iamrole", "gcs"]
|
|
@@ -403,12 +401,15 @@ class Datafile:
|
|
|
403
401
|
if node.get("mode") and node["mode"] not in ["append", "replace"]:
|
|
404
402
|
raise DatafileValidationError("COPY node mode must be append or replace")
|
|
405
403
|
# copy schedule must be @on-demand or a cron-expression
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
and
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
404
|
+
copy_schedule = node.get("copy_schedule")
|
|
405
|
+
if copy_schedule and copy_schedule != ON_DEMAND:
|
|
406
|
+
if isinstance(copy_schedule, str) and "tb_secret" in copy_schedule:
|
|
407
|
+
raise DatafileValidationError(
|
|
408
|
+
"COPY_SCHEDULE does not support { tb_secret(...) }. "
|
|
409
|
+
'Use a literal cron expression (for example "0 * * * *") or @on-demand.'
|
|
410
|
+
)
|
|
411
|
+
if not croniter.is_valid(copy_schedule):
|
|
412
|
+
raise DatafileValidationError("COPY node schedule must be @on-demand or a valid cron expression.")
|
|
412
413
|
for key in node.keys():
|
|
413
414
|
if key not in CopyParameters.valid_params():
|
|
414
415
|
raise DatafileValidationError(
|
|
@@ -505,10 +506,16 @@ class Datafile:
|
|
|
505
506
|
|
|
506
507
|
# Validate schedule format (common for both Kafka and S3/GCS)
|
|
507
508
|
export_schedule = node.get("export_schedule")
|
|
508
|
-
if export_schedule and export_schedule != ON_DEMAND
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
509
|
+
if export_schedule and export_schedule != ON_DEMAND:
|
|
510
|
+
if isinstance(export_schedule, str) and "tb_secret" in export_schedule:
|
|
511
|
+
raise DatafileValidationError(
|
|
512
|
+
f"Sink node {repr(node['name'])}: EXPORT_SCHEDULE does not support {{ tb_secret(...) }}. "
|
|
513
|
+
'Use a literal cron expression (for example "0 * * * *") or @on-demand.'
|
|
514
|
+
)
|
|
515
|
+
if not croniter.is_valid(export_schedule):
|
|
516
|
+
raise DatafileValidationError(
|
|
517
|
+
f"Sink node {repr(node['name'])} has invalid export_schedule '{export_schedule}'. Must be @on-demand or a valid cron expression."
|
|
518
|
+
)
|
|
512
519
|
|
|
513
520
|
def validate(self):
|
|
514
521
|
if self.kind == DatafileKind.pipe:
|
|
@@ -1725,7 +1732,9 @@ def parse(
|
|
|
1725
1732
|
|
|
1726
1733
|
parser_state.current_node["indexes"] = indexes
|
|
1727
1734
|
|
|
1728
|
-
def assign_var(
|
|
1735
|
+
def assign_var(
|
|
1736
|
+
v: str, allowed_values: Optional[set[str]] = None, lowercase: bool = False
|
|
1737
|
+
) -> Callable[[VarArg(str), KwArg(Any)], None]:
|
|
1729
1738
|
@multiline_not_supported
|
|
1730
1739
|
def _f(*args: str, **kwargs: Any):
|
|
1731
1740
|
s = _unquote((" ".join(args)).strip())
|
|
@@ -1736,6 +1745,8 @@ def parse(
|
|
|
1736
1745
|
lineno=kwargs["lineno"],
|
|
1737
1746
|
pos=1,
|
|
1738
1747
|
)
|
|
1748
|
+
if lowercase:
|
|
1749
|
+
val = val.lower()
|
|
1739
1750
|
parser_state.current_node[v.lower()] = val
|
|
1740
1751
|
|
|
1741
1752
|
return _f
|
|
@@ -2048,7 +2059,9 @@ def parse(
|
|
|
2048
2059
|
"import_schedule": assign_var("import_schedule"),
|
|
2049
2060
|
"import_strategy": import_strategy_deprecated, # Deprecated, always append
|
|
2050
2061
|
"import_bucket_uri": assign_var("import_bucket_uri"),
|
|
2051
|
-
|
|
2062
|
+
# Lowercase: format checks and executor routing downstream expect
|
|
2063
|
+
# lowercase values (ANALYTICS-A8M)
|
|
2064
|
+
"import_format": assign_var("import_format", lowercase=True),
|
|
2052
2065
|
"import_from_timestamp": assign_var("import_from_timestamp"),
|
|
2053
2066
|
"import_service": import_service_deprecated, # Deprecated
|
|
2054
2067
|
"import_external_datasource": import_external_datasource_deprecated, # Deprecated, BQ and SFK
|
tinybird/service_datasources.py
CHANGED
|
@@ -244,49 +244,6 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
244
244
|
{"name": "rows_quarantine", "type": "SimpleAggregateFunction(max, UInt64)"},
|
|
245
245
|
],
|
|
246
246
|
},
|
|
247
|
-
{
|
|
248
|
-
"name": "tinybird.bi_stats_rt",
|
|
249
|
-
"description": "Contains information about all requests to your BI Connector interface in real time.",
|
|
250
|
-
"dateColumn": "start_datetime",
|
|
251
|
-
"engine": {
|
|
252
|
-
"engine": "MergeTree",
|
|
253
|
-
"sorting_key": "cityHash64(query_normalized), start_datetime",
|
|
254
|
-
"ttl": "start_datetime + toIntervalDay(7)",
|
|
255
|
-
},
|
|
256
|
-
"columns": [
|
|
257
|
-
{"name": "start_datetime", "type": "DateTime"},
|
|
258
|
-
{"name": "query", "type": "String"},
|
|
259
|
-
{"name": "query_normalized", "type": "String"},
|
|
260
|
-
{"name": "error_code", "type": "Int32"},
|
|
261
|
-
{"name": "error", "type": "Nullable(String)"},
|
|
262
|
-
{"name": "duration", "type": "UInt64"},
|
|
263
|
-
{"name": "read_rows", "type": "UInt64"},
|
|
264
|
-
{"name": "read_bytes", "type": "UInt64"},
|
|
265
|
-
{"name": "result_rows", "type": "UInt64"},
|
|
266
|
-
{"name": "result_bytes", "type": "UInt64"},
|
|
267
|
-
],
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
"name": "tinybird.bi_stats",
|
|
271
|
-
"description": "Aggregates the stats in tinybird.bi_stats_rt by day.",
|
|
272
|
-
"dateColumn": "date",
|
|
273
|
-
"engine": {"engine": "MergeTree", "sorting_key": "cityHash64(query_normalized), start_datetime"},
|
|
274
|
-
"columns": [
|
|
275
|
-
{"name": "date", "type": "Date"},
|
|
276
|
-
{"name": "query_normalized", "type": "String"},
|
|
277
|
-
{"name": "view_count", "type": "UInt64"},
|
|
278
|
-
{"name": "error_count", "type": "UInt64"},
|
|
279
|
-
{"name": "avg_duration_state", "type": "AggregateFunction(avg, Float32)"},
|
|
280
|
-
{
|
|
281
|
-
"name": "quantile_timing_state",
|
|
282
|
-
"type": "AggregateFunction(quantilesTiming(0.9, 0.95, 0.99), Float64)",
|
|
283
|
-
},
|
|
284
|
-
{"name": "read_bytes_sum", "type": "UInt64"},
|
|
285
|
-
{"name": "read_rows_sum", "type": "UInt64"},
|
|
286
|
-
{"name": "avg_result_rows_state", "type": "AggregateFunction(avg, Float32)"},
|
|
287
|
-
{"name": "avg_result_bytes_state", "type": "AggregateFunction(avg, Float32)"},
|
|
288
|
-
],
|
|
289
|
-
},
|
|
290
247
|
{
|
|
291
248
|
"name": "tinybird.sinks_ops_log",
|
|
292
249
|
"description": "Contains information about your Sink pipes.",
|
|
@@ -483,6 +440,7 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
483
440
|
{"name": "error_code", "type": "Int16"},
|
|
484
441
|
{"name": "error", "type": "String"},
|
|
485
442
|
{"name": "fix_suggestion", "type": "String"},
|
|
443
|
+
{"name": "fix_suggestion_ai", "type": "String"},
|
|
486
444
|
{"name": "run_validation", "type": "DateTime"},
|
|
487
445
|
],
|
|
488
446
|
},
|
|
@@ -798,51 +756,6 @@ def get_organization_service_datasources() -> List[Dict[str, Any]]:
|
|
|
798
756
|
{"name": "token_name", "type": "String"},
|
|
799
757
|
],
|
|
800
758
|
},
|
|
801
|
-
{
|
|
802
|
-
"name": "organization.bi_stats_rt",
|
|
803
|
-
"description": "Contains information about all requests to the BI Connector interface for the whole Organization in real time.",
|
|
804
|
-
"dateColumn": "start_datetime",
|
|
805
|
-
"engine": {
|
|
806
|
-
"engine": "MergeTree",
|
|
807
|
-
"sorting_key": "cityHash64(query_normalized), start_datetime",
|
|
808
|
-
"ttl": "start_datetime + toIntervalDay(7)",
|
|
809
|
-
},
|
|
810
|
-
"columns": [
|
|
811
|
-
{"name": "database", "type": "String"},
|
|
812
|
-
{"name": "start_datetime", "type": "DateTime"},
|
|
813
|
-
{"name": "query", "type": "String"},
|
|
814
|
-
{"name": "query_normalized", "type": "String"},
|
|
815
|
-
{"name": "error_code", "type": "Int32"},
|
|
816
|
-
{"name": "error", "type": "Nullable(String)"},
|
|
817
|
-
{"name": "duration", "type": "UInt64"},
|
|
818
|
-
{"name": "read_rows", "type": "UInt64"},
|
|
819
|
-
{"name": "read_bytes", "type": "UInt64"},
|
|
820
|
-
{"name": "result_rows", "type": "UInt64"},
|
|
821
|
-
{"name": "result_bytes", "type": "UInt64"},
|
|
822
|
-
],
|
|
823
|
-
},
|
|
824
|
-
{
|
|
825
|
-
"name": "organization.bi_stats",
|
|
826
|
-
"description": "Aggregates the stats in organization.bi_stats_rt by day.",
|
|
827
|
-
"dateColumn": "date",
|
|
828
|
-
"engine": {"engine": "MergeTree", "sorting_key": "database, cityHash64(query_normalized), date"},
|
|
829
|
-
"columns": [
|
|
830
|
-
{"name": "database", "type": "String"},
|
|
831
|
-
{"name": "date", "type": "Date"},
|
|
832
|
-
{"name": "query_normalized", "type": "String"},
|
|
833
|
-
{"name": "view_count", "type": "UInt64"},
|
|
834
|
-
{"name": "error_count", "type": "UInt64"},
|
|
835
|
-
{"name": "avg_duration_state", "type": "AggregateFunction(avg, Float32)"},
|
|
836
|
-
{
|
|
837
|
-
"name": "quantile_timing_state",
|
|
838
|
-
"type": "AggregateFunction(quantilesTiming(0.9, 0.95, 0.99), Float64)",
|
|
839
|
-
},
|
|
840
|
-
{"name": "read_bytes_sum", "type": "UInt64"},
|
|
841
|
-
{"name": "read_rows_sum", "type": "UInt64"},
|
|
842
|
-
{"name": "avg_result_rows_state", "type": "AggregateFunction(avg, Float32)"},
|
|
843
|
-
{"name": "avg_result_bytes_state", "type": "AggregateFunction(avg, Float32)"},
|
|
844
|
-
],
|
|
845
|
-
},
|
|
846
759
|
{
|
|
847
760
|
"name": "organization.metrics_logs",
|
|
848
761
|
"description": "Metrics of your organization's dedicated clusters",
|
tinybird/sql_template.py
CHANGED
|
@@ -2911,13 +2911,21 @@ def extract_variables_from_sql(sql: str, params: List[Dict[str, Any]]) -> Dict[s
|
|
|
2911
2911
|
return defaults
|
|
2912
2912
|
|
|
2913
2913
|
|
|
2914
|
-
def render_template_with_secrets(
|
|
2914
|
+
def render_template_with_secrets(
|
|
2915
|
+
name: str,
|
|
2916
|
+
content: str,
|
|
2917
|
+
secrets: Optional[Dict[str, str]] = None,
|
|
2918
|
+
empty_secret_raises: bool = False,
|
|
2919
|
+
) -> str:
|
|
2915
2920
|
"""Renders a template with secrets, allowing for default values.
|
|
2916
2921
|
|
|
2917
2922
|
Args:
|
|
2918
2923
|
name: The name of the template
|
|
2919
2924
|
content: The template content
|
|
2920
2925
|
secrets: A dictionary mapping secret names to their values
|
|
2926
|
+
empty_secret_raises: When True, empty secret values or empty defaults raise
|
|
2927
|
+
instead of returning '""'. Used for sink metadata (Forward deploy) where
|
|
2928
|
+
an empty bucket path must not be baked as s3://"".
|
|
2921
2929
|
|
|
2922
2930
|
Returns:
|
|
2923
2931
|
The rendered template
|
|
@@ -2959,6 +2967,26 @@ def render_template_with_secrets(name: str, content: str, secrets: Optional[Dict
|
|
|
2959
2967
|
Traceback (most recent call last):
|
|
2960
2968
|
...
|
|
2961
2969
|
tinybird.sql_template.SQLTemplateException: Template Syntax Error: Cannot access secret 'MISSING_SECRET'. Check the secret exists in the Workspace and the token has the required scope.
|
|
2970
|
+
|
|
2971
|
+
>>> render_template_with_secrets(
|
|
2972
|
+
... "sink_bucket",
|
|
2973
|
+
... "s3://{{ tb_secret('MISSING_SECRET', '') }}",
|
|
2974
|
+
... secrets = {},
|
|
2975
|
+
... empty_secret_raises=True,
|
|
2976
|
+
... )
|
|
2977
|
+
Traceback (most recent call last):
|
|
2978
|
+
...
|
|
2979
|
+
tinybird.sql_template.SQLTemplateException: Template Syntax Error: Secret 'MISSING_SECRET' resolves to an empty value and cannot be used in sink metadata.
|
|
2980
|
+
|
|
2981
|
+
>>> render_template_with_secrets(
|
|
2982
|
+
... "sink_bucket",
|
|
2983
|
+
... "s3://{{ tb_secret('EMPTY_SECRET', 'fallback') }}",
|
|
2984
|
+
... secrets = {'EMPTY_SECRET': ''},
|
|
2985
|
+
... empty_secret_raises=True,
|
|
2986
|
+
... )
|
|
2987
|
+
Traceback (most recent call last):
|
|
2988
|
+
...
|
|
2989
|
+
tinybird.sql_template.SQLTemplateException: Template Syntax Error: Secret 'EMPTY_SECRET' resolves to an empty value and cannot be used in sink metadata.
|
|
2962
2990
|
"""
|
|
2963
2991
|
if not secrets:
|
|
2964
2992
|
secrets = {}
|
|
@@ -2974,15 +3002,24 @@ def render_template_with_secrets(name: str, content: str, secrets: Optional[Dict
|
|
|
2974
3002
|
The secret value or default
|
|
2975
3003
|
|
|
2976
3004
|
Raises:
|
|
2977
|
-
SQLTemplateException: If the secret is not found and no default is provided
|
|
3005
|
+
SQLTemplateException: If the secret is not found and no default is provided,
|
|
3006
|
+
or if empty_secret_raises is True and the resolved value is empty
|
|
2978
3007
|
"""
|
|
2979
3008
|
if secret_name in secrets:
|
|
2980
3009
|
value = secrets[secret_name]
|
|
2981
3010
|
if isinstance(value, str) and len(value) == 0:
|
|
3011
|
+
if empty_secret_raises:
|
|
3012
|
+
raise SQLTemplateException(
|
|
3013
|
+
f"Secret '{secret_name}' resolves to an empty value and cannot be used in sink metadata."
|
|
3014
|
+
)
|
|
2982
3015
|
return '""'
|
|
2983
3016
|
return value
|
|
2984
3017
|
elif default is not None:
|
|
2985
3018
|
if isinstance(default, str) and len(default) == 0:
|
|
3019
|
+
if empty_secret_raises:
|
|
3020
|
+
raise SQLTemplateException(
|
|
3021
|
+
f"Secret '{secret_name}' resolves to an empty value and cannot be used in sink metadata."
|
|
3022
|
+
)
|
|
2986
3023
|
return '""'
|
|
2987
3024
|
return default
|
|
2988
3025
|
else:
|
tinybird/sql_toolset.py
CHANGED
|
@@ -158,7 +158,20 @@ def has_unoptimized_join(sql: str, left_table: Optional[Union[Tuple[str, str], T
|
|
|
158
158
|
raise UnoptimizedJoinException(sql)
|
|
159
159
|
|
|
160
160
|
|
|
161
|
-
def
|
|
161
|
+
def _format_fragment_for_mutation_command(fragment: str) -> str:
|
|
162
|
+
"""Normalize a SQL fragment the way CH stores it in the
|
|
163
|
+
`system.mutations.command` column: format the expression with CH's own
|
|
164
|
+
formatter, then escape it as it appears inside the serialized command
|
|
165
|
+
(string literals keep backslash-escaped quotes)."""
|
|
166
|
+
formatted = chquery.format(f"""SELECT {fragment}""").split("SELECT ")[1]
|
|
167
|
+
formatted = formatted.replace("\\", "\\\\").replace("'", "''")
|
|
168
|
+
quoted = chquery.format(f"SELECT '{formatted}'").split("SELECT ")[1]
|
|
169
|
+
return quoted[1:-1]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def format_where_for_mutation_command(
|
|
173
|
+
where_clause: str, lightweight: bool = False, partition: Optional[str] = None
|
|
174
|
+
) -> str:
|
|
162
175
|
"""
|
|
163
176
|
>>> format_where_for_mutation_command("numnights = 99")
|
|
164
177
|
'DELETE WHERE numnights = 99'
|
|
@@ -172,12 +185,18 @@ def format_where_for_mutation_command(where_clause: str, lightweight: bool = Fal
|
|
|
172
185
|
"DELETE WHERE reservationid = \\\\'\\\\\\\\\\\\'foo\\\\'"
|
|
173
186
|
>>> format_where_for_mutation_command("number < 3", lightweight=True)
|
|
174
187
|
'UPDATE _row_exists = 0 WHERE number < 3'
|
|
188
|
+
>>> format_where_for_mutation_command("number < 3", lightweight=True, partition="201901")
|
|
189
|
+
'UPDATE _row_exists = 0 IN PARTITION 201901 WHERE number < 3'
|
|
190
|
+
>>> format_where_for_mutation_command("number < 3", lightweight=True, partition="'2019-01-01'")
|
|
191
|
+
"UPDATE _row_exists = 0 IN PARTITION \\\\'2019-01-01\\\\' WHERE number < 3"
|
|
175
192
|
"""
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
193
|
+
quoted_condition = _format_fragment_for_mutation_command(where_clause)
|
|
194
|
+
prefix = "UPDATE _row_exists = 0" if lightweight else "DELETE"
|
|
195
|
+
# Partition-scoped mutations store the partition expression in the
|
|
196
|
+
# command (`… IN PARTITION <expr> WHERE <cond>`), normalized by the same
|
|
197
|
+
# CH formatter, so it must be part of the match.
|
|
198
|
+
partition_clause = f" IN PARTITION {_format_fragment_for_mutation_command(partition)}" if partition else ""
|
|
199
|
+
return f"{prefix}{partition_clause} WHERE {quoted_condition}"
|
|
181
200
|
|
|
182
201
|
|
|
183
202
|
# Functions that take table/dictionary names as string literal arguments.
|
tinybird/tb/__cli__.py
CHANGED
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/forward/commands'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '4.6.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '4.6.13.dev0'
|
|
8
|
+
__revision__ = '9f77ad2'
|
tinybird/tb/client.py
CHANGED
|
@@ -546,20 +546,36 @@ class TinyB:
|
|
|
546
546
|
def datasource_sync(self, datasource_id: str):
|
|
547
547
|
return self._req(f"/v0/datasources/{datasource_id}/scheduling/runs", method="POST", data="")
|
|
548
548
|
|
|
549
|
-
def datasource_sample(
|
|
550
|
-
|
|
549
|
+
def datasource_sample(
|
|
550
|
+
self,
|
|
551
|
+
datasource_name: str,
|
|
552
|
+
max_files: int = 1,
|
|
553
|
+
rows: Optional[int] = None,
|
|
554
|
+
max_bytes: Optional[str] = None,
|
|
555
|
+
full_export: bool = False,
|
|
556
|
+
) -> Dict[str, Any]:
|
|
557
|
+
"""Start a sample import job for an S3/GCS/DynamoDB connected datasource.
|
|
551
558
|
|
|
552
559
|
Args:
|
|
553
560
|
datasource_name: Name of the datasource to import sample data into
|
|
554
|
-
max_files: Maximum number of files to import (default 1, max 10)
|
|
561
|
+
max_files: Maximum number of files to import for blob storage connectors (default 1, max 10)
|
|
562
|
+
rows: For DynamoDB, the maximum number of rows to scan and import (mutually exclusive with max_bytes)
|
|
563
|
+
max_bytes: For DynamoDB, the maximum approximate JSONEachRow bytes to import, capped by the server's
|
|
564
|
+
workspace limit (mutually exclusive with rows)
|
|
565
|
+
full_export: For DynamoDB, trigger a full PITR export instead of a bounded scan
|
|
555
566
|
|
|
556
567
|
Returns:
|
|
557
568
|
dict with job info including id, job_id, job_url, job, status
|
|
558
569
|
"""
|
|
570
|
+
payload: Dict[str, Any] = {"max_files": max_files, "full_export": full_export}
|
|
571
|
+
if rows is not None:
|
|
572
|
+
payload["rows"] = rows
|
|
573
|
+
if max_bytes is not None:
|
|
574
|
+
payload["max_bytes"] = max_bytes
|
|
559
575
|
return self._req(
|
|
560
576
|
f"/v0/datasources/{datasource_name}/sample",
|
|
561
577
|
method="POST",
|
|
562
|
-
data=json.dumps(
|
|
578
|
+
data=json.dumps(payload),
|
|
563
579
|
)
|
|
564
580
|
|
|
565
581
|
def datasource_scheduling_state(self, datasource_id: str):
|
tinybird/tb/modules/cli.py
CHANGED
|
@@ -1153,15 +1153,18 @@ def create_ctx_client(
|
|
|
1153
1153
|
if show_warnings and command:
|
|
1154
1154
|
click.echo(FeedbackManager.gray(message="Running against Tinybird Local"))
|
|
1155
1155
|
local_branch = None
|
|
1156
|
-
|
|
1156
|
+
explicit_token_passed = bool(config.get("token_passed"))
|
|
1157
|
+
if not test and not explicit_token_passed:
|
|
1157
1158
|
git_branch = get_current_git_branch()
|
|
1158
1159
|
if git_branch and not is_main_git_branch(git_branch):
|
|
1159
1160
|
local_branch = get_tinybird_branch_name_from_git_branch(git_branch)
|
|
1160
1161
|
ctx.ensure_object(dict)["git_branch"] = git_branch
|
|
1161
1162
|
client, workspace_created = get_tinybird_local_client(config, test=test, staging=staging, branch=local_branch)
|
|
1162
|
-
if local_branch:
|
|
1163
|
+
if local_branch and config.get("local_workspace_name") == local_branch:
|
|
1163
1164
|
ctx.ensure_object(dict)["local_branch"] = local_branch
|
|
1164
1165
|
ctx.ensure_object(dict)["branch_created"] = workspace_created
|
|
1166
|
+
if show_warnings and command not in ("build", "dev"):
|
|
1167
|
+
click.echo(FeedbackManager.gray(message=f"Using Tinybird Local branch '{local_branch}'"))
|
|
1165
1168
|
return client
|
|
1166
1169
|
|
|
1167
1170
|
|
tinybird/tb/modules/common.py
CHANGED
|
@@ -1614,6 +1614,7 @@ def run_aws_iamrole_connection_flow(
|
|
|
1614
1614
|
connection_name: str,
|
|
1615
1615
|
policy: str,
|
|
1616
1616
|
local_unavailable: bool = False,
|
|
1617
|
+
env: str = "local",
|
|
1617
1618
|
) -> Tuple[str, str, Optional[TinyB], Optional[TinyB]]:
|
|
1618
1619
|
"""
|
|
1619
1620
|
Run the interactive AWS IAM Role connection flow for S3 or DynamoDB.
|
|
@@ -1628,6 +1629,9 @@ def run_aws_iamrole_connection_flow(
|
|
|
1628
1629
|
connection_name: The name for the connection being created.
|
|
1629
1630
|
policy: The access policy type ('read' or 'write').
|
|
1630
1631
|
local_unavailable: If True, local environment is unavailable (e.g., missing AWS credentials).
|
|
1632
|
+
env: The active target environment ('local' or 'cloud'). When not local, the
|
|
1633
|
+
passed-in `client` is reused as the cloud client so secrets land in the
|
|
1634
|
+
workspace the command targets (including branches).
|
|
1631
1635
|
|
|
1632
1636
|
Returns:
|
|
1633
1637
|
A tuple containing:
|
|
@@ -1736,12 +1740,15 @@ def run_aws_iamrole_connection_flow(
|
|
|
1736
1740
|
|
|
1737
1741
|
if use_cloud:
|
|
1738
1742
|
try:
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1743
|
+
if env != "local":
|
|
1744
|
+
cloud_client = client
|
|
1745
|
+
else:
|
|
1746
|
+
cloud_client = TinyB(
|
|
1747
|
+
token=config.get("token", ""),
|
|
1748
|
+
host=config.get("host", ""),
|
|
1749
|
+
staging=False,
|
|
1750
|
+
request_from=getattr(client, "request_from", None),
|
|
1751
|
+
)
|
|
1745
1752
|
except Exception as e:
|
|
1746
1753
|
click.echo(FeedbackManager.warning(message=f"Failed to initialize cloud client: {e}"))
|
|
1747
1754
|
click.echo(FeedbackManager.warning(message="Continuing without cloud environment."))
|
|
@@ -363,6 +363,7 @@ def connection_create_s3(
|
|
|
363
363
|
connection_name=connection_name,
|
|
364
364
|
policy=access_type.lower(),
|
|
365
365
|
local_unavailable=local_aws_unavailable,
|
|
366
|
+
env=env,
|
|
366
367
|
)
|
|
367
368
|
unique_suffix = uuid.uuid4().hex[:8] # Use first 8 chars of a UUID for brevity
|
|
368
369
|
secret_name = f"s3_role_arn_{connection_name}_{unique_suffix}"
|
|
@@ -862,20 +862,50 @@ def datasource_sync(ctx: Context, datasource_name: str, yes: bool):
|
|
|
862
862
|
default=False,
|
|
863
863
|
help="Wait for the import job to finish",
|
|
864
864
|
)
|
|
865
|
+
@click.option(
|
|
866
|
+
"--rows",
|
|
867
|
+
default=None,
|
|
868
|
+
type=int,
|
|
869
|
+
help="For DynamoDB, the maximum number of rows to scan and import (default 1500; mutually exclusive with --max-bytes)",
|
|
870
|
+
)
|
|
871
|
+
@click.option(
|
|
872
|
+
"--max-bytes",
|
|
873
|
+
default=None,
|
|
874
|
+
type=str,
|
|
875
|
+
help="For DynamoDB, the maximum approximate JSONEachRow bytes to import, e.g. 500MB (capped at 10GB by default; mutually exclusive with --rows)",
|
|
876
|
+
)
|
|
877
|
+
@click.option(
|
|
878
|
+
"--full-export",
|
|
879
|
+
is_flag=True,
|
|
880
|
+
default=False,
|
|
881
|
+
help="For DynamoDB, trigger a full PITR export instead of a bounded sample (mutually exclusive with --rows and --max-bytes)",
|
|
882
|
+
)
|
|
865
883
|
@click.pass_context
|
|
866
|
-
def datasource_sample(
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
884
|
+
def datasource_sample(
|
|
885
|
+
ctx: Context,
|
|
886
|
+
datasource_name: str,
|
|
887
|
+
max_files: int,
|
|
888
|
+
wait: bool,
|
|
889
|
+
rows: Optional[int],
|
|
890
|
+
max_bytes: Optional[str],
|
|
891
|
+
full_export: bool,
|
|
892
|
+
) -> None:
|
|
893
|
+
"""Import sample data from a datasource connected to S3, GCS, or DynamoDB.
|
|
894
|
+
|
|
895
|
+
For S3 and GCS, this imports a limited number of files from the bucket URI
|
|
896
|
+
pattern. For DynamoDB, this scans and imports a bounded sample limited by
|
|
897
|
+
either --rows or --max-bytes (defaulting to 1500 rows), or --full-export to
|
|
898
|
+
trigger a PITR export of the whole table.
|
|
873
899
|
|
|
874
900
|
By default, returns immediately with job info. Use --wait to block until complete.
|
|
875
901
|
|
|
876
902
|
Examples:
|
|
877
903
|
tb --branch=my_branch datasource sample my_s3_ds
|
|
878
904
|
tb --branch=my_branch datasource sample my_s3_ds --max-files 3 --wait
|
|
905
|
+
tb --branch=my_branch datasource sample my_dynamodb_ds --wait
|
|
906
|
+
tb --branch=my_branch datasource sample my_dynamodb_ds --rows 100000 --wait
|
|
907
|
+
tb --branch=my_branch datasource sample my_dynamodb_ds --max-bytes 1GB --wait
|
|
908
|
+
tb --branch=my_branch datasource sample my_dynamodb_ds --full-export --wait
|
|
879
909
|
"""
|
|
880
910
|
from tinybird.tb.modules.common import wait_job
|
|
881
911
|
from tinybird.tb.modules.job_common import echo_job_url
|
|
@@ -884,10 +914,32 @@ def datasource_sample(ctx: Context, datasource_name: str, max_files: int, wait:
|
|
|
884
914
|
client: TinyB = ctx.obj["client"]
|
|
885
915
|
config = ctx.obj.get("config", {})
|
|
886
916
|
|
|
917
|
+
if rows is not None and max_bytes is not None:
|
|
918
|
+
raise CLIDatasourceException(
|
|
919
|
+
FeedbackManager.error(message="--rows and --max-bytes are mutually exclusive; pass only one.")
|
|
920
|
+
)
|
|
921
|
+
|
|
922
|
+
if full_export and (rows is not None or max_bytes is not None):
|
|
923
|
+
raise CLIDatasourceException(
|
|
924
|
+
FeedbackManager.error(message="--full-export cannot be combined with --rows or --max-bytes.")
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
if full_export:
|
|
928
|
+
click.echo(
|
|
929
|
+
FeedbackManager.warning(
|
|
930
|
+
message=(
|
|
931
|
+
"DynamoDB full export samples will import the whole table. "
|
|
932
|
+
"Use --rows or --max-bytes without --full-export for a bounded sample."
|
|
933
|
+
)
|
|
934
|
+
)
|
|
935
|
+
)
|
|
936
|
+
|
|
887
937
|
click.echo(FeedbackManager.info(message=f"Starting sample import for {datasource_name}..."))
|
|
888
938
|
|
|
889
939
|
# Start the job
|
|
890
|
-
result = client.datasource_sample(
|
|
940
|
+
result = client.datasource_sample(
|
|
941
|
+
datasource_name, max_files=max_files, rows=rows, max_bytes=max_bytes, full_export=full_export
|
|
942
|
+
)
|
|
891
943
|
|
|
892
944
|
job_id = result.get("job_id") or result.get("id")
|
|
893
945
|
if not job_id:
|
tinybird/tb/modules/local.py
CHANGED
|
@@ -9,7 +9,12 @@ import requests
|
|
|
9
9
|
from docker.client import DockerClient
|
|
10
10
|
|
|
11
11
|
from tinybird.tb.client import AuthNoTokenException
|
|
12
|
-
from tinybird.tb.modules.cli import
|
|
12
|
+
from tinybird.tb.modules.cli import (
|
|
13
|
+
cli,
|
|
14
|
+
get_current_git_branch,
|
|
15
|
+
get_tinybird_branch_name_from_git_branch,
|
|
16
|
+
is_main_git_branch,
|
|
17
|
+
)
|
|
13
18
|
from tinybird.tb.modules.common import (
|
|
14
19
|
_get_workspace_plan_name,
|
|
15
20
|
echo_json,
|
|
@@ -80,9 +85,6 @@ def clear_local_workspace() -> None:
|
|
|
80
85
|
user_token = tokens["user_token"]
|
|
81
86
|
admin_token = tokens["admin_token"]
|
|
82
87
|
user_client = config.get_client(host=TB_LOCAL_ADDRESS, token=user_token)
|
|
83
|
-
ws_name = config.get("name")
|
|
84
|
-
if not ws_name:
|
|
85
|
-
raise AuthNoTokenException()
|
|
86
88
|
|
|
87
89
|
user_workspaces = requests.get(
|
|
88
90
|
f"{TB_LOCAL_ADDRESS}/v1/user/workspaces?with_organization=true&token={admin_token}"
|
|
@@ -90,19 +92,30 @@ def clear_local_workspace() -> None:
|
|
|
90
92
|
user_org_id = user_workspaces.get("organization_id", {})
|
|
91
93
|
local_workspaces = user_workspaces.get("workspaces", [])
|
|
92
94
|
|
|
95
|
+
branch_ws_name = None
|
|
96
|
+
ws_name = config.get("name")
|
|
97
|
+
git_branch = get_current_git_branch()
|
|
98
|
+
if git_branch and not is_main_git_branch(git_branch):
|
|
99
|
+
branch_ws_name = get_tinybird_branch_name_from_git_branch(git_branch)
|
|
100
|
+
if branch_ws_name:
|
|
101
|
+
ws_name = branch_ws_name
|
|
102
|
+
if not ws_name:
|
|
103
|
+
raise AuthNoTokenException()
|
|
104
|
+
|
|
93
105
|
ws = next((ws for ws in local_workspaces if ws["name"] == ws_name), None)
|
|
94
106
|
|
|
95
|
-
if not ws:
|
|
107
|
+
if not ws and ws_name != branch_ws_name:
|
|
96
108
|
raise CLILocalException(FeedbackManager.error(message=f"Workspace '{ws_name}' not found."))
|
|
97
109
|
|
|
98
|
-
requests.delete(f"{TB_LOCAL_ADDRESS}/v1/workspaces/{ws['id']}?token={user_token}&hard_delete_confirmation=yes")
|
|
99
|
-
user_workspaces = user_client.user_workspaces(version="v1")
|
|
100
|
-
ws = next((ws for ws in user_workspaces["workspaces"] if ws["name"] == ws_name), None)
|
|
101
|
-
|
|
102
110
|
if ws:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
111
|
+
requests.delete(f"{TB_LOCAL_ADDRESS}/v1/workspaces/{ws['id']}?token={user_token}&hard_delete_confirmation=yes")
|
|
112
|
+
user_workspaces = user_client.user_workspaces(version="v1")
|
|
113
|
+
ws = next((ws for ws in user_workspaces["workspaces"] if ws["name"] == ws_name), None)
|
|
114
|
+
|
|
115
|
+
if ws:
|
|
116
|
+
raise CLILocalException(
|
|
117
|
+
FeedbackManager.error(message=f"Workspace '{ws_name}' was not cleared properly. Please try again.")
|
|
118
|
+
)
|
|
106
119
|
|
|
107
120
|
user_client.create_workspace(ws_name, assign_to_organization_id=user_org_id, version="v1")
|
|
108
121
|
user_workspaces = requests.get(f"{TB_LOCAL_ADDRESS}/v1/user/workspaces?token={admin_token}").json()
|
|
@@ -79,7 +79,10 @@ def get_tinybird_local_client(
|
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
def get_tinybird_local_config(
|
|
82
|
-
config_obj: Dict[str, Any],
|
|
82
|
+
config_obj: Dict[str, Any],
|
|
83
|
+
test: bool = False,
|
|
84
|
+
silent: bool = False,
|
|
85
|
+
branch: Optional[str] = None,
|
|
83
86
|
) -> tuple[CLIConfig, bool]:
|
|
84
87
|
"""Craft a client config with a workspace name based on the path of the project files.
|
|
85
88
|
|
|
@@ -143,6 +146,8 @@ def get_tinybird_local_config(
|
|
|
143
146
|
raise AuthNoTokenException()
|
|
144
147
|
workspace_created = True
|
|
145
148
|
|
|
149
|
+
config_obj["local_workspace_name"] = ws_name
|
|
150
|
+
|
|
146
151
|
ws_token = ws["token"]
|
|
147
152
|
config.set_token(ws_token)
|
|
148
153
|
config.set_token_for_host(TB_LOCAL_ADDRESS, ws_token)
|
tinybird/tb/modules/logs.py
CHANGED
|
@@ -21,7 +21,6 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
|
21
21
|
|
|
22
22
|
LOG_SOURCES: Tuple[str, ...] = (
|
|
23
23
|
"tinybird.pipe_stats_rt",
|
|
24
|
-
"tinybird.bi_stats_rt",
|
|
25
24
|
"tinybird.block_log",
|
|
26
25
|
"tinybird.datasources_ops_log",
|
|
27
26
|
"tinybird.endpoint_errors",
|
|
@@ -39,7 +38,6 @@ DEFAULT_LOG_SOURCES: Tuple[str, ...] = (
|
|
|
39
38
|
|
|
40
39
|
TIMESTAMP_COLUMNS: Dict[str, str] = {
|
|
41
40
|
"tinybird.pipe_stats_rt": "start_datetime",
|
|
42
|
-
"tinybird.bi_stats_rt": "start_datetime",
|
|
43
41
|
"tinybird.block_log": "timestamp",
|
|
44
42
|
"tinybird.datasources_ops_log": "timestamp",
|
|
45
43
|
"tinybird.endpoint_errors": "start_datetime",
|
|
@@ -61,16 +59,6 @@ RELEVANT_DETAIL_FIELDS: Dict[str, Tuple[str, ...]] = {
|
|
|
61
59
|
"read_bytes",
|
|
62
60
|
"result_rows",
|
|
63
61
|
),
|
|
64
|
-
"tinybird.bi_stats_rt": (
|
|
65
|
-
"query_normalized",
|
|
66
|
-
"error_code",
|
|
67
|
-
"error",
|
|
68
|
-
"duration",
|
|
69
|
-
"read_rows",
|
|
70
|
-
"read_bytes",
|
|
71
|
-
"result_rows",
|
|
72
|
-
"result_bytes",
|
|
73
|
-
),
|
|
74
62
|
"tinybird.block_log": (
|
|
75
63
|
"datasource_name",
|
|
76
64
|
"status",
|
|
@@ -207,7 +195,7 @@ _TEMPORAL_DETAIL_FIELDS = {
|
|
|
207
195
|
_DURATION_DETAIL_FIELDS = {"duration", "elapsed_time", "processing_time"}
|
|
208
196
|
_ROW_COUNT_DETAIL_FIELDS = {"rows", "read_rows", "written_rows", "result_rows", "quarantine_lines"}
|
|
209
197
|
_BYTE_COUNT_DETAIL_FIELDS = {"bytes", "read_bytes", "result_bytes", "written_bytes"}
|
|
210
|
-
_MILLISECOND_DURATION_SOURCES =
|
|
198
|
+
_MILLISECOND_DURATION_SOURCES: Set[str] = set()
|
|
211
199
|
|
|
212
200
|
|
|
213
201
|
def _to_iso_utc(dt: datetime) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird
|
|
3
|
-
Version: 4.6.
|
|
3
|
+
Version: 4.6.13.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -52,7 +52,34 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
54
|
|
|
55
|
-
4.6.
|
|
55
|
+
4.6.12
|
|
56
|
+
********
|
|
57
|
+
|
|
58
|
+
- `Added` Forward sink pipes support ``{{ tb_secret(...) }}`` in ``EXPORT_*`` metadata (for example ``EXPORT_BUCKET_URI``). Secrets are resolved at deploy time and baked into the sink settings; changing a secret requires a redeploy.
|
|
59
|
+
- `Fixed` Forward deploy now raises an error when a secret used in sink metadata resolves to an empty value.
|
|
60
|
+
- `Fixed` Forward deploy now rejects ``{{ tb_secret(...) }}`` in ``EXPORT_SCHEDULE`` and ``COPY_SCHEDULE``. Use a literal cron expression (for example ``0 * * * *``) or ``@on-demand``.
|
|
61
|
+
|
|
62
|
+
4.6.11
|
|
63
|
+
********
|
|
64
|
+
|
|
65
|
+
- `Added` `tb datasource sample` support for DynamoDB connectors.
|
|
66
|
+
|
|
67
|
+
4.6.10
|
|
68
|
+
********
|
|
69
|
+
|
|
70
|
+
- `Removed` `tinybird.bi_stats_rt` from `tb logs` sources. The BI Connector `bi_stats` / `bi_stats_rt` service datasources are deprecated.
|
|
71
|
+
|
|
72
|
+
4.6.9
|
|
73
|
+
*******
|
|
74
|
+
|
|
75
|
+
- `Fixed` Commands run against Tinybird Local with an explicit token (``--token``) now target the token's workspace.
|
|
76
|
+
|
|
77
|
+
4.6.8
|
|
78
|
+
*******
|
|
79
|
+
|
|
80
|
+
- `Fixed` Tinybird Local CLI commands to respect Git branch local workspaces correctly.
|
|
81
|
+
|
|
82
|
+
4.6.7
|
|
56
83
|
*******
|
|
57
84
|
|
|
58
85
|
- `Fixed` `tb login` now raises an actionable error when the CLI cannot complete the authentication.
|
|
@@ -3,41 +3,41 @@ tinybird/datatypes.py,sha256=DRScTI1-lgYjbC7u_4qxOLFleWL-vief_eBg_9WU37U,11304
|
|
|
3
3
|
tinybird/feedback_manager.py,sha256=ZnRsExCkEZKuslmSxn3m706-0UIZ_qOpdek9ar16KOI,68001
|
|
4
4
|
tinybird/git_settings.py,sha256=mqWgeboOlOFsSo97qyv595UCR2R1QCAqT4GTawBNPBg,3935
|
|
5
5
|
tinybird/prompts.py,sha256=FNYpphDYlrXpm5AQM3yfQPbj4gd_TVnwoaoeswtx0OE,32699
|
|
6
|
-
tinybird/service_datasources.py,sha256=
|
|
6
|
+
tinybird/service_datasources.py,sha256=asBTXONMv7sf7LFBx1a4eTcZCHPUq-I3r030AtorRzY,53643
|
|
7
7
|
tinybird/sql.py,sha256=L3tTmm62iTrf6WQdcV8mmwrCMitLFUvJ3OfDzyRTMGw,47385
|
|
8
|
-
tinybird/sql_template.py,sha256=
|
|
8
|
+
tinybird/sql_template.py,sha256=Mus34RE6DBcq57mGRu6vibXuCgov9htTPqqSkNknmR0,129666
|
|
9
9
|
tinybird/sql_template_fmt.py,sha256=Ma4qcs-2r8ZXQC4GUmrCqYz34DsnGF8k5lE2Jwnr314,10638
|
|
10
|
-
tinybird/sql_toolset.py,sha256=
|
|
10
|
+
tinybird/sql_toolset.py,sha256=I_RHAfhpYuIc3bNY9VcNjQ3zESAawb3D9ZMjb9-ev4M,28519
|
|
11
11
|
tinybird/syncasync.py,sha256=rIPmCvygWSFqfnlVqhZH4N9gVVTvD6DEPsfoxGizYrI,27776
|
|
12
12
|
tinybird/tornado_template.py,sha256=1_0nYFk_xJh_TMHh6AKkJILvnNY6xYmaM-uJ3Ofv7e8,42085
|
|
13
13
|
tinybird/ch_utils/constants.py,sha256=yTNizMzgYNBzUc2EV3moBfdrDIggOe9hiuAgWF7sv2c,4333
|
|
14
|
-
tinybird/ch_utils/engine.py,sha256=
|
|
15
|
-
tinybird/datafile/common.py,sha256=
|
|
14
|
+
tinybird/ch_utils/engine.py,sha256=OkR86FOOUPRpCsRxlR-kunykg-K4Daqo3uS06X1uvYQ,36887
|
|
15
|
+
tinybird/datafile/common.py,sha256=pLB5GmCCDLnafDEGp_-HnS8z_dYLTclYSk_bBpEhpro,111128
|
|
16
16
|
tinybird/datafile/exceptions.py,sha256=8rw2umdZjtby85QbuRKFO5ETz_eRHwUY5l7eHsy1wnI,556
|
|
17
17
|
tinybird/datafile/parse_connection.py,sha256=GxmGp_XnWbDZPDbh_PBxitlIMqZRYfDwxMBw-JQBp1g,1890
|
|
18
18
|
tinybird/datafile/parse_datasource.py,sha256=yd58HrUF4yNJXLn6OsvKGpZJpvrcjLGAeJG1lgBe_zk,1891
|
|
19
19
|
tinybird/datafile/parse_pipe.py,sha256=-9bbgVuiWRyDYydrLVflDBt8GstZotMy6dklsrc6MUY,3859
|
|
20
20
|
tinybird/iterating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
tinybird/iterating/data_branch_modes.py,sha256=5YuDa-gr8mKwmES8Xro6TRKbQtaOtIw4GbC606Qhu3o,184
|
|
22
|
-
tinybird/tb/__cli__.py,sha256=
|
|
22
|
+
tinybird/tb/__cli__.py,sha256=GqDS3d3b9YPNF68yqEjPdtNXJzS_oz7KOt2Mo9nxlCk,246
|
|
23
23
|
tinybird/tb/check_pypi.py,sha256=Gp0HkHHDFMSDL6nxKlOY51z7z1Uv-2LRexNTZSHHGmM,552
|
|
24
24
|
tinybird/tb/cli.py,sha256=IjiGfNIpxSxi1odK1kMj9s8lEhx3sAUgGA263XdmyR0,1119
|
|
25
|
-
tinybird/tb/client.py,sha256=
|
|
25
|
+
tinybird/tb/client.py,sha256=LQ470JkU9NQcmM_rjElD_aV2l8nlWHTKuqzC3Yx1IzM,57605
|
|
26
26
|
tinybird/tb/config.py,sha256=l6NtYvSPZDVOtt1W4G4ExXXDIf0hm6lvRnRoDMbdrsY,5429
|
|
27
27
|
tinybird/tb/modules/branch.py,sha256=U50nj2kZllCkOHQfJWQ-YQ260pvlcssgStMSovmqMiU,10157
|
|
28
28
|
tinybird/tb/modules/build.py,sha256=q7-aVM7q1tApiax_y6vYSCZq4cJ9ATSAm9D-elpNp7I,6543
|
|
29
29
|
tinybird/tb/modules/build_common.py,sha256=o04aeaoyGTnwhR0cEXAgQzc7SJya97YECoEihsi4SyU,24979
|
|
30
30
|
tinybird/tb/modules/cicd.py,sha256=IO4qqsoLRXcubALb7vx_QnRpg3zIIxfaVO9bGomlESY,8267
|
|
31
|
-
tinybird/tb/modules/cli.py,sha256=
|
|
32
|
-
tinybird/tb/modules/common.py,sha256=
|
|
31
|
+
tinybird/tb/modules/cli.py,sha256=oerpcsZ3vLsLZdCjgtVa6F9D3OFj-cqWFJfX-M40N2c,44038
|
|
32
|
+
tinybird/tb/modules/common.py,sha256=XWuEIpMo3-JkplFqPzgxQqJDKAZD7rujY2VOXerGPPQ,93355
|
|
33
33
|
tinybird/tb/modules/config.py,sha256=kZsMBf_qrGXPvhx1GW46DXS62ClVIKFFPjDXEZyGeyE,11181
|
|
34
34
|
tinybird/tb/modules/connection.py,sha256=HwHn0YgwqcKEYCLr2OqDzJzAUFd65Wv8MZiSUw_TLII,18452
|
|
35
|
-
tinybird/tb/modules/connection_dynamodb.py,sha256=
|
|
35
|
+
tinybird/tb/modules/connection_dynamodb.py,sha256=vaB28d6t8nOd6kcUQGMUkl3IZin5DYSBN2TBPm2968Q,9490
|
|
36
36
|
tinybird/tb/modules/connection_kafka.py,sha256=Qc8uUNl5SvUcUGb_aG3AirYKw6673FoX1Sfdlzgz6Y8,33530
|
|
37
|
-
tinybird/tb/modules/connection_s3.py,sha256=
|
|
37
|
+
tinybird/tb/modules/connection_s3.py,sha256=eR7lsrCYbVWZ8LI7F5MUBxm8_DAvuaVSKqUDq9CUUks,16499
|
|
38
38
|
tinybird/tb/modules/copy.py,sha256=Apzjxiyinp6KmgamypPKEe3BAnpxG7MwYcSYkHiG8sA,6033
|
|
39
39
|
tinybird/tb/modules/create.py,sha256=G3_wCUjNVzBiowo70NgwzmUUXXOxYO2LWjF9eEfcffc,22947
|
|
40
|
-
tinybird/tb/modules/datasource.py,sha256=
|
|
40
|
+
tinybird/tb/modules/datasource.py,sha256=baxfUQd7vDyEDh65fyOa2X5Xwf4OS3ligyznbbpAo6Q,76671
|
|
41
41
|
tinybird/tb/modules/deployment.py,sha256=TNDlvaYmk-zouvaAdMXlyFPbgbnMKQOt76xpZBggJI0,21184
|
|
42
42
|
tinybird/tb/modules/deployment_common.py,sha256=fLPWNNs8ZwSkWHJjLeqQUqTbKqnnhW1y8yKffBdDCo0,31948
|
|
43
43
|
tinybird/tb/modules/deprecations.py,sha256=XXekrzPO9v12F1ToQDUGzLYJJ2wrEUlGKOkLCSdfHiM,4935
|
|
@@ -51,13 +51,13 @@ tinybird/tb/modules/job.py,sha256=gjUceRkepgseQe1Q23G8B25R06r2UfdEIIXlIaqBA5E,30
|
|
|
51
51
|
tinybird/tb/modules/job_common.py,sha256=3rdRH9F9kCRL_dBa5fghB27xgHqnO3oulBeIb1AcSbE,687
|
|
52
52
|
tinybird/tb/modules/llm.py,sha256=fPBBCmM3KlCksLlgJkg4joDn6y3H5QjDzE-Pm4YNf7E,1782
|
|
53
53
|
tinybird/tb/modules/llm_utils.py,sha256=qs3HKJ1Lcugoumq1gzOpYRyRerEcSK6Yy_80vWoEbco,3217
|
|
54
|
-
tinybird/tb/modules/local.py,sha256=
|
|
55
|
-
tinybird/tb/modules/local_common.py,sha256=
|
|
54
|
+
tinybird/tb/modules/local.py,sha256=HPMxwyKLpMT0D5NJSrSOWTjqNdSlDo4klrZrbtD3GkA,15326
|
|
55
|
+
tinybird/tb/modules/local_common.py,sha256=GBKys9rHgM25r-YNijaZoJIFH3ronN1eQnSC3eAEhFc,38930
|
|
56
56
|
tinybird/tb/modules/local_logs.py,sha256=TTrfEQr3wVoddrQiKslSWJQ8BE4FOlMQZbH1yJ5f56I,7427
|
|
57
57
|
tinybird/tb/modules/login.py,sha256=fxgcsN0fMhjzT_6C8VrwGTxnLxLVuWlZvASFr8I9yUU,1885
|
|
58
58
|
tinybird/tb/modules/login_common.py,sha256=oRIAJm1cwJ4t4hZb1RKRmyylZuYz0mrEBo0xTOZHSQ8,22185
|
|
59
59
|
tinybird/tb/modules/logout.py,sha256=sniI4JNxpTrVeRCp0oGJuQ3yRerG4hH5uz6oBmjv724,1009
|
|
60
|
-
tinybird/tb/modules/logs.py,sha256=
|
|
60
|
+
tinybird/tb/modules/logs.py,sha256=M05V2OgWqv2suaCzz8c5IDfCnXhVqZ9WIh8rNQpolSg,21165
|
|
61
61
|
tinybird/tb/modules/materialization.py,sha256=SaomNeaAzLWtcnsZdetYBxEq0ihY1cRzh23n3Z1P_c4,5643
|
|
62
62
|
tinybird/tb/modules/open.py,sha256=ddABA4guIrBhrCKXYpkH4cfiAcFOG2B1eVePk5BEXto,1799
|
|
63
63
|
tinybird/tb/modules/pipe.py,sha256=xPKtezhnWZ6k_g82r4XpgKslofhuIxb_PvynH4gdUzI,2393
|
|
@@ -99,8 +99,8 @@ tinybird/tb_cli_modules/config.py,sha256=Ey9yqM27C4Irglm5-63RXte8K0bFh8ConKdIoAa
|
|
|
99
99
|
tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
|
|
100
100
|
tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
|
|
101
101
|
tinybird/tb_cli_modules/telemetry.py,sha256=W098H6jmS4kpE7hN3tadaREBTf7oMocel-lkKWN0pU8,10466
|
|
102
|
-
tinybird-4.6.
|
|
103
|
-
tinybird-4.6.
|
|
104
|
-
tinybird-4.6.
|
|
105
|
-
tinybird-4.6.
|
|
106
|
-
tinybird-4.6.
|
|
102
|
+
tinybird-4.6.13.dev0.dist-info/METADATA,sha256=gJeFvTk8TuQQGSnCdwvIHXhQSPJhzgXW3PHVqHmDFyM,15709
|
|
103
|
+
tinybird-4.6.13.dev0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
|
104
|
+
tinybird-4.6.13.dev0.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
|
|
105
|
+
tinybird-4.6.13.dev0.dist-info/top_level.txt,sha256=ZIQJTPCzMqnfDzM_hEGZrJqDSEcKnIK_49T86DGWpyQ,78
|
|
106
|
+
tinybird-4.6.13.dev0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|