tinybird 4.6.18.dev0__tar.gz → 4.6.19__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.18.dev0 → tinybird-4.6.19}/PKG-INFO +21 -1
- tinybird-4.6.19/pyproject.toml +228 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/ch_utils/constants.py +1 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/ch_utils/engine.py +56 -44
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/client.py +51 -26
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/datafile/common.py +20 -25
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/git_settings.py +1 -3
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/service_datasources.py +13 -12
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/sql.py +3 -10
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/sql_template.py +53 -71
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/sql_template_fmt.py +8 -13
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/sql_toolset.py +62 -5
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/syncasync.py +9 -11
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/client.py +54 -23
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/build_common.py +4 -6
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/cicd.py +1 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/cli.py +4 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/common.py +23 -89
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/config.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/connection_kafka.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/connection_s3.py +13 -18
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/create.py +3 -6
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/build.py +2 -3
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/build_pipe.py +1 -4
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/diff.py +2 -1
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/format_common.py +9 -10
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/format_connection.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/format_datasource.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/format_pipe.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/pipe_checker.py +6 -7
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/playground.py +3 -4
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datasource.py +7 -8
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/deployment_common.py +3 -5
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/feedback_manager.py +1 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/infra.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/job.py +22 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/logs.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/materialization.py +1 -1
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/project.py +4 -4
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/tinyunit/tinyunit.py +4 -4
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/token.py +2 -5
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/watch.py +1 -1
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/branch.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/cicd.py +2 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/cli.py +5 -9
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/common.py +27 -94
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/config.py +1 -2
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/datasource.py +1 -1
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/pipe.py +9 -13
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +4 -4
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/workspace.py +11 -13
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tornado_template.py +12 -17
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird.egg-info/PKG-INFO +21 -1
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird.egg-info/SOURCES.txt +1 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/setup.cfg +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/__cli__.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/check_pypi.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/config.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/context.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/datatypes.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/feedback_manager.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/iterating/__init__.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/iterating/data_branch_modes.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/prompts.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/cli.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/config.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/connection_dynamodb.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.6.18.dev0 → tinybird-4.6.19}/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.19
|
|
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,26 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
54
|
|
|
55
|
+
4.6.19
|
|
56
|
+
********
|
|
57
|
+
|
|
58
|
+
- `Changed` ``tb datasource append`` and ``tb datasource replace`` submit remote CSV, NDJSON, and Parquet URLs through the v1 import endpoint by default.
|
|
59
|
+
|
|
60
|
+
4.6.18
|
|
61
|
+
********
|
|
62
|
+
|
|
63
|
+
- `Fixed` CLI commands (for example ``tb migrate-to-forward``) no longer abort on startup when the best-effort refresh of the cached workspace id/name fails for a reason other than authentication.
|
|
64
|
+
|
|
65
|
+
4.6.17
|
|
66
|
+
********
|
|
67
|
+
|
|
68
|
+
- `Added` ``tb job retry <job_id>`` to retry eligible import and S3/GCS sync jobs in ``error`` or ``cancelled`` status.
|
|
69
|
+
|
|
70
|
+
4.6.18
|
|
71
|
+
********
|
|
72
|
+
|
|
73
|
+
- `Added` ``Markdown`` is now a valid ``FORMAT`` for SQL queries (for example ``tb sql "SELECT 1 FORMAT Markdown"``), returned as a Markdown table.
|
|
74
|
+
|
|
55
75
|
4.6.16
|
|
56
76
|
********
|
|
57
77
|
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools>=61.0",
|
|
4
|
+
"wheel==0.37.1",
|
|
5
|
+
"cffi==1.17.1",
|
|
6
|
+
]
|
|
7
|
+
build-backend = "setuptools.build_meta"
|
|
8
|
+
|
|
9
|
+
[project]
|
|
10
|
+
name = "tinybird"
|
|
11
|
+
version = "1.0"
|
|
12
|
+
description = "tinybird"
|
|
13
|
+
readme = { text = "tinybird analytics", content-type = "text/markdown" }
|
|
14
|
+
requires-python = ">=3.13,<3.15"
|
|
15
|
+
authors = [
|
|
16
|
+
{ name = "tinybird.co" },
|
|
17
|
+
]
|
|
18
|
+
dependencies = [
|
|
19
|
+
"GitPython==3.1.44",
|
|
20
|
+
"Markdown==3.5.1",
|
|
21
|
+
"aioboto3==14.0.0",
|
|
22
|
+
"aiofiles==24.1.0",
|
|
23
|
+
"aiohttp==3.11.2",
|
|
24
|
+
"anthropic==0.55.0",
|
|
25
|
+
"aws-msk-iam-sasl-signer-python==1.0.2",
|
|
26
|
+
"cachetools==5.5.0",
|
|
27
|
+
"cffi==1.17.1",
|
|
28
|
+
"chardet==4.0.0",
|
|
29
|
+
"ciso8601==2.2.0",
|
|
30
|
+
"click==8.1.8",
|
|
31
|
+
"clickhouse-cityhash==1.0.2.5",
|
|
32
|
+
"clickhouse-driver==0.2.9",
|
|
33
|
+
"confluent-kafka[avro,json,schemaregistry]==2.12.2",
|
|
34
|
+
"contextvars==2.4",
|
|
35
|
+
"cramjam==2.11.0",
|
|
36
|
+
"croniter==6.2.2",
|
|
37
|
+
"cryptography==3.4.8",
|
|
38
|
+
"datasketch==1.6.5",
|
|
39
|
+
"dnspython==2.8.0",
|
|
40
|
+
"docker==7.1.0",
|
|
41
|
+
"fastavro==1.12.2",
|
|
42
|
+
"fastmcp==2.12.2",
|
|
43
|
+
"google-cloud-aiplatform==1.148.1",
|
|
44
|
+
"google-cloud-compute==1.48.0",
|
|
45
|
+
"google-cloud-scheduler==2.20.0",
|
|
46
|
+
"google-cloud-secret-manager==2.29.0",
|
|
47
|
+
"google-cloud-storage==3.4.1",
|
|
48
|
+
"google_api_core==2.25.2",
|
|
49
|
+
"googleapis_common_protos==1.66.0",
|
|
50
|
+
"grpcio_status==1.67.1",
|
|
51
|
+
"humanfriendly==10.0",
|
|
52
|
+
"isal==1.8.0",
|
|
53
|
+
"jinja2",
|
|
54
|
+
"jsondiff==2.2.1",
|
|
55
|
+
"jsonschema==4.23.0",
|
|
56
|
+
"litellm==1.80.11",
|
|
57
|
+
"logfire-api==4.2.0",
|
|
58
|
+
"lru-dict==1.3.0",
|
|
59
|
+
"lz4==4.4.5",
|
|
60
|
+
"memray==1.20.0",
|
|
61
|
+
"msgspec==0.21.1",
|
|
62
|
+
"multidict==6.6.4",
|
|
63
|
+
"networkx==3.4.2",
|
|
64
|
+
"numpy==1.26.4",
|
|
65
|
+
"objgraph==3.6.2",
|
|
66
|
+
"opentelemetry-api==1.38.0",
|
|
67
|
+
"opentelemetry-exporter-otlp-proto-http==1.38.0",
|
|
68
|
+
"opentelemetry-sdk==1.38.0",
|
|
69
|
+
"orb-billing==2.17.0",
|
|
70
|
+
"orjson==3.11.5",
|
|
71
|
+
"packaging==23.2",
|
|
72
|
+
"passlib==1.7.1",
|
|
73
|
+
"posthog==7.28.0",
|
|
74
|
+
"pre-commit==4.6.2",
|
|
75
|
+
"prometheus_client==0.26.0",
|
|
76
|
+
"prompt_toolkit==3.0.48",
|
|
77
|
+
"propcache==0.3.2",
|
|
78
|
+
"proto_plus==1.25.0",
|
|
79
|
+
"protobuf==5.29.5",
|
|
80
|
+
"psutil==7.2.2",
|
|
81
|
+
"psycopg2-binary==2.9.12",
|
|
82
|
+
"py-spy==0.4.2",
|
|
83
|
+
"pyarrow==23.0.1",
|
|
84
|
+
"pycurl==7.45.7",
|
|
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",
|
|
89
|
+
"pyjwt[crypto]==2.9.0",
|
|
90
|
+
"pympler==1.1",
|
|
91
|
+
"pynacl==1.5.0",
|
|
92
|
+
"pyperclip==1.9.0",
|
|
93
|
+
"python-dateutil==2.9.0.post0",
|
|
94
|
+
"python-dotenv==1.1.0",
|
|
95
|
+
"python-ulid==2.7.0",
|
|
96
|
+
"pyyaml==6.0.1",
|
|
97
|
+
"redis[hiredis]==5.3.1",
|
|
98
|
+
"requests==2.32.4",
|
|
99
|
+
"sentry-sdk==2.69.1",
|
|
100
|
+
"setproctitle==1.3.3",
|
|
101
|
+
"shandy-sqlfmt==0.11.1",
|
|
102
|
+
"shandy-sqlfmt[jinjafmt]==0.11.1",
|
|
103
|
+
"sqlparse==0.4.3",
|
|
104
|
+
"starlette==1.0.1",
|
|
105
|
+
"streaming-form-data==1.20.0",
|
|
106
|
+
"stripe==3.1.0",
|
|
107
|
+
"tabulate==0.8.10",
|
|
108
|
+
"thefuzz==0.22.1",
|
|
109
|
+
"tinybird-python-sdk[ai]==0.3.7",
|
|
110
|
+
"tinybird-toolset==2.6.2",
|
|
111
|
+
"toposort==1.10",
|
|
112
|
+
"tornado==6.5.5",
|
|
113
|
+
"urllib3==1.26.20",
|
|
114
|
+
"uvicorn[standard]==0.49.0",
|
|
115
|
+
"virtualenv==20.21.1",
|
|
116
|
+
"watchdog==6.0.0",
|
|
117
|
+
"wheel==0.37.1",
|
|
118
|
+
"zlib-ng==1.0.0",
|
|
119
|
+
"zstandard==0.25.0",
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
[dependency-groups]
|
|
123
|
+
deploy = [
|
|
124
|
+
"GitPython==3.1.44",
|
|
125
|
+
"ansible==8.5.0",
|
|
126
|
+
"ara==1.6.1",
|
|
127
|
+
"boto3==1.36.21",
|
|
128
|
+
"fabric==3.2.2",
|
|
129
|
+
"google-auth==2.47.0",
|
|
130
|
+
"jsonnet",
|
|
131
|
+
"prettytable==3.8.0",
|
|
132
|
+
"requests==2.32.4",
|
|
133
|
+
"requests[security]",
|
|
134
|
+
"xmltodict",
|
|
135
|
+
]
|
|
136
|
+
devtools = [
|
|
137
|
+
"flameprof",
|
|
138
|
+
"matplotlib",
|
|
139
|
+
"memory_profiler",
|
|
140
|
+
"rope",
|
|
141
|
+
]
|
|
142
|
+
doc = [
|
|
143
|
+
"Pallets-Sphinx-Themes==2.3.0",
|
|
144
|
+
"pyOpenSSL<24.0.0",
|
|
145
|
+
"sphinx-autobuild==2024.2.4",
|
|
146
|
+
"sphinx-sitemap",
|
|
147
|
+
"sphinx==7.3.7",
|
|
148
|
+
"sphinxcontrib-httpdomain",
|
|
149
|
+
"sphinxcontrib-jquery==4.1",
|
|
150
|
+
]
|
|
151
|
+
lint = [
|
|
152
|
+
"botocore-stubs==1.36.23",
|
|
153
|
+
"mypy==2.3.1",
|
|
154
|
+
"ruff==0.16.8",
|
|
155
|
+
"types-Markdown",
|
|
156
|
+
"types-PyYAML",
|
|
157
|
+
"types-aiofiles==24.1.0.20241221",
|
|
158
|
+
"types-boto3-lite==1.36.21",
|
|
159
|
+
"types-cachetools",
|
|
160
|
+
"types-chardet",
|
|
161
|
+
"types-paramiko",
|
|
162
|
+
"types-pycurl",
|
|
163
|
+
"types-python-dateutil",
|
|
164
|
+
"types-pytz",
|
|
165
|
+
"types-requests",
|
|
166
|
+
"types-tabulate",
|
|
167
|
+
"types_croniter",
|
|
168
|
+
]
|
|
169
|
+
test = [
|
|
170
|
+
"coverage==7.10.6",
|
|
171
|
+
"freezegun==1.5.5",
|
|
172
|
+
"google-auth==2.47.0",
|
|
173
|
+
"gsutil==4.58",
|
|
174
|
+
"hypothesis==6.156.1",
|
|
175
|
+
"oauth2client==3.0.0",
|
|
176
|
+
"py==1.11.0",
|
|
177
|
+
"pytest-asyncio==0.23.8",
|
|
178
|
+
"pytest-cov==4.1.0",
|
|
179
|
+
"pytest-env==1.1.3",
|
|
180
|
+
"pytest-flakefinder==1.1.0",
|
|
181
|
+
"pytest-timeout==2.3.1",
|
|
182
|
+
"pytest-xdist==3.6.1",
|
|
183
|
+
"pytest==8.1.2",
|
|
184
|
+
"rangehttpserver==1.4.0",
|
|
185
|
+
"yappi==1.7.6",
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
[project.scripts]
|
|
189
|
+
tinybird_server = "tinybird.app:run"
|
|
190
|
+
tinybird_tool = "tinybird.tinybird_tool.main:cli"
|
|
191
|
+
tb_old = "tinybird.tb_cli:cli"
|
|
192
|
+
tb = "tinybird.tb.cli:cli"
|
|
193
|
+
colibri = "tinybird.colibri.cli:cli"
|
|
194
|
+
|
|
195
|
+
[tool.uv.workspace]
|
|
196
|
+
members = ["data_connector"]
|
|
197
|
+
|
|
198
|
+
[tool.setuptools]
|
|
199
|
+
include-package-data = true
|
|
200
|
+
|
|
201
|
+
[tool.setuptools.packages.find]
|
|
202
|
+
namespaces = false
|
|
203
|
+
include = ["tinybird", "tinybird.*", "tinybird_shared", "tinybird_shared.*", "scripts"]
|
|
204
|
+
exclude = ["tests*"]
|
|
205
|
+
|
|
206
|
+
[tool.setuptools.package-data]
|
|
207
|
+
tinybird = [
|
|
208
|
+
"templates/**/*",
|
|
209
|
+
"static/**/*",
|
|
210
|
+
"default_pipes/**/*",
|
|
211
|
+
"sql/**/*",
|
|
212
|
+
"monitors/**/*.sql",
|
|
213
|
+
"scripts/**/*",
|
|
214
|
+
"data_projects/**/*",
|
|
215
|
+
"data_projects/**/.*",
|
|
216
|
+
"raw_events/**/*",
|
|
217
|
+
"query_booster/**/*",
|
|
218
|
+
"deployments/**/*",
|
|
219
|
+
]
|
|
220
|
+
tinybird_shared = [
|
|
221
|
+
"redis_client/**/*",
|
|
222
|
+
"retry/**/*",
|
|
223
|
+
"metrics/**/*",
|
|
224
|
+
"gatherer_settings/**/*",
|
|
225
|
+
"clickhouse/**/*",
|
|
226
|
+
"gatherer_backpressure/**/*",
|
|
227
|
+
"data_connector_circuit_breaker/**/*",
|
|
228
|
+
]
|
|
@@ -111,8 +111,7 @@ class TableDetails:
|
|
|
111
111
|
|
|
112
112
|
@property
|
|
113
113
|
def version(self):
|
|
114
|
-
|
|
115
|
-
return _version
|
|
114
|
+
return self.details.get("version", None)
|
|
116
115
|
|
|
117
116
|
def is_replicated(self) -> bool:
|
|
118
117
|
engine: Optional[str] = self.details.get("engine", None)
|
|
@@ -183,6 +182,7 @@ class TableDetails:
|
|
|
183
182
|
settings = self.details.get("settings", None)
|
|
184
183
|
if settings and settings.strip().lower() != "index_granularity = 8192":
|
|
185
184
|
return settings
|
|
185
|
+
return None
|
|
186
186
|
|
|
187
187
|
@property
|
|
188
188
|
def ttl(self):
|
|
@@ -190,23 +190,19 @@ class TableDetails:
|
|
|
190
190
|
|
|
191
191
|
@property
|
|
192
192
|
def ver(self):
|
|
193
|
-
|
|
194
|
-
return _ver
|
|
193
|
+
return self.details.get("ver", None)
|
|
195
194
|
|
|
196
195
|
@property
|
|
197
196
|
def is_deleted(self):
|
|
198
|
-
|
|
199
|
-
return _is_deleted
|
|
197
|
+
return self.details.get("is_deleted", None)
|
|
200
198
|
|
|
201
199
|
@property
|
|
202
200
|
def columns(self):
|
|
203
|
-
|
|
204
|
-
return _columns
|
|
201
|
+
return self.details.get("columns", None)
|
|
205
202
|
|
|
206
203
|
@property
|
|
207
204
|
def sign(self):
|
|
208
|
-
|
|
209
|
-
return _sign
|
|
205
|
+
return self.details.get("sign", None)
|
|
210
206
|
|
|
211
207
|
@property
|
|
212
208
|
def statistics(self) -> Dict[str, Any]:
|
|
@@ -444,35 +440,64 @@ def get_engine_config(engine: str):
|
|
|
444
440
|
)
|
|
445
441
|
|
|
446
442
|
|
|
447
|
-
def
|
|
448
|
-
|
|
443
|
+
def validate_engine_config(
|
|
444
|
+
engine: str, args: dict, schema: Optional[str] = None, columns: Optional[List[Dict[str, Any]]] = None
|
|
445
|
+
) -> None:
|
|
446
|
+
if schema is not None and columns is not None:
|
|
447
|
+
raise ValueError("You can not use 'schema' and 'columns' at the same time")
|
|
448
|
+
_, (params, options) = get_engine_config(engine)
|
|
449
|
+
schema_columns = parse_table_structure(schema) if schema is not None else (columns or [])
|
|
450
|
+
engine_settings = {key.replace("engine_", ""): value for key, value in args.items()}
|
|
451
|
+
|
|
452
|
+
for arg in engine_settings:
|
|
453
|
+
if not hasattr(TableDetails, arg):
|
|
454
|
+
raise ValueError(f"engine_{arg} is not a valid option")
|
|
455
|
+
|
|
449
456
|
for p in params:
|
|
450
|
-
if p.required and p.name not in
|
|
457
|
+
if p.required and p.name not in engine_settings:
|
|
451
458
|
raise ValueError(f"Missing required parameter '{p.name}'")
|
|
452
|
-
param_value =
|
|
459
|
+
param_value = engine_settings.get(p.name) or p.default_value
|
|
453
460
|
if not param_value:
|
|
454
461
|
continue
|
|
455
462
|
if p.is_valid:
|
|
456
463
|
check_is_valid(
|
|
457
|
-
valid_check=p.is_valid,
|
|
464
|
+
valid_check=p.is_valid,
|
|
465
|
+
check_type="parameter",
|
|
466
|
+
columns=schema_columns,
|
|
467
|
+
tb_param=p.tb_param,
|
|
468
|
+
value=param_value,
|
|
458
469
|
)
|
|
470
|
+
|
|
471
|
+
for o in options:
|
|
472
|
+
if o.required and o.name not in engine_settings:
|
|
473
|
+
raise ValueError(f"Missing required option '{o.name}'")
|
|
474
|
+
option_value = engine_settings.get(o.name) or o.default_value
|
|
475
|
+
if o.is_valid:
|
|
476
|
+
check_is_valid(
|
|
477
|
+
valid_check=o.is_valid,
|
|
478
|
+
check_type="option",
|
|
479
|
+
columns=schema_columns,
|
|
480
|
+
tb_param=o.tb_param,
|
|
481
|
+
value=option_value,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def engine_params(params: List[EngineParam], args: Dict) -> List[str]:
|
|
486
|
+
params_values = []
|
|
487
|
+
for p in params:
|
|
488
|
+
param_value = args.get(p.name, None) or p.default_value
|
|
489
|
+
if not param_value:
|
|
490
|
+
continue
|
|
459
491
|
params_values.append(param_value)
|
|
460
492
|
return params_values
|
|
461
493
|
|
|
462
494
|
|
|
463
|
-
def engine_options(
|
|
495
|
+
def engine_options(options: List[EngineOption], args: Dict) -> List[str]:
|
|
464
496
|
options_values = []
|
|
465
497
|
engine_settings = ""
|
|
466
498
|
|
|
467
499
|
for o in options:
|
|
468
|
-
if o.required and o.name not in args:
|
|
469
|
-
raise ValueError(f"Missing required option '{o.name}'")
|
|
470
500
|
option_value = args.get(o.name) or o.default_value
|
|
471
|
-
if o.is_valid:
|
|
472
|
-
check_is_valid(
|
|
473
|
-
valid_check=o.is_valid, check_type="option", columns=columns, tb_param=o.tb_param, value=option_value
|
|
474
|
-
)
|
|
475
|
-
|
|
476
501
|
if option_value:
|
|
477
502
|
if o.sql.lower() == "settings":
|
|
478
503
|
engine_settings = f"{o.sql} {option_value}"
|
|
@@ -494,7 +519,7 @@ def check_is_valid(
|
|
|
494
519
|
columns: List[Dict[str, Any]],
|
|
495
520
|
tb_param: str,
|
|
496
521
|
value: str,
|
|
497
|
-
):
|
|
522
|
+
) -> None:
|
|
498
523
|
"""
|
|
499
524
|
>>> check_is_valid(sorting_key_is_valid, 'option', ['column-name'], 'sorting_key', 'date')
|
|
500
525
|
|
|
@@ -511,15 +536,13 @@ def check_is_valid(
|
|
|
511
536
|
raise ValueError(f"Invalid value '{value}' for {check_type} '{tb_param}', reason: {e}")
|
|
512
537
|
|
|
513
538
|
|
|
514
|
-
def build_engine(
|
|
515
|
-
engine
|
|
516
|
-
):
|
|
517
|
-
return f"{engine}({', '.join(engine_params(columns, params, args))}) {' '.join(engine_options(columns, options, args))}".strip()
|
|
539
|
+
def build_engine(engine: str, params: List[EngineParam], options: List[EngineOption], args: Dict) -> str:
|
|
540
|
+
return f"{engine}({', '.join(engine_params(params, args))}) {' '.join(engine_options(options, args))}".strip()
|
|
518
541
|
|
|
519
542
|
|
|
520
543
|
def engine_full_from_dict(
|
|
521
544
|
engine: str, args: dict, schema: Optional[str] = None, columns: Optional[List[Dict[str, Any]]] = None
|
|
522
|
-
):
|
|
545
|
+
) -> str:
|
|
523
546
|
"""
|
|
524
547
|
>>> schema = ''
|
|
525
548
|
>>> engine_full_from_dict('wadus', {}, schema=schema)
|
|
@@ -610,20 +633,10 @@ def engine_full_from_dict(
|
|
|
610
633
|
'ReplacingMergeTree(updated_at) PARTITION BY (tuple()) ORDER BY (project_id) SETTINGS index_granularity = 32'
|
|
611
634
|
"""
|
|
612
635
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
engine_config = get_engine_config(engine)
|
|
616
|
-
name, (params, options) = engine_config
|
|
617
|
-
if columns is None and schema is not None:
|
|
618
|
-
columns = parse_table_structure(schema)
|
|
619
|
-
|
|
636
|
+
validate_engine_config(engine, args, schema=schema, columns=columns)
|
|
637
|
+
name, (params, options) = get_engine_config(engine)
|
|
620
638
|
engine_settings = {key.replace("engine_", ""): value for key, value in args.items()}
|
|
621
|
-
|
|
622
|
-
for arg in engine_settings:
|
|
623
|
-
if not hasattr(TableDetails, arg):
|
|
624
|
-
raise ValueError(f"engine_{arg} is not a valid option")
|
|
625
|
-
|
|
626
|
-
return build_engine(name, columns, params, options, engine_settings)
|
|
639
|
+
return build_engine(name, params, options, engine_settings)
|
|
627
640
|
|
|
628
641
|
|
|
629
642
|
def engine_params_from_engine_full(engine_full: str) -> Dict[str, Any]:
|
|
@@ -699,8 +712,7 @@ def ttl_from_engine(engine: str) -> Optional[str]:
|
|
|
699
712
|
return None
|
|
700
713
|
settings_array = engine.split(" SETTINGS ")
|
|
701
714
|
settings = " SETTINGS " + settings_array[1] if len(settings_array) > 1 else None
|
|
702
|
-
|
|
703
|
-
return ttl
|
|
715
|
+
return ttl_array[1][: -(len(settings))] if settings else ttl_array[1]
|
|
704
716
|
|
|
705
717
|
|
|
706
718
|
def ttl_condition_from_engine_full(engine_full: Optional[str]) -> Optional[str]:
|
|
@@ -266,14 +266,13 @@ class TinyB:
|
|
|
266
266
|
|
|
267
267
|
async def alter_tokens(self, name: str, scopes: List[str]):
|
|
268
268
|
if not scopes:
|
|
269
|
-
return
|
|
269
|
+
return None
|
|
270
270
|
scopes_url: str = "&".join([f"scope={scope}" for scope in scopes])
|
|
271
271
|
url = f"/v0/tokens/{name}"
|
|
272
272
|
if len(url + "?" + scopes_url) > TinyB.MAX_GET_LENGTH:
|
|
273
273
|
return await self._req(url, method="PUT", data=scopes_url)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
return await self._req(url, method="PUT", data="")
|
|
274
|
+
url = url + "?" + scopes_url
|
|
275
|
+
return await self._req(url, method="PUT", data="")
|
|
277
276
|
|
|
278
277
|
async def datasources(self, branch: Optional[str] = None, used_by: bool = False) -> List[Dict[str, Any]]:
|
|
279
278
|
params = {}
|
|
@@ -294,16 +293,13 @@ class TinyB:
|
|
|
294
293
|
return await self._req(f"/v0/variables/{name}")
|
|
295
294
|
|
|
296
295
|
async def create_secret(self, name: str, value: str):
|
|
297
|
-
|
|
298
|
-
return response
|
|
296
|
+
return await self._req("/v0/variables", method="POST", data={"name": name, "value": value})
|
|
299
297
|
|
|
300
298
|
async def update_secret(self, name: str, value: str):
|
|
301
|
-
|
|
302
|
-
return response
|
|
299
|
+
return await self._req(f"/v0/variables/{name}", method="PUT", data={"value": value})
|
|
303
300
|
|
|
304
301
|
async def delete_secret(self, name: str):
|
|
305
|
-
|
|
306
|
-
return response
|
|
302
|
+
return await self._req(f"/v0/variables/{name}", method="DELETE")
|
|
307
303
|
|
|
308
304
|
async def get_connections(self, service: Optional[str] = None):
|
|
309
305
|
params = {}
|
|
@@ -412,6 +408,16 @@ class TinyB:
|
|
|
412
408
|
format: str = "csv",
|
|
413
409
|
replace_options: Optional[Set[str]] = None,
|
|
414
410
|
) -> Dict[str, Any]:
|
|
411
|
+
if mode in ("append", "replace"):
|
|
412
|
+
return await self.datasource_append_url(
|
|
413
|
+
table_name,
|
|
414
|
+
url,
|
|
415
|
+
mode=mode,
|
|
416
|
+
sql_condition=sql_condition,
|
|
417
|
+
format=format,
|
|
418
|
+
replace_options=replace_options,
|
|
419
|
+
)
|
|
420
|
+
|
|
415
421
|
params = {"name": table_name, "url": url, "mode": mode, "debug": "blocks_block_log", "format": format}
|
|
416
422
|
|
|
417
423
|
if sql_condition:
|
|
@@ -428,6 +434,33 @@ class TinyB:
|
|
|
428
434
|
|
|
429
435
|
return await self.wait_for_job(res["id"], status_callback, backoff_multiplier=1.5, maximum_backoff_seconds=20)
|
|
430
436
|
|
|
437
|
+
async def datasource_append_url(
|
|
438
|
+
self,
|
|
439
|
+
datasource_name: str,
|
|
440
|
+
url: str,
|
|
441
|
+
mode: str = "append",
|
|
442
|
+
sql_condition: Optional[str] = None,
|
|
443
|
+
format: str = "csv",
|
|
444
|
+
replace_options: Optional[Set[str]] = None,
|
|
445
|
+
) -> Dict[str, Any]:
|
|
446
|
+
params = {"format": format, "url": url}
|
|
447
|
+
if sql_condition:
|
|
448
|
+
params["replace_condition"] = sql_condition
|
|
449
|
+
if replace_options:
|
|
450
|
+
for option in replace_options:
|
|
451
|
+
params[option] = "true"
|
|
452
|
+
|
|
453
|
+
res = await self._req(
|
|
454
|
+
f"/v1/datasources/{quote(datasource_name, safe='')}/{mode}?{urlencode(params, safe='')}",
|
|
455
|
+
method="POST",
|
|
456
|
+
data=b"",
|
|
457
|
+
)
|
|
458
|
+
if not isinstance(res, dict):
|
|
459
|
+
raise RuntimeError("We couldn't confirm that your import started. Please try again.")
|
|
460
|
+
if "error" in res:
|
|
461
|
+
raise Exception(res["error"])
|
|
462
|
+
return res
|
|
463
|
+
|
|
431
464
|
async def datasource_delete(self, datasource_name: str, force: bool = False, dry_run: bool = False):
|
|
432
465
|
params = {"force": "true" if force else "false", "dry_run": "true" if dry_run else "false"}
|
|
433
466
|
return await self._req(f"/v0/datasources/{datasource_name}?{urlencode(params)}", method="DELETE")
|
|
@@ -577,8 +610,7 @@ class TinyB:
|
|
|
577
610
|
node_name = node["params"]["name"] if node.get("params", None) else node["name"]
|
|
578
611
|
if datasource_name:
|
|
579
612
|
params["datasource"] = datasource_name
|
|
580
|
-
|
|
581
|
-
return response
|
|
613
|
+
return await self._req(f"/v0/pipes/{pipe_name}/nodes/{node_name}/analysis?{urlencode(params)}")
|
|
582
614
|
|
|
583
615
|
async def populate_node(
|
|
584
616
|
self,
|
|
@@ -600,10 +632,7 @@ class TinyB:
|
|
|
600
632
|
params.update({"populate_condition": populate_condition})
|
|
601
633
|
if on_demand_compute:
|
|
602
634
|
params.update({"on_demand_compute": "true"})
|
|
603
|
-
|
|
604
|
-
f"/v0/pipes/{pipe_name}/nodes/{node_name}/population?{urlencode(params)}", method="POST"
|
|
605
|
-
)
|
|
606
|
-
return response
|
|
635
|
+
return await self._req(f"/v0/pipes/{pipe_name}/nodes/{node_name}/population?{urlencode(params)}", method="POST")
|
|
607
636
|
|
|
608
637
|
async def pipes(self, branch=None, dependencies: bool = False, node_attrs=None, attrs=None) -> List[Dict[str, Any]]:
|
|
609
638
|
params = {
|
|
@@ -635,9 +664,8 @@ class TinyB:
|
|
|
635
664
|
query_string = urlencode(params)
|
|
636
665
|
if len(url + "?" + query_string) > TinyB.MAX_GET_LENGTH:
|
|
637
666
|
return await self._req(f"/v0/pipes/{pipe_name_or_uid}.{format}", method="POST", data=params)
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return await self._req(url)
|
|
667
|
+
url = url + "?" + query_string
|
|
668
|
+
return await self._req(url)
|
|
641
669
|
|
|
642
670
|
async def pipe_create(self, pipe_name: str, sql: str):
|
|
643
671
|
return await self._req(
|
|
@@ -726,8 +754,7 @@ class TinyB:
|
|
|
726
754
|
|
|
727
755
|
if len(sql) > TinyB.MAX_GET_LENGTH:
|
|
728
756
|
return await self._req(f"/v0/sql?{urlencode(params)}", data=sql, method="POST")
|
|
729
|
-
|
|
730
|
-
return await self._req(f"/v0/sql?q={quote(sql, safe='')}&{urlencode(params)}")
|
|
757
|
+
return await self._req(f"/v0/sql?q={quote(sql, safe='')}&{urlencode(params)}")
|
|
731
758
|
|
|
732
759
|
async def jobs(self, status=None):
|
|
733
760
|
jobs = (await self._req("/v0/jobs"))["jobs"]
|
|
@@ -922,7 +949,7 @@ class TinyB:
|
|
|
922
949
|
|
|
923
950
|
async def add_workspaces_to_organization(self, organization_id: str, workspace_ids: List[str]):
|
|
924
951
|
if not workspace_ids:
|
|
925
|
-
return
|
|
952
|
+
return None
|
|
926
953
|
return await self._req(
|
|
927
954
|
f"/v0/organizations/{organization_id}/workspaces",
|
|
928
955
|
method="PUT",
|
|
@@ -1105,8 +1132,7 @@ class TinyB:
|
|
|
1105
1132
|
from tinybird.sql_toolset import format_sql
|
|
1106
1133
|
|
|
1107
1134
|
return format_sql(sql)
|
|
1108
|
-
|
|
1109
|
-
return await self._sql_get_format_remote(sql, with_clickhouse_format)
|
|
1135
|
+
return await self._sql_get_format_remote(sql, with_clickhouse_format)
|
|
1110
1136
|
except ModuleNotFoundError:
|
|
1111
1137
|
return await self._sql_get_format_remote(sql, with_clickhouse_format)
|
|
1112
1138
|
|
|
@@ -1168,8 +1194,7 @@ class TinyB:
|
|
|
1168
1194
|
return next((connector for connector in result["connectors"] if connector_equals(connector, kwargs)), None)
|
|
1169
1195
|
|
|
1170
1196
|
async def regions(self):
|
|
1171
|
-
|
|
1172
|
-
return regions
|
|
1197
|
+
return await self._req("/v0/regions")
|
|
1173
1198
|
|
|
1174
1199
|
async def datasource_query_copy(self, datasource_name: str, sql_query: str):
|
|
1175
1200
|
params = {"copy_to": datasource_name}
|