tinybird 4.6.22__tar.gz → 4.6.22.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 → tinybird-4.6.22.dev0}/PKG-INFO +1 -11
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/pyproject.toml +25 -29
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/client.py +8 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/sql_template.py +25 -54
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/sql_template_fmt.py +2 -2
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/syncasync.py +43 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/client.py +8 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/common.py +3 -3
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/create.py +4 -2
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/pull.py +3 -73
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datasource.py +1 -1
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/deployment_common.py +6 -4
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/exceptions.py +21 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/common.py +3 -3
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/datasource.py +1 -1
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tornado_template.py +93 -38
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird.egg-info/PKG-INFO +1 -11
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/setup.cfg +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/__cli__.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/check_pypi.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/config.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/context.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/datafile/common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/datatypes.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/feedback_manager.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/git_settings.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/iterating/__init__.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/iterating/data_branch_modes.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/prompts.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/service_datasources.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/sql.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/sql_toolset.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/cli.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/config.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/build_common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/cli.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/config.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/connection_dynamodb.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/connection_kafka.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/connection_s3.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/format_connection.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/datafile/playground.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/infra.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/job.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/logs.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/project.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/token.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/utils/__init__.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird/utils/bools.py +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.dev0}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.6.22 → tinybird-4.6.22.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.22
|
|
3
|
+
Version: 4.6.22.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -52,16 +52,6 @@ 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
|
-
|
|
65
55
|
4.6.20
|
|
66
56
|
********
|
|
67
57
|
|
|
@@ -18,35 +18,34 @@ authors = [
|
|
|
18
18
|
dependencies = [
|
|
19
19
|
"GitPython==3.1.44",
|
|
20
20
|
"Markdown==3.5.1",
|
|
21
|
-
"aioboto3
|
|
21
|
+
"aioboto3==14.0.0",
|
|
22
22
|
"aiofiles==24.1.0",
|
|
23
|
-
"aiohttp
|
|
24
|
-
"anthropic
|
|
25
|
-
"async-lru==2.3.0",
|
|
23
|
+
"aiohttp==3.11.2",
|
|
24
|
+
"anthropic==0.55.0",
|
|
26
25
|
"aws-msk-iam-sasl-signer-python==1.0.2",
|
|
27
26
|
"cachetools==5.5.0",
|
|
28
27
|
"cffi==1.17.1",
|
|
29
28
|
"chardet==4.0.0",
|
|
30
29
|
"ciso8601==2.2.0",
|
|
31
|
-
"click
|
|
30
|
+
"click==8.1.8",
|
|
32
31
|
"clickhouse-cityhash==1.0.2.5",
|
|
33
32
|
"clickhouse-driver==0.2.9",
|
|
34
33
|
"confluent-kafka[avro,json,schemaregistry]==2.12.2",
|
|
35
34
|
"contextvars==2.4",
|
|
36
35
|
"cramjam==2.11.0",
|
|
37
36
|
"croniter==6.2.2",
|
|
38
|
-
"cryptography
|
|
37
|
+
"cryptography==3.4.8",
|
|
39
38
|
"datasketch==1.6.5",
|
|
40
39
|
"dnspython==2.8.0",
|
|
41
40
|
"docker==7.1.0",
|
|
42
41
|
"fastavro==1.12.2",
|
|
43
42
|
"fastmcp==2.12.2",
|
|
44
|
-
"google-cloud-aiplatform
|
|
43
|
+
"google-cloud-aiplatform==1.148.1",
|
|
45
44
|
"google-cloud-compute==1.48.0",
|
|
46
45
|
"google-cloud-scheduler==2.20.0",
|
|
47
46
|
"google-cloud-secret-manager==2.29.0",
|
|
48
|
-
"google-cloud-storage
|
|
49
|
-
"google_api_core
|
|
47
|
+
"google-cloud-storage==3.4.1",
|
|
48
|
+
"google_api_core==2.25.2",
|
|
50
49
|
"googleapis_common_protos==1.66.0",
|
|
51
50
|
"grpcio_status==1.67.1",
|
|
52
51
|
"humanfriendly==10.0",
|
|
@@ -69,7 +68,7 @@ dependencies = [
|
|
|
69
68
|
"opentelemetry-sdk==1.38.0",
|
|
70
69
|
"orb-billing==2.17.0",
|
|
71
70
|
"orjson==3.11.5",
|
|
72
|
-
"packaging
|
|
71
|
+
"packaging==23.2",
|
|
73
72
|
"passlib==1.7.1",
|
|
74
73
|
"posthog==7.28.0",
|
|
75
74
|
"pre-commit==4.6.2",
|
|
@@ -83,10 +82,10 @@ dependencies = [
|
|
|
83
82
|
"py-spy==0.4.2",
|
|
84
83
|
"pyarrow==23.0.1",
|
|
85
84
|
"pycurl==7.45.7",
|
|
86
|
-
"pydantic-ai-slim[anthropic]
|
|
87
|
-
"pydantic-ai-slim[google]
|
|
88
|
-
"pydantic-ai-slim[retries]
|
|
89
|
-
"pydantic
|
|
85
|
+
"pydantic-ai-slim[anthropic]==0.5.0",
|
|
86
|
+
"pydantic-ai-slim[google]==0.5.0",
|
|
87
|
+
"pydantic-ai-slim[retries]==0.5.0",
|
|
88
|
+
"pydantic==2.12.5",
|
|
90
89
|
"pyjwt[crypto]==2.9.0",
|
|
91
90
|
"pympler==1.1",
|
|
92
91
|
"pynacl==1.5.0",
|
|
@@ -94,10 +93,10 @@ dependencies = [
|
|
|
94
93
|
"python-dateutil==2.9.0.post0",
|
|
95
94
|
"python-dotenv==1.1.0",
|
|
96
95
|
"python-ulid==2.7.0",
|
|
97
|
-
"pyyaml
|
|
96
|
+
"pyyaml==6.0.1",
|
|
98
97
|
"redis[hiredis]==5.3.1",
|
|
99
98
|
"requests==2.32.4",
|
|
100
|
-
"sentry-sdk==2.69.
|
|
99
|
+
"sentry-sdk==2.69.1",
|
|
101
100
|
"setproctitle==1.3.3",
|
|
102
101
|
"shandy-sqlfmt==0.11.1",
|
|
103
102
|
"shandy-sqlfmt[jinjafmt]==0.11.1",
|
|
@@ -108,7 +107,7 @@ dependencies = [
|
|
|
108
107
|
"tabulate==0.8.10",
|
|
109
108
|
"thefuzz==0.22.1",
|
|
110
109
|
"tinybird-python-sdk[ai]==0.3.7",
|
|
111
|
-
"tinybird-toolset==2.6.
|
|
110
|
+
"tinybird-toolset==2.6.2",
|
|
112
111
|
"toposort==1.10",
|
|
113
112
|
"tornado==6.5.5",
|
|
114
113
|
"urllib3==1.26.20",
|
|
@@ -125,9 +124,9 @@ deploy = [
|
|
|
125
124
|
"GitPython==3.1.44",
|
|
126
125
|
"ansible==8.5.0",
|
|
127
126
|
"ara==1.6.1",
|
|
128
|
-
"boto3
|
|
127
|
+
"boto3==1.36.21",
|
|
129
128
|
"fabric==3.2.2",
|
|
130
|
-
"google-auth
|
|
129
|
+
"google-auth==2.47.0",
|
|
131
130
|
"jsonnet",
|
|
132
131
|
"prettytable==3.8.0",
|
|
133
132
|
"requests==2.32.4",
|
|
@@ -142,7 +141,7 @@ devtools = [
|
|
|
142
141
|
]
|
|
143
142
|
doc = [
|
|
144
143
|
"Pallets-Sphinx-Themes==2.3.0",
|
|
145
|
-
"pyOpenSSL
|
|
144
|
+
"pyOpenSSL<24.0.0",
|
|
146
145
|
"sphinx-autobuild==2024.2.4",
|
|
147
146
|
"sphinx-sitemap",
|
|
148
147
|
"sphinx==7.3.7",
|
|
@@ -150,15 +149,15 @@ doc = [
|
|
|
150
149
|
"sphinxcontrib-jquery==4.1",
|
|
151
150
|
]
|
|
152
151
|
lint = [
|
|
153
|
-
"botocore-stubs
|
|
152
|
+
"botocore-stubs==1.36.23",
|
|
154
153
|
"flake8~=7.3",
|
|
155
154
|
"flake8-async~=26.8",
|
|
156
155
|
"mypy==2.3.1",
|
|
157
|
-
"ruff==0.16.
|
|
156
|
+
"ruff==0.16.8",
|
|
158
157
|
"types-Markdown",
|
|
159
158
|
"types-PyYAML",
|
|
160
159
|
"types-aiofiles==24.1.0.20241221",
|
|
161
|
-
"types-boto3-lite
|
|
160
|
+
"types-boto3-lite==1.36.21",
|
|
162
161
|
"types-cachetools",
|
|
163
162
|
"types-chardet",
|
|
164
163
|
"types-paramiko",
|
|
@@ -172,19 +171,18 @@ lint = [
|
|
|
172
171
|
test = [
|
|
173
172
|
"coverage==7.10.6",
|
|
174
173
|
"freezegun==1.5.5",
|
|
175
|
-
"google-auth
|
|
174
|
+
"google-auth==2.47.0",
|
|
176
175
|
"gsutil==4.58",
|
|
177
|
-
"httpx2~=2.13",
|
|
178
176
|
"hypothesis==6.156.1",
|
|
179
177
|
"oauth2client==3.0.0",
|
|
180
178
|
"py==1.11.0",
|
|
181
|
-
"pytest-asyncio
|
|
179
|
+
"pytest-asyncio==0.23.8",
|
|
182
180
|
"pytest-cov==4.1.0",
|
|
183
181
|
"pytest-env==1.1.3",
|
|
184
182
|
"pytest-flakefinder==1.1.0",
|
|
185
183
|
"pytest-timeout==2.3.1",
|
|
186
184
|
"pytest-xdist==3.6.1",
|
|
187
|
-
"pytest
|
|
185
|
+
"pytest==8.1.2",
|
|
188
186
|
"rangehttpserver==1.4.0",
|
|
189
187
|
"yappi==1.7.6",
|
|
190
188
|
]
|
|
@@ -206,8 +204,6 @@ colibri = "tinybird.colibri.cli:cli"
|
|
|
206
204
|
members = [
|
|
207
205
|
"chbackups",
|
|
208
206
|
"data_connector",
|
|
209
|
-
"gatherer",
|
|
210
|
-
"tinybird_orchestrator",
|
|
211
207
|
]
|
|
212
208
|
|
|
213
209
|
[tool.setuptools]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ast
|
|
2
|
+
import builtins
|
|
2
3
|
import linecache
|
|
3
4
|
import logging
|
|
4
5
|
import re
|
|
@@ -1335,10 +1336,8 @@ sqlescape_for_string_expression = sqlescape_generator(
|
|
|
1335
1336
|
)
|
|
1336
1337
|
|
|
1337
1338
|
|
|
1338
|
-
def escape_single_quote_str(s
|
|
1339
|
-
|
|
1340
|
-
# otherwise a trailing backslash escapes the closing quote and the following input becomes SQL
|
|
1341
|
-
return "'" + s.replace("\\", "\\\\").replace("'", "''") + "'"
|
|
1339
|
+
def escape_single_quote_str(s):
|
|
1340
|
+
return "'" + s.replace("'", "''") + "'"
|
|
1342
1341
|
|
|
1343
1342
|
|
|
1344
1343
|
def expression_wrapper(x, name, escape_arrays: bool = False):
|
|
@@ -1386,16 +1385,16 @@ _namespace = {
|
|
|
1386
1385
|
"close": None,
|
|
1387
1386
|
"print": None,
|
|
1388
1387
|
"input": None,
|
|
1388
|
+
# Keep customer parameters named `type`/`dir` usable without restoring the unsafe builtins.
|
|
1389
|
+
"type": None,
|
|
1390
|
+
"dir": None,
|
|
1389
1391
|
}
|
|
1390
1392
|
|
|
1391
1393
|
|
|
1392
|
-
|
|
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}
|
|
1394
|
+
reserved_vars = {"_tt_tmp", "_tt_append", "isinstance", "str", "error", "custom_error", *list(vars(builtins))}
|
|
1396
1395
|
for p in DEFAULT_PARAM_NAMES: # we handle these in an specific manner
|
|
1397
1396
|
reserved_vars.discard(p) # `format` is part of builtins
|
|
1398
|
-
# Allow 'id' as a template parameter
|
|
1397
|
+
# Allow 'id' to be used as a template parameter - https://gitlab.com/tinybird/analytics/-/issues/19119
|
|
1399
1398
|
reserved_vars.discard("id")
|
|
1400
1399
|
error_vars = ["error", "custom_error"]
|
|
1401
1400
|
|
|
@@ -1472,7 +1471,8 @@ def generate(self, **kwargs) -> Tuple[str, TemplateExecutionResults]:
|
|
|
1472
1471
|
return Expression(f"-- disable {feature}\n")
|
|
1473
1472
|
|
|
1474
1473
|
namespace.update(_namespace)
|
|
1475
|
-
#
|
|
1474
|
+
# This is to fix the issue https://gitlab.com/tinybird/analytics/-/issues/19119
|
|
1475
|
+
# We need to do the override here because if we modify the _namespace, we would filter out parameters from the users
|
|
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 (type is in reserved_vars):
|
|
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,24 +2374,7 @@ def wrap_vars(t, escape_arrays: bool = False):
|
|
|
2374
2374
|
return var
|
|
2375
2375
|
|
|
2376
2376
|
|
|
2377
|
-
def
|
|
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]:
|
|
2377
|
+
def get_used_tables_in_template(sql):
|
|
2395
2378
|
"""
|
|
2396
2379
|
>>> get_used_tables_in_template("select * from {{table('test')}}")
|
|
2397
2380
|
['test']
|
|
@@ -2405,42 +2388,30 @@ def get_used_tables_in_template(sql: str) -> List[str]:
|
|
|
2405
2388
|
[]
|
|
2406
2389
|
>>> get_used_tables_in_template("select * from {{table('my.test')}}, {{table('another.one')}}")
|
|
2407
2390
|
['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']
|
|
2412
2391
|
"""
|
|
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, ...]:
|
|
2420
2392
|
try:
|
|
2421
2393
|
t = Template(sql)
|
|
2422
2394
|
|
|
2423
2395
|
def _n(chunks, tables):
|
|
2424
2396
|
for x in chunks:
|
|
2425
2397
|
if type(x).__name__ == "_Expression":
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
tables.append(name)
|
|
2398
|
+
c = compile(x.expression, "<string>", "exec", dont_inherit=True)
|
|
2399
|
+
v = [x.lower() for x in c.co_names if x not in _namespace and x not in reserved_vars]
|
|
2400
|
+
if "table" in v:
|
|
2401
|
+
|
|
2402
|
+
def _t(*args, **kwargs):
|
|
2403
|
+
return str(args[0])
|
|
2404
|
+
|
|
2405
|
+
n = {"table": _t, "TABLE": _t}
|
|
2406
|
+
e = "_tt_tmp = %s" % x.expression
|
|
2407
|
+
exec_in(e, n)
|
|
2408
|
+
tables += [n["_tt_tmp"]]
|
|
2438
2409
|
elif type(x).__name__ == "_ControlBlock":
|
|
2439
2410
|
_n(x.body.chunks, tables)
|
|
2440
2411
|
|
|
2441
|
-
tables
|
|
2412
|
+
tables = []
|
|
2442
2413
|
_n(t.file.body.chunks, tables)
|
|
2443
|
-
return
|
|
2414
|
+
return tables
|
|
2444
2415
|
except SecurityException as e:
|
|
2445
2416
|
raise SQLTemplateException(e)
|
|
2446
2417
|
|
|
@@ -214,8 +214,8 @@ class TinybirdDialect(ClickHouse):
|
|
|
214
214
|
],
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
for section
|
|
218
|
-
for rule in
|
|
217
|
+
for section in override_rules:
|
|
218
|
+
for rule in override_rules[section]:
|
|
219
219
|
for rr in self.RULES[section]:
|
|
220
220
|
if rr.name == rule.name:
|
|
221
221
|
self.RULES[section].remove(rr)
|
|
@@ -260,6 +260,49 @@ 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
|
+
|
|
263
306
|
class AsyncToSync:
|
|
264
307
|
"""
|
|
265
308
|
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.22'
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '4.6.22.dev0'
|
|
8
|
+
__revision__ = '3a75e0ef'
|
|
@@ -1277,11 +1277,11 @@ class ConnectionReplacements:
|
|
|
1277
1277
|
"""Maps prompt parameters to API parameters."""
|
|
1278
1278
|
|
|
1279
1279
|
api_params = {}
|
|
1280
|
-
for key
|
|
1280
|
+
for key in params.keys():
|
|
1281
1281
|
try:
|
|
1282
|
-
api_params[ConnectionReplacements._PARAMS_REPLACEMENTS[service][key]] =
|
|
1282
|
+
api_params[ConnectionReplacements._PARAMS_REPLACEMENTS[service][key]] = params[key]
|
|
1283
1283
|
except KeyError:
|
|
1284
|
-
api_params[key] =
|
|
1284
|
+
api_params[key] = params[key]
|
|
1285
1285
|
|
|
1286
1286
|
api_params["service"] = service
|
|
1287
1287
|
return api_params
|
|
@@ -215,12 +215,14 @@ 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
|
|
218
|
+
for x in PROJECT_PATHS_DESCRIPTIONS.keys():
|
|
219
219
|
try:
|
|
220
220
|
path = x.split("→")[0].strip()
|
|
221
221
|
f = folder_path / path
|
|
222
222
|
f.mkdir()
|
|
223
|
-
click.echo(
|
|
223
|
+
click.echo(
|
|
224
|
+
FeedbackManager.info(message=f"./{x} ") + FeedbackManager.gray(message=PROJECT_PATHS_DESCRIPTIONS[x])
|
|
225
|
+
)
|
|
224
226
|
except FileExistsError:
|
|
225
227
|
pass
|
|
226
228
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
1
|
from pathlib import Path
|
|
3
2
|
from typing import Any, Optional
|
|
4
3
|
|
|
5
4
|
import click
|
|
6
5
|
|
|
7
|
-
from tinybird.datafile.common import PipeNodeTypes
|
|
8
|
-
from tinybird.datafile.parse_pipe import parse_pipe
|
|
9
6
|
from tinybird.tb.client import AuthNoTokenException, TinyB
|
|
10
7
|
from tinybird.tb.modules.datafile.format_datasource import format_datasource
|
|
11
8
|
from tinybird.tb.modules.datafile.format_pipe import format_pipe
|
|
@@ -13,52 +10,6 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
|
13
10
|
|
|
14
11
|
PULL_EXISTING_FILE_MAX_DEPTH = 5
|
|
15
12
|
|
|
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
|
-
|
|
62
13
|
|
|
63
14
|
def folder_pull(
|
|
64
15
|
client: TinyB,
|
|
@@ -110,7 +61,6 @@ def folder_pull(
|
|
|
110
61
|
get_resource_function: str,
|
|
111
62
|
progress_bar: bool = False,
|
|
112
63
|
fmt: bool = False,
|
|
113
|
-
demoted_pipe_types: Optional[dict[str, str]] = None,
|
|
114
64
|
) -> list[Path]:
|
|
115
65
|
def write_resource(k: dict[str, Any]) -> Optional[Path]:
|
|
116
66
|
name = f"{k['name']}.{extension}"
|
|
@@ -123,19 +73,8 @@ def folder_pull(
|
|
|
123
73
|
else:
|
|
124
74
|
resource = getattr(client, get_resource_function)(k["name"])
|
|
125
75
|
resource_to_write = resource
|
|
126
|
-
|
|
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:
|
|
76
|
+
|
|
77
|
+
if fmt:
|
|
139
78
|
if extension == "datasource":
|
|
140
79
|
resource_to_write = format_datasource(name, content=resource)
|
|
141
80
|
elif extension == "pipe":
|
|
@@ -146,7 +85,7 @@ def folder_pull(
|
|
|
146
85
|
dest_folder = Path(folder) / "vendor" / k["name"].split(".", 1)[0]
|
|
147
86
|
name = f"{k['name'].split('.', 1)[1]}.{extension}"
|
|
148
87
|
|
|
149
|
-
file_folder = get_file_folder(extension,
|
|
88
|
+
file_folder = get_file_folder(extension, k.get("type"))
|
|
150
89
|
f = Path(dest_folder) / file_folder if file_folder is not None else Path(dest_folder)
|
|
151
90
|
|
|
152
91
|
existing_file = find_existing_resource_file(Path(dest_folder), name)
|
|
@@ -189,14 +128,6 @@ def folder_pull(
|
|
|
189
128
|
pipes = client.pipes()
|
|
190
129
|
connections = client.connections()
|
|
191
130
|
|
|
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
|
-
|
|
200
131
|
if only_vendored:
|
|
201
132
|
written_files = write_files(
|
|
202
133
|
resources=[ds for ds in datasources if "shared_from" in ds],
|
|
@@ -223,7 +154,6 @@ def folder_pull(
|
|
|
223
154
|
get_resource_function="pipe_file",
|
|
224
155
|
progress_bar=progress_bar,
|
|
225
156
|
fmt=fmt,
|
|
226
|
-
demoted_pipe_types=demoted_pipe_types,
|
|
227
157
|
)
|
|
228
158
|
)
|
|
229
159
|
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", help="SQL WHERE condition to remove rows", hidden=True, required=True)
|
|
680
|
+
@click.option("--sql-condition", default=None, 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,12 +335,13 @@ 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
|
-
|
|
339
|
-
deployment_to_discard = next(deployment for deployment in deployments if deployment is not live_deployment)
|
|
338
|
+
current_deployment, deployment_to_discard = deployments[0], deployments[1]
|
|
340
339
|
|
|
341
|
-
|
|
340
|
+
# NOTE(eclbg): we never get here. We wrote this code when we though we'd enable promoting back and forth between
|
|
341
|
+
# staging and live, but the current CLI commands don't allow getting in that state
|
|
342
|
+
if current_deployment.get("status") != "data_ready":
|
|
342
343
|
click.echo(FeedbackManager.error(message="Previous deployment is not ready"))
|
|
343
|
-
deploy_errors =
|
|
344
|
+
deploy_errors = current_deployment.get("errors", [])
|
|
344
345
|
for deploy_error in deploy_errors:
|
|
345
346
|
click.echo(FeedbackManager.error(message=f"* {deploy_error}"))
|
|
346
347
|
return
|
|
@@ -358,6 +359,7 @@ def discard_deployment(host: Optional[str], headers: dict, wait: bool, request_f
|
|
|
358
359
|
click.echo(FeedbackManager.error(message=result.get("error")))
|
|
359
360
|
sys_exit("deployment_error", result.get("error", "Unknown error"))
|
|
360
361
|
|
|
362
|
+
deployment_to_discard = deployments[1]
|
|
361
363
|
click.echo(FeedbackManager.success(message="Discard process successfully started"))
|
|
362
364
|
|
|
363
365
|
if wait:
|
|
@@ -92,6 +92,20 @@ 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
|
+
|
|
95
109
|
class CLITestException(CLIException):
|
|
96
110
|
"""Exceptions generated by the test commands"""
|
|
97
111
|
|
|
@@ -113,6 +127,13 @@ class CLIMockException(CLIException):
|
|
|
113
127
|
super().__init__(message, "mock_error", **kw_telemetry_event_data)
|
|
114
128
|
|
|
115
129
|
|
|
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
|
+
|
|
116
137
|
class CLILoginException(CLIException):
|
|
117
138
|
"""Exceptions generated by the login commands"""
|
|
118
139
|
|