tinybird 4.6.23.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.23.dev0 → tinybird-4.6.24.dev0}/PKG-INFO +6 -1
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/pyproject.toml +28 -25
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/client.py +0 -8
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/sql_template.py +55 -24
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/sql_template_fmt.py +2 -2
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/syncasync.py +0 -43
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/client.py +0 -8
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/common.py +3 -3
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/create.py +2 -4
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/pull.py +73 -3
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datasource.py +1 -1
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/exceptions.py +0 -21
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/common.py +3 -3
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/datasource.py +1 -1
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tornado_template.py +38 -93
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/PKG-INFO +6 -1
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/setup.cfg +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/__cli__.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/check_pypi.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/config.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/context.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/datatypes.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/feedback_manager.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/git_settings.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/iterating/__init__.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/iterating/data_branch_modes.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/prompts.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/service_datasources.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/sql.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/sql_toolset.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/cli.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/config.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/build_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/cli.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/config.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/connection_dynamodb.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/connection_kafka.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/connection_s3.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/format_connection.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/datafile/playground.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/deployment_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/infra.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/job.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/logs.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/project.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/token.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/utils/__init__.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird/utils/bools.py +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.6.23.dev0 → tinybird-4.6.24.dev0}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.6.23.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,11 @@ 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
|
+
|
|
55
60
|
4.6.21
|
|
56
61
|
********
|
|
57
62
|
|
|
@@ -18,35 +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
25
|
"async-lru==2.3.0",
|
|
26
26
|
"aws-msk-iam-sasl-signer-python==1.0.2",
|
|
27
27
|
"cachetools==5.5.0",
|
|
28
28
|
"cffi==1.17.1",
|
|
29
29
|
"chardet==4.0.0",
|
|
30
30
|
"ciso8601==2.2.0",
|
|
31
|
-
"click
|
|
31
|
+
"click~=8.5",
|
|
32
32
|
"clickhouse-cityhash==1.0.2.5",
|
|
33
33
|
"clickhouse-driver==0.2.9",
|
|
34
34
|
"confluent-kafka[avro,json,schemaregistry]==2.12.2",
|
|
35
35
|
"contextvars==2.4",
|
|
36
36
|
"cramjam==2.11.0",
|
|
37
37
|
"croniter==6.2.2",
|
|
38
|
-
"cryptography
|
|
38
|
+
"cryptography~=38.0",
|
|
39
39
|
"datasketch==1.6.5",
|
|
40
40
|
"dnspython==2.8.0",
|
|
41
41
|
"docker==7.1.0",
|
|
42
42
|
"fastavro==1.12.2",
|
|
43
43
|
"fastmcp==2.12.2",
|
|
44
|
-
"google-cloud-aiplatform
|
|
44
|
+
"google-cloud-aiplatform~=1.148",
|
|
45
45
|
"google-cloud-compute==1.48.0",
|
|
46
46
|
"google-cloud-scheduler==2.20.0",
|
|
47
47
|
"google-cloud-secret-manager==2.29.0",
|
|
48
|
-
"google-cloud-storage
|
|
49
|
-
"google_api_core
|
|
48
|
+
"google-cloud-storage~=3.4",
|
|
49
|
+
"google_api_core~=2.25",
|
|
50
50
|
"googleapis_common_protos==1.66.0",
|
|
51
51
|
"grpcio_status==1.67.1",
|
|
52
52
|
"humanfriendly==10.0",
|
|
@@ -69,7 +69,7 @@ dependencies = [
|
|
|
69
69
|
"opentelemetry-sdk==1.38.0",
|
|
70
70
|
"orb-billing==2.17.0",
|
|
71
71
|
"orjson==3.11.5",
|
|
72
|
-
"packaging
|
|
72
|
+
"packaging~=26.3",
|
|
73
73
|
"passlib==1.7.1",
|
|
74
74
|
"posthog==7.28.0",
|
|
75
75
|
"pre-commit==4.6.2",
|
|
@@ -83,10 +83,10 @@ dependencies = [
|
|
|
83
83
|
"py-spy==0.4.2",
|
|
84
84
|
"pyarrow==23.0.1",
|
|
85
85
|
"pycurl==7.45.7",
|
|
86
|
-
"pydantic-ai-slim[anthropic]
|
|
87
|
-
"pydantic-ai-slim[google]
|
|
88
|
-
"pydantic-ai-slim[retries]
|
|
89
|
-
"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",
|
|
90
90
|
"pyjwt[crypto]==2.9.0",
|
|
91
91
|
"pympler==1.1",
|
|
92
92
|
"pynacl==1.5.0",
|
|
@@ -94,10 +94,10 @@ dependencies = [
|
|
|
94
94
|
"python-dateutil==2.9.0.post0",
|
|
95
95
|
"python-dotenv==1.1.0",
|
|
96
96
|
"python-ulid==2.7.0",
|
|
97
|
-
"pyyaml
|
|
97
|
+
"pyyaml~=6.0",
|
|
98
98
|
"redis[hiredis]==5.3.1",
|
|
99
99
|
"requests==2.32.4",
|
|
100
|
-
"sentry-sdk==2.69.
|
|
100
|
+
"sentry-sdk==2.69.2",
|
|
101
101
|
"setproctitle==1.3.3",
|
|
102
102
|
"shandy-sqlfmt==0.11.1",
|
|
103
103
|
"shandy-sqlfmt[jinjafmt]==0.11.1",
|
|
@@ -108,7 +108,7 @@ dependencies = [
|
|
|
108
108
|
"tabulate==0.8.10",
|
|
109
109
|
"thefuzz==0.22.1",
|
|
110
110
|
"tinybird-python-sdk[ai]==0.3.7",
|
|
111
|
-
"tinybird-toolset==2.6.
|
|
111
|
+
"tinybird-toolset==2.6.6",
|
|
112
112
|
"toposort==1.10",
|
|
113
113
|
"tornado==6.5.5",
|
|
114
114
|
"urllib3==1.26.20",
|
|
@@ -125,9 +125,9 @@ deploy = [
|
|
|
125
125
|
"GitPython==3.1.44",
|
|
126
126
|
"ansible==8.5.0",
|
|
127
127
|
"ara==1.6.1",
|
|
128
|
-
"boto3
|
|
128
|
+
"boto3~=1.40",
|
|
129
129
|
"fabric==3.2.2",
|
|
130
|
-
"google-auth
|
|
130
|
+
"google-auth~=2.47",
|
|
131
131
|
"jsonnet",
|
|
132
132
|
"prettytable==3.8.0",
|
|
133
133
|
"requests==2.32.4",
|
|
@@ -142,7 +142,7 @@ devtools = [
|
|
|
142
142
|
]
|
|
143
143
|
doc = [
|
|
144
144
|
"Pallets-Sphinx-Themes==2.3.0",
|
|
145
|
-
"pyOpenSSL
|
|
145
|
+
"pyOpenSSL~=23.2",
|
|
146
146
|
"sphinx-autobuild==2024.2.4",
|
|
147
147
|
"sphinx-sitemap",
|
|
148
148
|
"sphinx==7.3.7",
|
|
@@ -150,15 +150,15 @@ doc = [
|
|
|
150
150
|
"sphinxcontrib-jquery==4.1",
|
|
151
151
|
]
|
|
152
152
|
lint = [
|
|
153
|
-
"botocore-stubs
|
|
153
|
+
"botocore-stubs~=1.40",
|
|
154
154
|
"flake8~=7.3",
|
|
155
155
|
"flake8-async~=26.8",
|
|
156
156
|
"mypy==2.3.1",
|
|
157
|
-
"ruff==0.16.
|
|
157
|
+
"ruff==0.16.9",
|
|
158
158
|
"types-Markdown",
|
|
159
159
|
"types-PyYAML",
|
|
160
160
|
"types-aiofiles==24.1.0.20241221",
|
|
161
|
-
"types-boto3-lite
|
|
161
|
+
"types-boto3-lite~=1.40",
|
|
162
162
|
"types-cachetools",
|
|
163
163
|
"types-chardet",
|
|
164
164
|
"types-paramiko",
|
|
@@ -172,18 +172,19 @@ lint = [
|
|
|
172
172
|
test = [
|
|
173
173
|
"coverage==7.10.6",
|
|
174
174
|
"freezegun==1.5.5",
|
|
175
|
-
"google-auth
|
|
175
|
+
"google-auth~=2.47",
|
|
176
176
|
"gsutil==4.58",
|
|
177
|
+
"httpx2~=2.13",
|
|
177
178
|
"hypothesis==6.156.1",
|
|
178
179
|
"oauth2client==3.0.0",
|
|
179
180
|
"py==1.11.0",
|
|
180
|
-
"pytest-asyncio
|
|
181
|
+
"pytest-asyncio~=1.4",
|
|
181
182
|
"pytest-cov==4.1.0",
|
|
182
183
|
"pytest-env==1.1.3",
|
|
183
184
|
"pytest-flakefinder==1.1.0",
|
|
184
185
|
"pytest-timeout==2.3.1",
|
|
185
186
|
"pytest-xdist==3.6.1",
|
|
186
|
-
"pytest
|
|
187
|
+
"pytest~=8.1",
|
|
187
188
|
"rangehttpserver==1.4.0",
|
|
188
189
|
"yappi==1.7.6",
|
|
189
190
|
]
|
|
@@ -205,6 +206,8 @@ colibri = "tinybird.colibri.cli:cli"
|
|
|
205
206
|
members = [
|
|
206
207
|
"chbackups",
|
|
207
208
|
"data_connector",
|
|
209
|
+
"gatherer",
|
|
210
|
+
"tinybird_orchestrator",
|
|
208
211
|
]
|
|
209
212
|
|
|
210
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):
|
|
@@ -1388,13 +1389,14 @@ _namespace = {
|
|
|
1388
1389
|
}
|
|
1389
1390
|
|
|
1390
1391
|
|
|
1391
|
-
|
|
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}
|
|
1392
1396
|
for p in DEFAULT_PARAM_NAMES: # we handle these in an specific manner
|
|
1393
1397
|
reserved_vars.discard(p) # `format` is part of builtins
|
|
1394
|
-
# Allow 'id'
|
|
1398
|
+
# Allow 'id' as a template parameter name despite being a builtin - https://gitlab.com/tinybird/analytics/-/issues/19119
|
|
1395
1399
|
reserved_vars.discard("id")
|
|
1396
|
-
reserved_vars.discard("type")
|
|
1397
|
-
reserved_vars.discard("dir")
|
|
1398
1400
|
error_vars = ["error", "custom_error"]
|
|
1399
1401
|
|
|
1400
1402
|
|
|
@@ -1470,8 +1472,8 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1470
1472
|
return Expression(f"-- disable {feature}\n")
|
|
1471
1473
|
|
|
1472
1474
|
namespace.update(_namespace)
|
|
1473
|
-
# Default
|
|
1474
|
-
namespace.update({"id": None
|
|
1475
|
+
# Default it here, not in _namespace, so it stays visible to variable extraction.
|
|
1476
|
+
namespace.update({"id": None})
|
|
1475
1477
|
namespace.update(kwargs)
|
|
1476
1478
|
namespace.update(
|
|
1477
1479
|
{
|
|
@@ -1820,7 +1822,7 @@ def get_var_names(t: Template):
|
|
|
1820
1822
|
>>> [v['name'] for v in get_var_names(Template("{% for name in secret_names %}{{tb_secret(name)}}{% end %}"))]
|
|
1821
1823
|
['secret_names', 'name', 'tb_secret', 'name']
|
|
1822
1824
|
|
|
1823
|
-
Type casting with date function in elif chain
|
|
1825
|
+
Type casting with date function in elif chain:
|
|
1824
1826
|
>>> t = Template("{% if kind == 'int' %}{{Int32(val, 0)}}{% elif kind == 'date' %}{{DateTime(val)}}{% elif kind == 'diff' %}{{date_diff_in_days(val, now)}}{% end %}")
|
|
1825
1827
|
>>> [v['name'] for v in get_var_names(t)]
|
|
1826
1828
|
['kind', 'Int32', 'val', 'kind', 'DateTime', 'val', 'kind', 'date_diff_in_days', 'val', 'now']
|
|
@@ -2372,7 +2374,24 @@ def wrap_vars(t, escape_arrays: bool = False):
|
|
|
2372
2374
|
return var
|
|
2373
2375
|
|
|
2374
2376
|
|
|
2375
|
-
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]:
|
|
2376
2395
|
"""
|
|
2377
2396
|
>>> get_used_tables_in_template("select * from {{table('test')}}")
|
|
2378
2397
|
['test']
|
|
@@ -2386,30 +2405,42 @@ def get_used_tables_in_template(sql):
|
|
|
2386
2405
|
[]
|
|
2387
2406
|
>>> get_used_tables_in_template("select * from {{table('my.test')}}, {{table('another.one')}}")
|
|
2388
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']
|
|
2389
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, ...]:
|
|
2390
2420
|
try:
|
|
2391
2421
|
t = Template(sql)
|
|
2392
2422
|
|
|
2393
2423
|
def _n(chunks, tables):
|
|
2394
2424
|
for x in chunks:
|
|
2395
2425
|
if type(x).__name__ == "_Expression":
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
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)
|
|
2407
2438
|
elif type(x).__name__ == "_ControlBlock":
|
|
2408
2439
|
_n(x.body.chunks, tables)
|
|
2409
2440
|
|
|
2410
|
-
tables = []
|
|
2441
|
+
tables: List[str] = []
|
|
2411
2442
|
_n(t.file.body.chunks, tables)
|
|
2412
|
-
return tables
|
|
2443
|
+
return tuple(tables)
|
|
2413
2444
|
except SecurityException as e:
|
|
2414
2445
|
raise SQLTemplateException(e)
|
|
2415
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",
|
|
@@ -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
|
|
|
@@ -1304,11 +1304,11 @@ class ConnectionReplacements:
|
|
|
1304
1304
|
"""Maps prompt parameters to API parameters."""
|
|
1305
1305
|
|
|
1306
1306
|
api_params = {}
|
|
1307
|
-
for key in params.
|
|
1307
|
+
for key, value in params.items():
|
|
1308
1308
|
try:
|
|
1309
|
-
api_params[ConnectionReplacements._PARAMS_REPLACEMENTS[service][key]] =
|
|
1309
|
+
api_params[ConnectionReplacements._PARAMS_REPLACEMENTS[service][key]] = value
|
|
1310
1310
|
except KeyError:
|
|
1311
|
-
api_params[key] =
|
|
1311
|
+
api_params[key] = value
|
|
1312
1312
|
|
|
1313
1313
|
api_params["service"] = service
|
|
1314
1314
|
return api_params
|
|
@@ -385,7 +385,7 @@ async def datasource_truncate(ctx, datasource_name, yes, cascade):
|
|
|
385
385
|
|
|
386
386
|
@datasource.command(name="delete")
|
|
387
387
|
@click.argument("datasource_name")
|
|
388
|
-
@click.option("--sql-condition",
|
|
388
|
+
@click.option("--sql-condition", help="SQL WHERE condition to remove rows", hidden=True, required=True)
|
|
389
389
|
@click.option("--yes", is_flag=True, default=False, help="Do not ask for confirmation")
|
|
390
390
|
@click.option(
|
|
391
391
|
"--wait/--no-wait",
|