tinybird 4.6.22.dev0__tar.gz → 4.6.24.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.
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/PKG-INFO +11 -1
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/pyproject.toml +29 -25
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/client.py +0 -8
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/sql_template.py +54 -25
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/sql_template_fmt.py +2 -2
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/syncasync.py +0 -43
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/client.py +0 -8
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/common.py +3 -3
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/create.py +2 -4
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/pull.py +73 -3
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datasource.py +1 -1
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/deployment_common.py +4 -6
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/exceptions.py +0 -21
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/common.py +3 -3
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/datasource.py +1 -1
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tornado_template.py +38 -93
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/PKG-INFO +11 -1
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/setup.cfg +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/__cli__.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/check_pypi.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/config.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/context.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/datatypes.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/feedback_manager.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/git_settings.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/iterating/__init__.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/iterating/data_branch_modes.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/prompts.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/service_datasources.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/sql.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/sql_toolset.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/cli.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/config.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/build_common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/cli.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/config.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/connection_dynamodb.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/connection_kafka.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/connection_s3.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/format_connection.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/playground.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/infra.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/job.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/logs.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/project.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/token.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/utils/__init__.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird/utils/bools.py +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.6.22.dev0 → tinybird-4.6.24.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.
|
|
3
|
+
Version: 4.6.24.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -52,6 +52,16 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
54
|
|
|
55
|
+
4.6.22
|
|
56
|
+
********
|
|
57
|
+
|
|
58
|
+
- `Added` ``tb pull`` demotes sink and copy pipes that exceed the workspace's sink/copy pipe plan limit to plain pipes instead of failing, stripping their ``TYPE``/``EXPORT_*``/``TARGET_DATASOURCE``/``COPY_SCHEDULE`` settings and warning that the plan must be upgraded to restore them.
|
|
59
|
+
|
|
60
|
+
4.6.21
|
|
61
|
+
********
|
|
62
|
+
|
|
63
|
+
- `Fixed` ``tb deployment discard`` now discards the deployment that is not live, instead of assuming the live deployment is listed first. Previously, if removing the old deployment failed after a promotion, the command refused to discard it.
|
|
64
|
+
|
|
55
65
|
4.6.20
|
|
56
66
|
********
|
|
57
67
|
|
|
@@ -18,34 +18,35 @@ authors = [
|
|
|
18
18
|
dependencies = [
|
|
19
19
|
"GitPython==3.1.44",
|
|
20
20
|
"Markdown==3.5.1",
|
|
21
|
-
"aioboto3
|
|
21
|
+
"aioboto3~=15.0",
|
|
22
22
|
"aiofiles==24.1.0",
|
|
23
|
-
"aiohttp
|
|
24
|
-
"anthropic
|
|
23
|
+
"aiohttp~=3.11",
|
|
24
|
+
"anthropic~=1.9",
|
|
25
|
+
"async-lru==2.3.0",
|
|
25
26
|
"aws-msk-iam-sasl-signer-python==1.0.2",
|
|
26
27
|
"cachetools==5.5.0",
|
|
27
28
|
"cffi==1.17.1",
|
|
28
29
|
"chardet==4.0.0",
|
|
29
30
|
"ciso8601==2.2.0",
|
|
30
|
-
"click
|
|
31
|
+
"click~=8.5",
|
|
31
32
|
"clickhouse-cityhash==1.0.2.5",
|
|
32
33
|
"clickhouse-driver==0.2.9",
|
|
33
34
|
"confluent-kafka[avro,json,schemaregistry]==2.12.2",
|
|
34
35
|
"contextvars==2.4",
|
|
35
36
|
"cramjam==2.11.0",
|
|
36
37
|
"croniter==6.2.2",
|
|
37
|
-
"cryptography
|
|
38
|
+
"cryptography~=38.0",
|
|
38
39
|
"datasketch==1.6.5",
|
|
39
40
|
"dnspython==2.8.0",
|
|
40
41
|
"docker==7.1.0",
|
|
41
42
|
"fastavro==1.12.2",
|
|
42
43
|
"fastmcp==2.12.2",
|
|
43
|
-
"google-cloud-aiplatform
|
|
44
|
+
"google-cloud-aiplatform~=1.148",
|
|
44
45
|
"google-cloud-compute==1.48.0",
|
|
45
46
|
"google-cloud-scheduler==2.20.0",
|
|
46
47
|
"google-cloud-secret-manager==2.29.0",
|
|
47
|
-
"google-cloud-storage
|
|
48
|
-
"google_api_core
|
|
48
|
+
"google-cloud-storage~=3.4",
|
|
49
|
+
"google_api_core~=2.25",
|
|
49
50
|
"googleapis_common_protos==1.66.0",
|
|
50
51
|
"grpcio_status==1.67.1",
|
|
51
52
|
"humanfriendly==10.0",
|
|
@@ -68,7 +69,7 @@ dependencies = [
|
|
|
68
69
|
"opentelemetry-sdk==1.38.0",
|
|
69
70
|
"orb-billing==2.17.0",
|
|
70
71
|
"orjson==3.11.5",
|
|
71
|
-
"packaging
|
|
72
|
+
"packaging~=26.3",
|
|
72
73
|
"passlib==1.7.1",
|
|
73
74
|
"posthog==7.28.0",
|
|
74
75
|
"pre-commit==4.6.2",
|
|
@@ -82,10 +83,10 @@ dependencies = [
|
|
|
82
83
|
"py-spy==0.4.2",
|
|
83
84
|
"pyarrow==23.0.1",
|
|
84
85
|
"pycurl==7.45.7",
|
|
85
|
-
"pydantic-ai-slim[anthropic]
|
|
86
|
-
"pydantic-ai-slim[google]
|
|
87
|
-
"pydantic-ai-slim[retries]
|
|
88
|
-
"pydantic
|
|
86
|
+
"pydantic-ai-slim[anthropic]~=2.0",
|
|
87
|
+
"pydantic-ai-slim[google]~=2.0",
|
|
88
|
+
"pydantic-ai-slim[retries]~=2.0",
|
|
89
|
+
"pydantic~=2.12",
|
|
89
90
|
"pyjwt[crypto]==2.9.0",
|
|
90
91
|
"pympler==1.1",
|
|
91
92
|
"pynacl==1.5.0",
|
|
@@ -93,10 +94,10 @@ dependencies = [
|
|
|
93
94
|
"python-dateutil==2.9.0.post0",
|
|
94
95
|
"python-dotenv==1.1.0",
|
|
95
96
|
"python-ulid==2.7.0",
|
|
96
|
-
"pyyaml
|
|
97
|
+
"pyyaml~=6.0",
|
|
97
98
|
"redis[hiredis]==5.3.1",
|
|
98
99
|
"requests==2.32.4",
|
|
99
|
-
"sentry-sdk==2.69.
|
|
100
|
+
"sentry-sdk==2.69.2",
|
|
100
101
|
"setproctitle==1.3.3",
|
|
101
102
|
"shandy-sqlfmt==0.11.1",
|
|
102
103
|
"shandy-sqlfmt[jinjafmt]==0.11.1",
|
|
@@ -107,7 +108,7 @@ dependencies = [
|
|
|
107
108
|
"tabulate==0.8.10",
|
|
108
109
|
"thefuzz==0.22.1",
|
|
109
110
|
"tinybird-python-sdk[ai]==0.3.7",
|
|
110
|
-
"tinybird-toolset==2.6.
|
|
111
|
+
"tinybird-toolset==2.6.6",
|
|
111
112
|
"toposort==1.10",
|
|
112
113
|
"tornado==6.5.5",
|
|
113
114
|
"urllib3==1.26.20",
|
|
@@ -124,9 +125,9 @@ deploy = [
|
|
|
124
125
|
"GitPython==3.1.44",
|
|
125
126
|
"ansible==8.5.0",
|
|
126
127
|
"ara==1.6.1",
|
|
127
|
-
"boto3
|
|
128
|
+
"boto3~=1.40",
|
|
128
129
|
"fabric==3.2.2",
|
|
129
|
-
"google-auth
|
|
130
|
+
"google-auth~=2.47",
|
|
130
131
|
"jsonnet",
|
|
131
132
|
"prettytable==3.8.0",
|
|
132
133
|
"requests==2.32.4",
|
|
@@ -141,7 +142,7 @@ devtools = [
|
|
|
141
142
|
]
|
|
142
143
|
doc = [
|
|
143
144
|
"Pallets-Sphinx-Themes==2.3.0",
|
|
144
|
-
"pyOpenSSL
|
|
145
|
+
"pyOpenSSL~=23.2",
|
|
145
146
|
"sphinx-autobuild==2024.2.4",
|
|
146
147
|
"sphinx-sitemap",
|
|
147
148
|
"sphinx==7.3.7",
|
|
@@ -149,15 +150,15 @@ doc = [
|
|
|
149
150
|
"sphinxcontrib-jquery==4.1",
|
|
150
151
|
]
|
|
151
152
|
lint = [
|
|
152
|
-
"botocore-stubs
|
|
153
|
+
"botocore-stubs~=1.40",
|
|
153
154
|
"flake8~=7.3",
|
|
154
155
|
"flake8-async~=26.8",
|
|
155
156
|
"mypy==2.3.1",
|
|
156
|
-
"ruff==0.16.
|
|
157
|
+
"ruff==0.16.9",
|
|
157
158
|
"types-Markdown",
|
|
158
159
|
"types-PyYAML",
|
|
159
160
|
"types-aiofiles==24.1.0.20241221",
|
|
160
|
-
"types-boto3-lite
|
|
161
|
+
"types-boto3-lite~=1.40",
|
|
161
162
|
"types-cachetools",
|
|
162
163
|
"types-chardet",
|
|
163
164
|
"types-paramiko",
|
|
@@ -171,18 +172,19 @@ lint = [
|
|
|
171
172
|
test = [
|
|
172
173
|
"coverage==7.10.6",
|
|
173
174
|
"freezegun==1.5.5",
|
|
174
|
-
"google-auth
|
|
175
|
+
"google-auth~=2.47",
|
|
175
176
|
"gsutil==4.58",
|
|
177
|
+
"httpx2~=2.13",
|
|
176
178
|
"hypothesis==6.156.1",
|
|
177
179
|
"oauth2client==3.0.0",
|
|
178
180
|
"py==1.11.0",
|
|
179
|
-
"pytest-asyncio
|
|
181
|
+
"pytest-asyncio~=1.4",
|
|
180
182
|
"pytest-cov==4.1.0",
|
|
181
183
|
"pytest-env==1.1.3",
|
|
182
184
|
"pytest-flakefinder==1.1.0",
|
|
183
185
|
"pytest-timeout==2.3.1",
|
|
184
186
|
"pytest-xdist==3.6.1",
|
|
185
|
-
"pytest
|
|
187
|
+
"pytest~=8.1",
|
|
186
188
|
"rangehttpserver==1.4.0",
|
|
187
189
|
"yappi==1.7.6",
|
|
188
190
|
]
|
|
@@ -204,6 +206,8 @@ colibri = "tinybird.colibri.cli:cli"
|
|
|
204
206
|
members = [
|
|
205
207
|
"chbackups",
|
|
206
208
|
"data_connector",
|
|
209
|
+
"gatherer",
|
|
210
|
+
"tinybird_orchestrator",
|
|
207
211
|
]
|
|
208
212
|
|
|
209
213
|
[tool.setuptools]
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import ast
|
|
2
|
-
import builtins
|
|
3
2
|
import linecache
|
|
4
3
|
import logging
|
|
5
4
|
import re
|
|
@@ -1336,8 +1335,10 @@ sqlescape_for_string_expression = sqlescape_generator(
|
|
|
1336
1335
|
)
|
|
1337
1336
|
|
|
1338
1337
|
|
|
1339
|
-
def escape_single_quote_str(s):
|
|
1340
|
-
|
|
1338
|
+
def escape_single_quote_str(s: str) -> str:
|
|
1339
|
+
# ClickHouse string literals treat backslash as an escape char, so it must be doubled too:
|
|
1340
|
+
# otherwise a trailing backslash escapes the closing quote and the following input becomes SQL
|
|
1341
|
+
return "'" + s.replace("\\", "\\\\").replace("'", "''") + "'"
|
|
1341
1342
|
|
|
1342
1343
|
|
|
1343
1344
|
def expression_wrapper(x, name, escape_arrays: bool = False):
|
|
@@ -1385,16 +1386,16 @@ _namespace = {
|
|
|
1385
1386
|
"close": None,
|
|
1386
1387
|
"print": None,
|
|
1387
1388
|
"input": None,
|
|
1388
|
-
# Keep customer parameters named `type`/`dir` usable without restoring the unsafe builtins.
|
|
1389
|
-
"type": None,
|
|
1390
|
-
"dir": None,
|
|
1391
1389
|
}
|
|
1392
1390
|
|
|
1393
1391
|
|
|
1394
|
-
|
|
1392
|
+
# Built from the builtins templates can actually resolve: names missing from SAFE_BUILTINS (`type`, `dir`,
|
|
1393
|
+
# `property`, `object`, ...) can only be template parameters, so they must be discovered as such to get a
|
|
1394
|
+
# value (None or a test-mode placeholder) instead of raising NameError.
|
|
1395
|
+
reserved_vars = {"_tt_tmp", "_tt_append", "isinstance", "str", "error", "custom_error", *SAFE_BUILTINS}
|
|
1395
1396
|
for p in DEFAULT_PARAM_NAMES: # we handle these in an specific manner
|
|
1396
1397
|
reserved_vars.discard(p) # `format` is part of builtins
|
|
1397
|
-
# Allow 'id'
|
|
1398
|
+
# Allow 'id' as a template parameter name despite being a builtin - https://gitlab.com/tinybird/analytics/-/issues/19119
|
|
1398
1399
|
reserved_vars.discard("id")
|
|
1399
1400
|
error_vars = ["error", "custom_error"]
|
|
1400
1401
|
|
|
@@ -1471,8 +1472,7 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1471
1472
|
return Expression(f"-- disable {feature}\n")
|
|
1472
1473
|
|
|
1473
1474
|
namespace.update(_namespace)
|
|
1474
|
-
#
|
|
1475
|
-
# We need to do the override here because if we modify the _namespace, we would filter out parameters from the users
|
|
1475
|
+
# Default it here, not in _namespace, so it stays visible to variable extraction.
|
|
1476
1476
|
namespace.update({"id": None})
|
|
1477
1477
|
namespace.update(kwargs)
|
|
1478
1478
|
namespace.update(
|
|
@@ -1822,7 +1822,7 @@ def get_var_names(t: Template):
|
|
|
1822
1822
|
>>> [v['name'] for v in get_var_names(Template("{% for name in secret_names %}{{tb_secret(name)}}{% end %}"))]
|
|
1823
1823
|
['secret_names', 'name', 'tb_secret', 'name']
|
|
1824
1824
|
|
|
1825
|
-
Type casting with date function in elif chain
|
|
1825
|
+
Type casting with date function in elif chain:
|
|
1826
1826
|
>>> t = Template("{% if kind == 'int' %}{{Int32(val, 0)}}{% elif kind == 'date' %}{{DateTime(val)}}{% elif kind == 'diff' %}{{date_diff_in_days(val, now)}}{% end %}")
|
|
1827
1827
|
>>> [v['name'] for v in get_var_names(t)]
|
|
1828
1828
|
['kind', 'Int32', 'val', 'kind', 'DateTime', 'val', 'kind', 'date_diff_in_days', 'val', 'now']
|
|
@@ -2374,7 +2374,24 @@ def wrap_vars(t, escape_arrays: bool = False):
|
|
|
2374
2374
|
return var
|
|
2375
2375
|
|
|
2376
2376
|
|
|
2377
|
-
def
|
|
2377
|
+
def _constant_table_name(node: ast.expr) -> Optional[str]:
|
|
2378
|
+
"""Value of a constant table() argument: a literal or a concatenation of string literals."""
|
|
2379
|
+
if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
|
|
2380
|
+
return str(node.value)
|
|
2381
|
+
return _string_literal(node)
|
|
2382
|
+
|
|
2383
|
+
|
|
2384
|
+
def _string_literal(node: ast.expr) -> Optional[str]:
|
|
2385
|
+
if isinstance(node, ast.Constant) and isinstance(node.value, str):
|
|
2386
|
+
return node.value
|
|
2387
|
+
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.Add):
|
|
2388
|
+
left, right = _string_literal(node.left), _string_literal(node.right)
|
|
2389
|
+
if left is not None and right is not None:
|
|
2390
|
+
return left + right
|
|
2391
|
+
return None
|
|
2392
|
+
|
|
2393
|
+
|
|
2394
|
+
def get_used_tables_in_template(sql: str) -> List[str]:
|
|
2378
2395
|
"""
|
|
2379
2396
|
>>> get_used_tables_in_template("select * from {{table('test')}}")
|
|
2380
2397
|
['test']
|
|
@@ -2388,30 +2405,42 @@ def get_used_tables_in_template(sql):
|
|
|
2388
2405
|
[]
|
|
2389
2406
|
>>> get_used_tables_in_template("select * from {{table('my.test')}}, {{table('another.one')}}")
|
|
2390
2407
|
['my.test', 'another.one']
|
|
2408
|
+
|
|
2409
|
+
Only constant table names can be known without rendering, so anything else is skipped
|
|
2410
|
+
>>> get_used_tables_in_template("select * from {{table(tbl)}}, {{TABLE('b')}}, {{table('my.' + 'c')}}")
|
|
2411
|
+
['b', 'my.c']
|
|
2391
2412
|
"""
|
|
2413
|
+
return list(_get_used_tables_in_template_cached(sql))
|
|
2414
|
+
|
|
2415
|
+
|
|
2416
|
+
# Building the Template dominates the cost and the result only depends on the SQL, which deployments and
|
|
2417
|
+
# /v0/sql pipelines scan repeatedly
|
|
2418
|
+
@lru_cache(maxsize=2**10)
|
|
2419
|
+
def _get_used_tables_in_template_cached(sql: str) -> Tuple[str, ...]:
|
|
2392
2420
|
try:
|
|
2393
2421
|
t = Template(sql)
|
|
2394
2422
|
|
|
2395
2423
|
def _n(chunks, tables):
|
|
2396
2424
|
for x in chunks:
|
|
2397
2425
|
if type(x).__name__ == "_Expression":
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2426
|
+
# Read the names from the AST instead of executing the expression: this runs outside
|
|
2427
|
+
# generate(), without the restricted builtins, on every pipe, query and deployment.
|
|
2428
|
+
for node in ast.walk(ast.parse(x.expression)):
|
|
2429
|
+
if (
|
|
2430
|
+
isinstance(node, ast.Call)
|
|
2431
|
+
and isinstance(node.func, ast.Name)
|
|
2432
|
+
and node.func.id in ("table", "TABLE")
|
|
2433
|
+
and node.args
|
|
2434
|
+
):
|
|
2435
|
+
name = _constant_table_name(node.args[0])
|
|
2436
|
+
if name is not None:
|
|
2437
|
+
tables.append(name)
|
|
2409
2438
|
elif type(x).__name__ == "_ControlBlock":
|
|
2410
2439
|
_n(x.body.chunks, tables)
|
|
2411
2440
|
|
|
2412
|
-
tables = []
|
|
2441
|
+
tables: List[str] = []
|
|
2413
2442
|
_n(t.file.body.chunks, tables)
|
|
2414
|
-
return tables
|
|
2443
|
+
return tuple(tables)
|
|
2415
2444
|
except SecurityException as e:
|
|
2416
2445
|
raise SQLTemplateException(e)
|
|
2417
2446
|
|
|
@@ -214,8 +214,8 @@ class TinybirdDialect(ClickHouse):
|
|
|
214
214
|
],
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
for section in override_rules:
|
|
218
|
-
for rule in
|
|
217
|
+
for section, rules in override_rules.items():
|
|
218
|
+
for rule in rules:
|
|
219
219
|
for rr in self.RULES[section]:
|
|
220
220
|
if rr.name == rule.name:
|
|
221
221
|
self.RULES[section].remove(rr)
|
|
@@ -260,49 +260,6 @@ def _iscoroutinefunction_or_partial(func: Any) -> bool:
|
|
|
260
260
|
return asyncio.iscoroutinefunction(func)
|
|
261
261
|
|
|
262
262
|
|
|
263
|
-
class ThreadSensitiveContext:
|
|
264
|
-
"""Async context manager to manage context for thread sensitive mode
|
|
265
|
-
This context manager controls which thread pool executor is used when in
|
|
266
|
-
thread sensitive mode. By default, a single thread pool executor is shared
|
|
267
|
-
within a process.
|
|
268
|
-
In Python 3.7+, the ThreadSensitiveContext() context manager may be used to
|
|
269
|
-
specify a thread pool per context.
|
|
270
|
-
In Python 3.6, usage of this context manager has no effect.
|
|
271
|
-
This context manager is re-entrant, so only the outer-most call to
|
|
272
|
-
ThreadSensitiveContext will set the context.
|
|
273
|
-
"""
|
|
274
|
-
|
|
275
|
-
def __init__(self):
|
|
276
|
-
self.token = None
|
|
277
|
-
|
|
278
|
-
if contextvars:
|
|
279
|
-
|
|
280
|
-
async def __aenter__(self):
|
|
281
|
-
try:
|
|
282
|
-
SyncToAsync.thread_sensitive_context.get()
|
|
283
|
-
except LookupError:
|
|
284
|
-
self.token = SyncToAsync.thread_sensitive_context.set(self)
|
|
285
|
-
|
|
286
|
-
return self
|
|
287
|
-
|
|
288
|
-
async def __aexit__(self, exc, value, tb):
|
|
289
|
-
if not self.token:
|
|
290
|
-
return
|
|
291
|
-
|
|
292
|
-
executor = SyncToAsync.context_to_thread_executor.pop(self, None)
|
|
293
|
-
if executor:
|
|
294
|
-
executor.shutdown()
|
|
295
|
-
SyncToAsync.thread_sensitive_context.reset(self.token)
|
|
296
|
-
|
|
297
|
-
else:
|
|
298
|
-
|
|
299
|
-
async def __aenter__(self):
|
|
300
|
-
return self
|
|
301
|
-
|
|
302
|
-
async def __aexit__(self, exc, value, tb):
|
|
303
|
-
pass
|
|
304
|
-
|
|
305
|
-
|
|
306
263
|
class AsyncToSync:
|
|
307
264
|
"""
|
|
308
265
|
Utility class which turns an awaitable that only works on the thread with
|
|
@@ -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.24.dev0'
|
|
8
|
+
__revision__ = '5269fe22'
|
|
@@ -1277,11 +1277,11 @@ class ConnectionReplacements:
|
|
|
1277
1277
|
"""Maps prompt parameters to API parameters."""
|
|
1278
1278
|
|
|
1279
1279
|
api_params = {}
|
|
1280
|
-
for key in params.
|
|
1280
|
+
for key, value in params.items():
|
|
1281
1281
|
try:
|
|
1282
|
-
api_params[ConnectionReplacements._PARAMS_REPLACEMENTS[service][key]] =
|
|
1282
|
+
api_params[ConnectionReplacements._PARAMS_REPLACEMENTS[service][key]] = value
|
|
1283
1283
|
except KeyError:
|
|
1284
|
-
api_params[key] =
|
|
1284
|
+
api_params[key] = value
|
|
1285
1285
|
|
|
1286
1286
|
api_params["service"] = service
|
|
1287
1287
|
return api_params
|
|
@@ -215,14 +215,12 @@ def create_project_structure(folder: str):
|
|
|
215
215
|
"connections →": "Connect to and ingest data from popular sources: Kafka, S3 or GCS.",
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
for x in PROJECT_PATHS_DESCRIPTIONS.
|
|
218
|
+
for x, description in PROJECT_PATHS_DESCRIPTIONS.items():
|
|
219
219
|
try:
|
|
220
220
|
path = x.split("→")[0].strip()
|
|
221
221
|
f = folder_path / path
|
|
222
222
|
f.mkdir()
|
|
223
|
-
click.echo(
|
|
224
|
-
FeedbackManager.info(message=f"./{x} ") + FeedbackManager.gray(message=PROJECT_PATHS_DESCRIPTIONS[x])
|
|
225
|
-
)
|
|
223
|
+
click.echo(FeedbackManager.info(message=f"./{x} ") + FeedbackManager.gray(message=description))
|
|
226
224
|
except FileExistsError:
|
|
227
225
|
pass
|
|
228
226
|
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
from datetime import datetime
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from typing import Any, Optional
|
|
3
4
|
|
|
4
5
|
import click
|
|
5
6
|
|
|
7
|
+
from tinybird.datafile.common import PipeNodeTypes
|
|
8
|
+
from tinybird.datafile.parse_pipe import parse_pipe
|
|
6
9
|
from tinybird.tb.client import AuthNoTokenException, TinyB
|
|
7
10
|
from tinybird.tb.modules.datafile.format_datasource import format_datasource
|
|
8
11
|
from tinybird.tb.modules.datafile.format_pipe import format_pipe
|
|
@@ -10,6 +13,52 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
|
10
13
|
|
|
11
14
|
PULL_EXISTING_FILE_MAX_DEPTH = 5
|
|
12
15
|
|
|
16
|
+
DEMOTABLE_NODE_TYPES = {
|
|
17
|
+
PipeNodeTypes.DATA_SINK: ("sink_pipes", "Sink"),
|
|
18
|
+
PipeNodeTypes.COPY: ("copy_pipes", "Copy"),
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _parse_created_at(value: Any) -> datetime:
|
|
23
|
+
try:
|
|
24
|
+
return datetime.fromisoformat(str(value))
|
|
25
|
+
except ValueError:
|
|
26
|
+
return datetime.min
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def pipes_over_node_type_limit(pipes: list[dict[str, Any]], node_type: str, limit: Optional[int]) -> set[str]:
|
|
30
|
+
if limit is None:
|
|
31
|
+
return set()
|
|
32
|
+
|
|
33
|
+
matching_pipes = [p for p in pipes if p.get("type") == node_type]
|
|
34
|
+
if len(matching_pipes) <= limit:
|
|
35
|
+
return set()
|
|
36
|
+
|
|
37
|
+
matching_pipes.sort(key=lambda p: _parse_created_at(p.get("created_at")))
|
|
38
|
+
return {p["name"] for p in matching_pipes[limit:]}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def pipes_over_plan_limits(pipes: list[dict[str, Any]], limits: dict[str, Any]) -> dict[str, str]:
|
|
42
|
+
demoted: dict[str, str] = {}
|
|
43
|
+
for node_type, (limits_key, _label) in DEMOTABLE_NODE_TYPES.items():
|
|
44
|
+
limit = limits.get(limits_key, {}).get("max")
|
|
45
|
+
for name in pipes_over_node_type_limit(pipes, node_type, limit):
|
|
46
|
+
demoted[name] = node_type
|
|
47
|
+
return demoted
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def demote_pipe_content(name: str, content: str, node_type: str) -> str:
|
|
51
|
+
datafile = parse_pipe(name, content=content, replace_includes=False).datafile
|
|
52
|
+
demoted = False
|
|
53
|
+
for node in datafile.nodes:
|
|
54
|
+
if (node.get("type") or "").lower() == node_type:
|
|
55
|
+
node.pop("type", None)
|
|
56
|
+
demoted = True
|
|
57
|
+
|
|
58
|
+
if not demoted:
|
|
59
|
+
return content
|
|
60
|
+
return format_pipe(name, datafile=datafile)
|
|
61
|
+
|
|
13
62
|
|
|
14
63
|
def folder_pull(
|
|
15
64
|
client: TinyB,
|
|
@@ -61,6 +110,7 @@ def folder_pull(
|
|
|
61
110
|
get_resource_function: str,
|
|
62
111
|
progress_bar: bool = False,
|
|
63
112
|
fmt: bool = False,
|
|
113
|
+
demoted_pipe_types: Optional[dict[str, str]] = None,
|
|
64
114
|
) -> list[Path]:
|
|
65
115
|
def write_resource(k: dict[str, Any]) -> Optional[Path]:
|
|
66
116
|
name = f"{k['name']}.{extension}"
|
|
@@ -73,8 +123,19 @@ def folder_pull(
|
|
|
73
123
|
else:
|
|
74
124
|
resource = getattr(client, get_resource_function)(k["name"])
|
|
75
125
|
resource_to_write = resource
|
|
76
|
-
|
|
77
|
-
|
|
126
|
+
resource_type = k.get("type")
|
|
127
|
+
|
|
128
|
+
demoted_node_type = demoted_pipe_types.get(k["name"]) if demoted_pipe_types else None
|
|
129
|
+
if demoted_node_type:
|
|
130
|
+
resource_to_write = demote_pipe_content(name, resource, demoted_node_type)
|
|
131
|
+
resource_type = None
|
|
132
|
+
label = DEMOTABLE_NODE_TYPES[demoted_node_type][1]
|
|
133
|
+
warnings.append(
|
|
134
|
+
f"{label} pipe '{k['name']}' exceeds the {demoted_node_type} pipe limit of your current "
|
|
135
|
+
f"plan and was pulled as a plain pipe without its {demoted_node_type} configuration. "
|
|
136
|
+
"Upgrade your plan and reconfigure it to restore it."
|
|
137
|
+
)
|
|
138
|
+
elif fmt:
|
|
78
139
|
if extension == "datasource":
|
|
79
140
|
resource_to_write = format_datasource(name, content=resource)
|
|
80
141
|
elif extension == "pipe":
|
|
@@ -85,7 +146,7 @@ def folder_pull(
|
|
|
85
146
|
dest_folder = Path(folder) / "vendor" / k["name"].split(".", 1)[0]
|
|
86
147
|
name = f"{k['name'].split('.', 1)[1]}.{extension}"
|
|
87
148
|
|
|
88
|
-
file_folder = get_file_folder(extension,
|
|
149
|
+
file_folder = get_file_folder(extension, resource_type)
|
|
89
150
|
f = Path(dest_folder) / file_folder if file_folder is not None else Path(dest_folder)
|
|
90
151
|
|
|
91
152
|
existing_file = find_existing_resource_file(Path(dest_folder), name)
|
|
@@ -128,6 +189,14 @@ def folder_pull(
|
|
|
128
189
|
pipes = client.pipes()
|
|
129
190
|
connections = client.connections()
|
|
130
191
|
|
|
192
|
+
demoted_pipe_types: dict[str, str] = {}
|
|
193
|
+
if not only_vendored:
|
|
194
|
+
try:
|
|
195
|
+
limits = client.workspace_info().get("limits", {})
|
|
196
|
+
except Exception:
|
|
197
|
+
limits = {}
|
|
198
|
+
demoted_pipe_types = pipes_over_plan_limits(pipes, limits)
|
|
199
|
+
|
|
131
200
|
if only_vendored:
|
|
132
201
|
written_files = write_files(
|
|
133
202
|
resources=[ds for ds in datasources if "shared_from" in ds],
|
|
@@ -154,6 +223,7 @@ def folder_pull(
|
|
|
154
223
|
get_resource_function="pipe_file",
|
|
155
224
|
progress_bar=progress_bar,
|
|
156
225
|
fmt=fmt,
|
|
226
|
+
demoted_pipe_types=demoted_pipe_types,
|
|
157
227
|
)
|
|
158
228
|
)
|
|
159
229
|
written_files.extend(
|
|
@@ -677,7 +677,7 @@ def datasource_start(ctx: Context, datasource_name: str) -> None:
|
|
|
677
677
|
|
|
678
678
|
@datasource.command(name="delete")
|
|
679
679
|
@click.argument("datasource_name")
|
|
680
|
-
@click.option("--sql-condition",
|
|
680
|
+
@click.option("--sql-condition", help="SQL WHERE condition to remove rows", hidden=True, required=True)
|
|
681
681
|
@click.option("--yes", is_flag=True, default=False, help="Do not ask for confirmation")
|
|
682
682
|
@click.option(
|
|
683
683
|
"--wait/--no-wait",
|
|
@@ -335,13 +335,12 @@ def discard_deployment(host: Optional[str], headers: dict, wait: bool, request_f
|
|
|
335
335
|
click.echo(FeedbackManager.error(message="Only one deployment found. Cannot discard the only deployment."))
|
|
336
336
|
return
|
|
337
337
|
|
|
338
|
-
|
|
338
|
+
live_deployment = next((deployment for deployment in deployments if deployment.get("live")), deployments[0])
|
|
339
|
+
deployment_to_discard = next(deployment for deployment in deployments if deployment is not live_deployment)
|
|
339
340
|
|
|
340
|
-
|
|
341
|
-
# staging and live, but the current CLI commands don't allow getting in that state
|
|
342
|
-
if current_deployment.get("status") != "data_ready":
|
|
341
|
+
if live_deployment.get("status") != "data_ready":
|
|
343
342
|
click.echo(FeedbackManager.error(message="Previous deployment is not ready"))
|
|
344
|
-
deploy_errors =
|
|
343
|
+
deploy_errors = live_deployment.get("errors", [])
|
|
345
344
|
for deploy_error in deploy_errors:
|
|
346
345
|
click.echo(FeedbackManager.error(message=f"* {deploy_error}"))
|
|
347
346
|
return
|
|
@@ -359,7 +358,6 @@ def discard_deployment(host: Optional[str], headers: dict, wait: bool, request_f
|
|
|
359
358
|
click.echo(FeedbackManager.error(message=result.get("error")))
|
|
360
359
|
sys_exit("deployment_error", result.get("error", "Unknown error"))
|
|
361
360
|
|
|
362
|
-
deployment_to_discard = deployments[1]
|
|
363
361
|
click.echo(FeedbackManager.success(message="Discard process successfully started"))
|
|
364
362
|
|
|
365
363
|
if wait:
|
|
@@ -92,20 +92,6 @@ class CLITokenException(CLIException):
|
|
|
92
92
|
super().__init__(message, "token_error", **kw_telemetry_event_data)
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
class CLIBuildException(CLIException):
|
|
96
|
-
"""Exceptions generated by the build commands"""
|
|
97
|
-
|
|
98
|
-
def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
|
|
99
|
-
super().__init__(message, "build_error", **kw_telemetry_event_data)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
class CLIDeploymentException(CLIException):
|
|
103
|
-
"""Exceptions generated by the deployment commands"""
|
|
104
|
-
|
|
105
|
-
def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
|
|
106
|
-
super().__init__(message, "deployment_error", **kw_telemetry_event_data)
|
|
107
|
-
|
|
108
|
-
|
|
109
95
|
class CLITestException(CLIException):
|
|
110
96
|
"""Exceptions generated by the test commands"""
|
|
111
97
|
|
|
@@ -127,13 +113,6 @@ class CLIMockException(CLIException):
|
|
|
127
113
|
super().__init__(message, "mock_error", **kw_telemetry_event_data)
|
|
128
114
|
|
|
129
115
|
|
|
130
|
-
class CLIAgentException(CLIException):
|
|
131
|
-
"""Exceptions generated by the agent commands"""
|
|
132
|
-
|
|
133
|
-
def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
|
|
134
|
-
super().__init__(message, "agent_error", **kw_telemetry_event_data)
|
|
135
|
-
|
|
136
|
-
|
|
137
116
|
class CLILoginException(CLIException):
|
|
138
117
|
"""Exceptions generated by the login commands"""
|
|
139
118
|
|