tinybird-cli 5.3.1.dev3__tar.gz → 5.3.1.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/PKG-INFO +17 -2
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/__cli__.py +2 -2
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/client.py +3 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/datafile.py +67 -8
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/feedback_manager.py +1 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/sql_template.py +4 -1
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/sql_toolset.py +9 -1
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/pipe.py +11 -1
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tornado_template.py +3 -6
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird_cli.egg-info/PKG-INFO +17 -2
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird_cli.egg-info/requires.txt +1 -1
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/setup.cfg +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/check_pypi.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/config.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/connectors.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/context.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/datatypes.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/git_settings.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/sql.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/syncasync.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/token.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird_cli.egg-info/SOURCES.txt +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird_cli.egg-info/dependency_links.txt +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird_cli.egg-info/entry_points.txt +0 -0
- {tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird_cli.egg-info/top_level.txt +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tinybird-cli
|
|
3
|
-
Version: 5.3.1.
|
|
3
|
+
Version: 5.3.1.dev5
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
7
7
|
Author-email: support@tinybird.co
|
|
8
|
-
Requires-Python: >=3.8, <3.
|
|
8
|
+
Requires-Python: >=3.8, <3.13
|
|
9
9
|
Description-Content-Type: text/x-rst
|
|
10
10
|
Provides-Extra: bigquery
|
|
11
11
|
Provides-Extra: snowflake
|
|
@@ -18,6 +18,21 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
18
18
|
Changelog
|
|
19
19
|
----------
|
|
20
20
|
|
|
21
|
+
5.3.1.dev5
|
|
22
|
+
**********
|
|
23
|
+
|
|
24
|
+
- `Fixed` Do not try to deploy shared Datafiles from the `vendor` folder on `tb deploy`
|
|
25
|
+
|
|
26
|
+
5.3.1.dev4
|
|
27
|
+
**********
|
|
28
|
+
|
|
29
|
+
- `Added` support to Python 3.12
|
|
30
|
+
|
|
31
|
+
5.3.1.dev3
|
|
32
|
+
**********
|
|
33
|
+
|
|
34
|
+
- `Added` support to Stream Pipes in `tb push` and `tb pull` commands. (Feature in development. It requires access)
|
|
35
|
+
|
|
21
36
|
5.3.1.dev2
|
|
22
37
|
**********
|
|
23
38
|
|
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/cli/introduction.html'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '5.3.1.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '5.3.1.dev5'
|
|
8
|
+
__revision__ = '4613f9c'
|
|
@@ -600,6 +600,9 @@ class TinyB(object):
|
|
|
600
600
|
async def pipe_remove_sink(self, pipe_name_or_id: str, node_id: str):
|
|
601
601
|
return await self._req(f"/v0/pipes/{pipe_name_or_id}/nodes/{node_id}/sink", method="DELETE")
|
|
602
602
|
|
|
603
|
+
async def pipe_remove_stream(self, pipe_name_or_id: str, node_id: str):
|
|
604
|
+
return await self._req(f"/v0/pipes/{pipe_name_or_id}/nodes/{node_id}/stream", method="DELETE")
|
|
605
|
+
|
|
603
606
|
async def pipe_run_sink(self, pipe_name_or_id: str, params: Optional[Dict[str, str]] = None):
|
|
604
607
|
params = {**params} if params else {}
|
|
605
608
|
return await self._req(f"/v0/pipes/{pipe_name_or_id}/sink?{urlencode(params)}", method="POST")
|
|
@@ -95,6 +95,7 @@ class PipeTypes:
|
|
|
95
95
|
ENDPOINT = "endpoint"
|
|
96
96
|
COPY = "copy"
|
|
97
97
|
DATA_SINK = "sink"
|
|
98
|
+
STREAM = "stream"
|
|
98
99
|
DEFAULT = "default"
|
|
99
100
|
|
|
100
101
|
|
|
@@ -105,6 +106,7 @@ class PipeNodeTypes:
|
|
|
105
106
|
DEFAULT = "default"
|
|
106
107
|
DATA_SINK = "sink"
|
|
107
108
|
COPY = "copy"
|
|
109
|
+
STREAM = "stream"
|
|
108
110
|
|
|
109
111
|
|
|
110
112
|
class DataFileExtensions:
|
|
@@ -190,8 +192,8 @@ class ImportReplacements:
|
|
|
190
192
|
|
|
191
193
|
|
|
192
194
|
class ExportReplacements:
|
|
193
|
-
SERVICES = ("gcs_hmac", "s3", "s3_iamrole")
|
|
194
|
-
NODE_TYPES = PipeNodeTypes.DATA_SINK
|
|
195
|
+
SERVICES = ("gcs_hmac", "s3", "s3_iamrole", "kafka")
|
|
196
|
+
NODE_TYPES = (PipeNodeTypes.DATA_SINK, PipeNodeTypes.STREAM)
|
|
195
197
|
_REPLACEMENTS = (
|
|
196
198
|
("export_service", "service", None),
|
|
197
199
|
("export_connection_name", "connection", None),
|
|
@@ -201,11 +203,20 @@ class ExportReplacements:
|
|
|
201
203
|
("export_format", "format", "csv"),
|
|
202
204
|
("export_compression", "compression", None),
|
|
203
205
|
("export_strategy", "strategy", "@new"),
|
|
206
|
+
("kafka_connection_name", "connection", None),
|
|
207
|
+
("kafka_topic", "kafka_topic", None),
|
|
208
|
+
("kafka_group_id", "kafka_group_id", None),
|
|
204
209
|
)
|
|
205
210
|
|
|
211
|
+
@staticmethod
|
|
212
|
+
def get_export_service(node: Dict[str, Optional[str]]) -> str:
|
|
213
|
+
if (node.get("type", "standard") or "standard").lower() == PipeNodeTypes.STREAM:
|
|
214
|
+
return "kafka"
|
|
215
|
+
return (node.get("export_service", "") or "").lower()
|
|
216
|
+
|
|
206
217
|
@staticmethod
|
|
207
218
|
def is_export_node(node: Dict[str, Optional[str]]) -> bool:
|
|
208
|
-
export_service =
|
|
219
|
+
export_service = ExportReplacements.get_export_service(node)
|
|
209
220
|
node_type = (node.get("type", "standard") or "standard").lower()
|
|
210
221
|
if not export_service:
|
|
211
222
|
return False
|
|
@@ -219,16 +230,26 @@ class ExportReplacements:
|
|
|
219
230
|
def get_params_from_datafile(node: Dict[str, Optional[str]]) -> Dict[str, Optional[str]]:
|
|
220
231
|
"""Returns the export parameters for a given node."""
|
|
221
232
|
params = {}
|
|
233
|
+
export_service = ExportReplacements.get_export_service(node)
|
|
222
234
|
for datafile_key, export_key, default_value in ExportReplacements._REPLACEMENTS:
|
|
235
|
+
if export_service != "kafka" and "kafka_" in datafile_key:
|
|
236
|
+
continue
|
|
237
|
+
if export_service == "kafka" and "export_" in datafile_key:
|
|
238
|
+
continue
|
|
223
239
|
if datafile_key == "export_schedule" and node.get(datafile_key, None) == ON_DEMAND:
|
|
224
240
|
node[datafile_key] = ""
|
|
225
241
|
params[export_key] = node[datafile_key] if datafile_key in node else default_value
|
|
226
242
|
return params
|
|
227
243
|
|
|
228
244
|
@staticmethod
|
|
229
|
-
def get_datafile_key(param: str) -> Optional[str]:
|
|
245
|
+
def get_datafile_key(param: str, node: Dict[str, Optional[str]]) -> Optional[str]:
|
|
230
246
|
"""Returns the datafile key for a given export parameter."""
|
|
247
|
+
export_service = ExportReplacements.get_export_service(node)
|
|
231
248
|
for datafile_k, export_k, _ in ExportReplacements._REPLACEMENTS:
|
|
249
|
+
if export_service != "kafka" and "kafka_" in datafile_k:
|
|
250
|
+
continue
|
|
251
|
+
if export_service == "kafka" and "export_" in datafile_k:
|
|
252
|
+
continue
|
|
232
253
|
if export_k == param.lower():
|
|
233
254
|
return datafile_k.upper()
|
|
234
255
|
return None
|
|
@@ -2323,6 +2344,8 @@ async def check_pipe(
|
|
|
2323
2344
|
await cl.pipe_remove_copy(current_pipe["id"], current_pipe["copy_node"])
|
|
2324
2345
|
if pipe_type == PipeTypes.DATA_SINK:
|
|
2325
2346
|
await cl.pipe_remove_sink(current_pipe["id"], current_pipe["sink_node"])
|
|
2347
|
+
if pipe_type == PipeTypes.STREAM:
|
|
2348
|
+
await cl.pipe_remove_stream(current_pipe["id"], current_pipe["stream_node"])
|
|
2326
2349
|
|
|
2327
2350
|
# In case of doing --force for a materialized view, checker is being created as standard pipe
|
|
2328
2351
|
for node in checker_pipe["nodes"]:
|
|
@@ -2525,6 +2548,9 @@ async def check_copy_pipe(pipe, copy_node, tb_client: TinyB):
|
|
|
2525
2548
|
if pipe_type == PipeTypes.DATA_SINK:
|
|
2526
2549
|
await tb_client.pipe_remove_sink(pipe_name, pipe["sink_node"])
|
|
2527
2550
|
|
|
2551
|
+
if pipe_type == PipeTypes.STREAM:
|
|
2552
|
+
await tb_client.pipe_remove_stream(pipe_name, pipe["stream_node"])
|
|
2553
|
+
|
|
2528
2554
|
|
|
2529
2555
|
async def check_sink_pipe(pipe, sink_node, tb_client: TinyB):
|
|
2530
2556
|
if not sink_node["export_params"]:
|
|
@@ -2548,6 +2574,29 @@ async def check_sink_pipe(pipe, sink_node, tb_client: TinyB):
|
|
|
2548
2574
|
if pipe_type == PipeTypes.COPY:
|
|
2549
2575
|
await tb_client.pipe_remove_copy(pipe_name, pipe["copy_node"])
|
|
2550
2576
|
|
|
2577
|
+
if pipe_type == PipeTypes.STREAM:
|
|
2578
|
+
await tb_client.pipe_remove_stream(pipe_name, pipe["stream_node"])
|
|
2579
|
+
|
|
2580
|
+
|
|
2581
|
+
async def check_stream_pipe(pipe, stream_node, tb_client: TinyB):
|
|
2582
|
+
if not stream_node["params"]:
|
|
2583
|
+
return
|
|
2584
|
+
|
|
2585
|
+
if not pipe:
|
|
2586
|
+
return
|
|
2587
|
+
|
|
2588
|
+
pipe_name = pipe["name"]
|
|
2589
|
+
pipe_type = pipe["type"]
|
|
2590
|
+
|
|
2591
|
+
if pipe_type == PipeTypes.ENDPOINT:
|
|
2592
|
+
await tb_client.pipe_remove_endpoint(pipe_name, pipe["endpoint"])
|
|
2593
|
+
|
|
2594
|
+
if pipe_type == PipeTypes.COPY:
|
|
2595
|
+
await tb_client.pipe_remove_copy(pipe_name, pipe["copy_node"])
|
|
2596
|
+
|
|
2597
|
+
if pipe_type == PipeTypes.DATA_SINK:
|
|
2598
|
+
await tb_client.pipe_remove_sink(pipe_name, pipe["sink_node"])
|
|
2599
|
+
|
|
2551
2600
|
|
|
2552
2601
|
def show_materialized_view_warnings(warnings):
|
|
2553
2602
|
"""
|
|
@@ -2635,6 +2684,7 @@ async def new_pipe(
|
|
|
2635
2684
|
is_materialized = any([node.get("params", {}).get("type", None) == "materialized" for node in p["nodes"]])
|
|
2636
2685
|
copy_node = next((node for node in p["nodes"] if node.get("params", {}).get("type", None) == "copy"), None)
|
|
2637
2686
|
sink_node = next((node for node in p["nodes"] if node.get("params", {}).get("type", None) == "sink"), None)
|
|
2687
|
+
stream_node = next((node for node in p["nodes"] if node.get("params", {}).get("type", None) == "stream"), None)
|
|
2638
2688
|
|
|
2639
2689
|
for node in p["nodes"]:
|
|
2640
2690
|
if node["params"]["name"] == p["name"]:
|
|
@@ -2644,7 +2694,7 @@ async def new_pipe(
|
|
|
2644
2694
|
if force or run_tests:
|
|
2645
2695
|
# TODO: this should create a different node and rename it to the final one on success
|
|
2646
2696
|
if check and not populate:
|
|
2647
|
-
if not is_materialized and not copy_node and not sink_node:
|
|
2697
|
+
if not is_materialized and not copy_node and not sink_node and not stream_node:
|
|
2648
2698
|
await check_pipe(
|
|
2649
2699
|
p,
|
|
2650
2700
|
host,
|
|
@@ -2680,6 +2730,8 @@ async def new_pipe(
|
|
|
2680
2730
|
await check_copy_pipe(pipe=current_pipe, copy_node=copy_node, tb_client=tb_client)
|
|
2681
2731
|
if sink_node:
|
|
2682
2732
|
await check_sink_pipe(pipe=current_pipe, sink_node=sink_node, tb_client=tb_client)
|
|
2733
|
+
if stream_node:
|
|
2734
|
+
await check_stream_pipe(pipe=current_pipe, stream_node=stream_node, tb_client=tb_client)
|
|
2683
2735
|
if run_tests:
|
|
2684
2736
|
logging.info(f"skipping force override of {p['name']}")
|
|
2685
2737
|
return
|
|
@@ -2727,6 +2779,9 @@ async def new_pipe(
|
|
|
2727
2779
|
if sink_node:
|
|
2728
2780
|
body.update(sink_node.get("export_params", {}))
|
|
2729
2781
|
|
|
2782
|
+
if stream_node:
|
|
2783
|
+
body.update(stream_node.get("export_params", {}))
|
|
2784
|
+
|
|
2730
2785
|
post_headers = {"Content-Type": "application/json"}
|
|
2731
2786
|
|
|
2732
2787
|
post_headers.update(headers)
|
|
@@ -3804,6 +3859,10 @@ async def build_graph(
|
|
|
3804
3859
|
processed_filename = f.relative_to(os.getcwd())
|
|
3805
3860
|
except ValueError:
|
|
3806
3861
|
processed_filename = f
|
|
3862
|
+
# This is to avoid processing shared data sources
|
|
3863
|
+
if "vendor/" in str(processed_filename):
|
|
3864
|
+
click.echo(FeedbackManager.info_skipping_resource(resource=processed_filename))
|
|
3865
|
+
continue
|
|
3807
3866
|
click.echo(FeedbackManager.info_processing_file(filename=processed_filename))
|
|
3808
3867
|
await process(str(f), deps, dep_map, to_run, workspace_lib_paths)
|
|
3809
3868
|
|
|
@@ -4703,7 +4762,6 @@ async def format_engine(
|
|
|
4703
4762
|
async def format_node_type(file_parts: List[str], node: Dict[str, Any]) -> List[str]:
|
|
4704
4763
|
node_type = node.get("type", "").lower()
|
|
4705
4764
|
node_type_upper = f"TYPE {node_type.upper()}"
|
|
4706
|
-
|
|
4707
4765
|
# Materialized pipe
|
|
4708
4766
|
if node_type == PipeNodeTypes.MATERIALIZED:
|
|
4709
4767
|
file_parts.append(node_type_upper)
|
|
@@ -4732,7 +4790,7 @@ async def format_node_type(file_parts: List[str], node: Dict[str, Any]) -> List[
|
|
|
4732
4790
|
file_parts.append(f"{CopyParameters.COPY_SCHEDULE.upper()} {ON_DEMAND}")
|
|
4733
4791
|
file_parts.append(DATAFILE_NEW_LINE)
|
|
4734
4792
|
|
|
4735
|
-
# Sink pipe
|
|
4793
|
+
# Sink or Stream pipe
|
|
4736
4794
|
if ExportReplacements.is_export_node(node):
|
|
4737
4795
|
file_parts.append(node_type_upper)
|
|
4738
4796
|
export_params = ExportReplacements.get_params_from_datafile(node)
|
|
@@ -4740,7 +4798,7 @@ async def format_node_type(file_parts: List[str], node: Dict[str, Any]) -> List[
|
|
|
4740
4798
|
for param, value in export_params.items():
|
|
4741
4799
|
if param == "schedule_cron" and not value:
|
|
4742
4800
|
value = ON_DEMAND
|
|
4743
|
-
datafile_key = ExportReplacements.get_datafile_key(param)
|
|
4801
|
+
datafile_key = ExportReplacements.get_datafile_key(param, node)
|
|
4744
4802
|
if datafile_key:
|
|
4745
4803
|
file_parts.append(f"{datafile_key} {value}")
|
|
4746
4804
|
file_parts.append(DATAFILE_NEW_LINE)
|
|
@@ -5189,6 +5247,7 @@ def is_endpoint_with_no_dependencies(
|
|
|
5189
5247
|
PipeNodeTypes.MATERIALIZED,
|
|
5190
5248
|
PipeNodeTypes.COPY,
|
|
5191
5249
|
PipeNodeTypes.DATA_SINK,
|
|
5250
|
+
PipeNodeTypes.STREAM,
|
|
5192
5251
|
]:
|
|
5193
5252
|
return False
|
|
5194
5253
|
|
|
@@ -709,6 +709,7 @@ Ready? """
|
|
|
709
709
|
info_unlinking_materialized_pipe = info_message("** Unlinking materialized pipe {pipe}")
|
|
710
710
|
info_unlinking_copy_pipe = info_message("** Unlinking copy pipe {pipe}")
|
|
711
711
|
info_unlinking_sink_pipe = info_message("** Unlinking sink pipe {pipe}")
|
|
712
|
+
info_unlinking_stream_pipe = info_message("** Unlinking stream pipe {pipe}")
|
|
712
713
|
info_materialized_unlinking_pipe_not_found = info_message("** {pipe} not found")
|
|
713
714
|
info_materialized_dry_unlinking_pipe = info_message("** [DRY RUN] Unlinking materialized pipe {pipe}")
|
|
714
715
|
info_copy_datasource_created = info_message("** Copy pipe '{pipe}' created the Data Source '{datasource}'")
|
|
@@ -1429,6 +1429,7 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1429
1429
|
"__loader__": ObjectDict(get_source=lambda name: self.code),
|
|
1430
1430
|
"max_threads": set_max_threads,
|
|
1431
1431
|
"tb_secret": set_tb_secret,
|
|
1432
|
+
"tb_var": set_tb_secret,
|
|
1432
1433
|
"backend_hint": set_backend_hint,
|
|
1433
1434
|
"cache_ttl": set_cache_ttl,
|
|
1434
1435
|
"activate": set_activate,
|
|
@@ -2116,6 +2117,8 @@ def render_sql_template(
|
|
|
2116
2117
|
("select * from table where str = 'test'", {}, ['pipeline'])
|
|
2117
2118
|
>>> render_sql_template("select * from table where str = {{tb_secret('test')}}", secrets = [ 'tb_secret_test' ])
|
|
2118
2119
|
('select * from table where str = {test: String}', {}, [])
|
|
2120
|
+
>>> render_sql_template("select * from table where str = {{tb_var('test')}}", secrets = [ 'tb_secret_test' ])
|
|
2121
|
+
('select * from table where str = {test: String}', {}, [])
|
|
2119
2122
|
>>> render_sql_template("select * from table where str = {{tb_secret('test')}}", variables = { 'test': '1234' })
|
|
2120
2123
|
Traceback (most recent call last):
|
|
2121
2124
|
...
|
|
@@ -2146,7 +2149,7 @@ def render_sql_template(
|
|
|
2146
2149
|
return Comment("error launched")
|
|
2147
2150
|
|
|
2148
2151
|
v: dict = {x["name"]: Placeholder(x["name"], x["line"]) for x in template_variables}
|
|
2149
|
-
is_tb_secret = any([s for s in template_variables if s["name"] == "tb_secret"])
|
|
2152
|
+
is_tb_secret = any([s for s in template_variables if s["name"] == "tb_secret" or s["name"] == "tb_var"])
|
|
2150
2153
|
|
|
2151
2154
|
if variables:
|
|
2152
2155
|
v.update(variables)
|
|
@@ -70,7 +70,9 @@ def sql_get_used_tables_cached(
|
|
|
70
70
|
table_functions: bool = True,
|
|
71
71
|
function_allow_list: Optional[FrozenSet[str]] = None,
|
|
72
72
|
) -> List[Tuple[str, str, str]]:
|
|
73
|
-
"""
|
|
73
|
+
"""More like: get used sql names
|
|
74
|
+
|
|
75
|
+
Returns a list of tuples: (database_or_namespace, table_name, table_func).
|
|
74
76
|
>>> sql_get_used_tables("SELECT 1 FROM the_table")
|
|
75
77
|
[('', 'the_table', '')]
|
|
76
78
|
>>> sql_get_used_tables("SELECT 1 FROM the_database.the_table")
|
|
@@ -104,6 +106,8 @@ def sql_get_used_tables_cached(
|
|
|
104
106
|
raise InvalidFunction(msg=msg) from e
|
|
105
107
|
elif "Unknown function tb_secret" in msg:
|
|
106
108
|
raise InvalidFunction(msg="Unknown function tb_secret. Usage: {{tb_secret('secret_name')}}") from e
|
|
109
|
+
elif "Unknown function tb_var" in msg:
|
|
110
|
+
raise InvalidFunction(msg="Unknown function tb_var. Usage: {{tb_var('var_name')}}") from e
|
|
107
111
|
raise
|
|
108
112
|
return [(default_database, sql, "")]
|
|
109
113
|
|
|
@@ -115,6 +119,10 @@ def sql_get_used_tables(
|
|
|
115
119
|
table_functions: bool = True,
|
|
116
120
|
function_allow_list: Optional[FrozenSet[str]] = None,
|
|
117
121
|
) -> List[Tuple[str, str, str]]:
|
|
122
|
+
"""More like: get used sql names
|
|
123
|
+
|
|
124
|
+
Returns a list of tuples: (database_or_namespace, table_name, table_func).
|
|
125
|
+
"""
|
|
118
126
|
hashable_list = frozenset() if function_allow_list is None else function_allow_list
|
|
119
127
|
|
|
120
128
|
return copy.copy(
|
|
@@ -16,7 +16,7 @@ from click import Context
|
|
|
16
16
|
import tinybird.context as context
|
|
17
17
|
from tinybird.client import DoesNotExistException, TinyB
|
|
18
18
|
from tinybird.config import DEFAULT_API_HOST, FeatureFlags
|
|
19
|
-
from tinybird.datafile import PipeTypes, folder_push, get_name_version, process_file, wait_job
|
|
19
|
+
from tinybird.datafile import PipeNodeTypes, PipeTypes, folder_push, get_name_version, process_file, wait_job
|
|
20
20
|
from tinybird.feedback_manager import FeedbackManager
|
|
21
21
|
from tinybird.tb_cli_modules.branch import warn_if_in_live
|
|
22
22
|
from tinybird.tb_cli_modules.cli import cli
|
|
@@ -348,6 +348,16 @@ async def pipe_unlink_output_node(
|
|
|
348
348
|
await client.pipe_remove_sink(pipe["name"], node_uid)
|
|
349
349
|
click.echo(FeedbackManager.success_pipe_unlinked(pipe=pipe["name"]))
|
|
350
350
|
|
|
351
|
+
if pipe["type"] == PipeTypes.STREAM:
|
|
352
|
+
click.echo(FeedbackManager.info_unlinking_stream_pipe(pipe=pipe["name"]))
|
|
353
|
+
node_uid = next((node["id"] for node in pipe["nodes"] if node["node_type"] == PipeNodeTypes.STREAM), None)
|
|
354
|
+
|
|
355
|
+
if not node_uid:
|
|
356
|
+
raise CLIPipeException(FeedbackManager.error_unlinking_pipe_not_linked(pipe=pipe_name_or_id))
|
|
357
|
+
else:
|
|
358
|
+
await client.pipe_remove_stream(pipe["name"], node_uid)
|
|
359
|
+
click.echo(FeedbackManager.success_pipe_unlinked(pipe=pipe["name"]))
|
|
360
|
+
|
|
351
361
|
except Exception as e:
|
|
352
362
|
raise CLIPipeException(FeedbackManager.error_exception(error=e))
|
|
353
363
|
|
|
@@ -204,19 +204,15 @@ import os.path
|
|
|
204
204
|
import posixpath
|
|
205
205
|
import re
|
|
206
206
|
import threading
|
|
207
|
+
from io import StringIO
|
|
207
208
|
from typing import Union
|
|
208
209
|
|
|
209
210
|
from tornado import escape
|
|
210
211
|
from tornado.log import app_log
|
|
211
|
-
from tornado.util import
|
|
212
|
+
from tornado.util import ObjectDict, exec_in, unicode_type
|
|
212
213
|
|
|
213
214
|
from .context import disable_template_security_validation
|
|
214
215
|
|
|
215
|
-
if PY3:
|
|
216
|
-
from io import StringIO
|
|
217
|
-
else:
|
|
218
|
-
from cStringIO import StringIO
|
|
219
|
-
|
|
220
216
|
_DEFAULT_AUTOESCAPE = "xhtml_escape"
|
|
221
217
|
_UNSET = object()
|
|
222
218
|
|
|
@@ -1051,6 +1047,7 @@ VALID_FUNCTION_NAMES = {
|
|
|
1051
1047
|
"sql_unescape",
|
|
1052
1048
|
"max_threads",
|
|
1053
1049
|
"tb_secret",
|
|
1050
|
+
"tb_var",
|
|
1054
1051
|
"Int",
|
|
1055
1052
|
"table",
|
|
1056
1053
|
"TABLE",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tinybird-cli
|
|
3
|
-
Version: 5.3.1.
|
|
3
|
+
Version: 5.3.1.dev5
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
7
7
|
Author-email: support@tinybird.co
|
|
8
|
-
Requires-Python: >=3.8, <3.
|
|
8
|
+
Requires-Python: >=3.8, <3.13
|
|
9
9
|
Description-Content-Type: text/x-rst
|
|
10
10
|
Provides-Extra: bigquery
|
|
11
11
|
Provides-Extra: snowflake
|
|
@@ -18,6 +18,21 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
18
18
|
Changelog
|
|
19
19
|
----------
|
|
20
20
|
|
|
21
|
+
5.3.1.dev5
|
|
22
|
+
**********
|
|
23
|
+
|
|
24
|
+
- `Fixed` Do not try to deploy shared Datafiles from the `vendor` folder on `tb deploy`
|
|
25
|
+
|
|
26
|
+
5.3.1.dev4
|
|
27
|
+
**********
|
|
28
|
+
|
|
29
|
+
- `Added` support to Python 3.12
|
|
30
|
+
|
|
31
|
+
5.3.1.dev3
|
|
32
|
+
**********
|
|
33
|
+
|
|
34
|
+
- `Added` support to Stream Pipes in `tb push` and `tb pull` commands. (Feature in development. It requires access)
|
|
35
|
+
|
|
21
36
|
5.3.1.dev2
|
|
22
37
|
**********
|
|
23
38
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/tinyunit/tinyunit.py
RENAMED
|
File without changes
|
{tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird/tb_cli_modules/workspace_members.py
RENAMED
|
File without changes
|
|
File without changes
|
{tinybird-cli-5.3.1.dev3 → tinybird-cli-5.3.1.dev5}/tinybird_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|