tinybird 0.0.1.dev290__tar.gz → 0.0.1.dev292__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.
Potentially problematic release.
This version of tinybird might be problematic. Click here for more details.
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/PKG-INFO +1 -1
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/context.py +3 -2
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/datafile/common.py +2 -2
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/sql.py +30 -22
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/__cli__.py +2 -2
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/agent.py +10 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/explore_agent.py +5 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/mock_agent.py +5 -1
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/prompts.py +49 -2
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/run_command.py +9 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/cli.py +26 -3
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/diff.py +2 -2
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/pull.py +51 -38
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/deployment_common.py +8 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/project.py +10 -1
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird.egg-info/PKG-INFO +1 -1
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/setup.cfg +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/__cli__.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/check_pypi.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/client.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/config.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/connectors.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/datatypes.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/git_settings.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/prompts.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/service_datasources.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/sql_template.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/sql_toolset.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/syncasync.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/cli.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/client.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/config.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/__init__.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/animations.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/banner.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/command_agent.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/compactor.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/file_agent.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/memory.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/models.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/testing_agent.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/__init__.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/analyze.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/append.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/build.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/datafile.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/deploy.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/deploy_check.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/diff_resource.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/execute_query.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/file.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/get_endpoint_stats.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/get_openapi_definition.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/mock.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/plan.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/request_endpoint.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/secret.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/test.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/utils.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/build.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/build_common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/config.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/create.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/playground.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/dev_server.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/info.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/infra.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/job.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/local.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/login.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/mock.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/mock_common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/open.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/shell.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/table.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/test.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/token.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tornado_template.py +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -3,10 +3,11 @@ from typing import TYPE_CHECKING
|
|
|
3
3
|
|
|
4
4
|
# Avoid circular import error
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
|
-
from
|
|
6
|
+
from hfi.hfi_workspace_data import HfiWorkspaceData
|
|
7
|
+
|
|
7
8
|
|
|
8
9
|
workspace_id: ContextVar[str] = ContextVar("workspace_id")
|
|
9
|
-
|
|
10
|
+
hfi_workspace_data: ContextVar["HfiWorkspaceData"] = ContextVar("hfi_workspace_data")
|
|
10
11
|
table_id: ContextVar[str] = ContextVar("table_id")
|
|
11
12
|
hfi_frequency: ContextVar[float] = ContextVar("hfi_frequency")
|
|
12
13
|
hfi_frequency_gatherer: ContextVar[float] = ContextVar("hfi_frequency_gatherer")
|
|
@@ -1870,7 +1870,7 @@ def parse(
|
|
|
1870
1870
|
|
|
1871
1871
|
for entries in args:
|
|
1872
1872
|
# In case they specify multiple workspaces, handle both line-separated and comma-separated values
|
|
1873
|
-
lines = entries.splitlines()
|
|
1873
|
+
lines = _unquote(entries).splitlines()
|
|
1874
1874
|
for line in lines:
|
|
1875
1875
|
# Split by comma and strip whitespace from each workspace name
|
|
1876
1876
|
workspaces = [workspace.strip().rstrip(",") for workspace in line.split(",") if workspace.strip()]
|
|
@@ -1957,7 +1957,7 @@ def parse(
|
|
|
1957
1957
|
"import_query": assign_var("import_query"), # Deprecated, BQ and SFK
|
|
1958
1958
|
"import_table_arn": assign_var("import_table_arn"), # Only for DynamoDB
|
|
1959
1959
|
"import_export_bucket": assign_var("import_export_bucket"), # For DynamoDB
|
|
1960
|
-
"shared_with": shared_with,
|
|
1960
|
+
"shared_with": shared_with,
|
|
1961
1961
|
"export_service": export_service, # Deprecated
|
|
1962
1962
|
"forward_query": sql("forward_query"),
|
|
1963
1963
|
"backfill": assign_var("backfill", allowed_values={"skip"}),
|
|
@@ -7,6 +7,9 @@ from typing import Any, Dict, Iterable, List, Optional
|
|
|
7
7
|
|
|
8
8
|
valid_chars_name: str = string.ascii_letters + string.digits + "._`*<>+-'"
|
|
9
9
|
valid_chars_fn: str = valid_chars_name + "[](),=!?:/ \n\t\r"
|
|
10
|
+
# Use sets for O(1) membership checks in hot loops
|
|
11
|
+
_VALID_CHARS_NAME_SET = set(valid_chars_name)
|
|
12
|
+
_VALID_CHARS_FN_SET = set(valid_chars_fn)
|
|
10
13
|
|
|
11
14
|
INDEX_WHITELIST = ["minmax", "set", "bloom_filter", "ngrambf_v1", "tokenbf_v1"]
|
|
12
15
|
INDEX_SUPPORTED_TYPES = {
|
|
@@ -28,6 +31,15 @@ INDEX_SUPPORTED_TYPES = {
|
|
|
28
31
|
"ngrambf_v1": ["String", "FixedString", "Map"],
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
# Precompiled regexes used across functions to avoid recompilation overhead
|
|
35
|
+
_RE_FORMAT = re.compile(r"\s+format\s+(\w+)\s*$", re.IGNORECASE)
|
|
36
|
+
_RE_REMOVE_FORMAT = re.compile(r"\s+(format)\s+(\w+)\s*$", re.IGNORECASE)
|
|
37
|
+
_RE_TRY_FIX_NULLABLE_SAF = re.compile(r"SimpleAggregateFunction\((\w+),\s*(?!(?:Nullable))([\w,.()]+)\)")
|
|
38
|
+
_RE_INDEX_ENTRY = re.compile(
|
|
39
|
+
r"(\w+)\s+([\w\s*\[\]\*\(\),\'\"-><.]+)\s+TYPE\s+(\w+)(?:\(([\w\s*.,]+)\))?(?:\s+GRANULARITY\s+(\d+))?"
|
|
40
|
+
)
|
|
41
|
+
_RE_REPLICATED_MT = re.compile(r"Replicated(.*)MergeTree\(([^\)]*)\)(.*)")
|
|
42
|
+
|
|
31
43
|
|
|
32
44
|
@dataclass
|
|
33
45
|
class TableIndex:
|
|
@@ -137,10 +149,9 @@ def get_format(sql: str) -> Optional[str]:
|
|
|
137
149
|
>>> get_format('select * from test formAt JSON')
|
|
138
150
|
'JSON'
|
|
139
151
|
"""
|
|
140
|
-
FORMAT_RE = r"\s+format\s+(\w+)\s*$"
|
|
141
152
|
sql = sql.strip()
|
|
142
|
-
|
|
143
|
-
return
|
|
153
|
+
match = _RE_FORMAT.findall(sql)
|
|
154
|
+
return match[0] if match else None
|
|
144
155
|
|
|
145
156
|
|
|
146
157
|
def get_format_group(sql: str) -> str:
|
|
@@ -151,10 +162,9 @@ def get_format_group(sql: str) -> str:
|
|
|
151
162
|
>>> get_format_group('select * from test formAt JSON')
|
|
152
163
|
' formAt JSON'
|
|
153
164
|
"""
|
|
154
|
-
FORMAT_RE = r"\s+format\s+(\w+)\s*$"
|
|
155
165
|
sql = sql.strip()
|
|
156
|
-
|
|
157
|
-
return
|
|
166
|
+
match = _RE_FORMAT.search(sql)
|
|
167
|
+
return match.group() if match else ""
|
|
158
168
|
|
|
159
169
|
|
|
160
170
|
def wrap_finalize_aggregation(sql: str, describe_result: Dict[str, Any], fm_group: Optional[str] = None) -> str:
|
|
@@ -186,9 +196,8 @@ def remove_format(sql: str) -> str:
|
|
|
186
196
|
>>> remove_format('select * from test formAt JSON')
|
|
187
197
|
'select * from test'
|
|
188
198
|
"""
|
|
189
|
-
FORMAT_RE = r"\s+(format)\s+(\w+)\s*$"
|
|
190
199
|
sql = sql.strip()
|
|
191
|
-
return
|
|
200
|
+
return _RE_REMOVE_FORMAT.sub("", sql)
|
|
192
201
|
|
|
193
202
|
|
|
194
203
|
def col_name(name: str, backquotes: bool = True) -> str:
|
|
@@ -220,7 +229,7 @@ def try_to_fix_nullable_in_simple_aggregating_function(t: str) -> Optional[str]:
|
|
|
220
229
|
# as it is done with other aggregate functions.
|
|
221
230
|
# If not, the aggregation could return incorrect results.
|
|
222
231
|
result = None
|
|
223
|
-
if match :=
|
|
232
|
+
if match := _RE_TRY_FIX_NULLABLE_SAF.search(t):
|
|
224
233
|
fn = match.group(1)
|
|
225
234
|
inner_type = match.group(2)
|
|
226
235
|
result = f"SimpleAggregateFunction({fn}, Nullable({inner_type}))"
|
|
@@ -342,10 +351,7 @@ def parse_indexes_structure(indexes: Optional[List[str]]) -> List[TableIndex]:
|
|
|
342
351
|
if index.count("TYPE") != 1:
|
|
343
352
|
raise ValueError("invalid INDEX format. Usage: `name expr TYPE type_full GRANULARITY granularity`")
|
|
344
353
|
|
|
345
|
-
match =
|
|
346
|
-
r"(\w+)\s+([\w\s*\[\]\*\(\),\'\"-><.]+)\s+TYPE\s+(\w+)(?:\(([\w\s*.,]+)\))?(?:\s+GRANULARITY\s+(\d+))?",
|
|
347
|
-
index,
|
|
348
|
-
)
|
|
354
|
+
match = _RE_INDEX_ENTRY.match(index)
|
|
349
355
|
if match:
|
|
350
356
|
index_name, a, index_type, value, granularity = match.groups()
|
|
351
357
|
index_expr = f"{index_type}({value})" if value else index_type
|
|
@@ -552,7 +558,7 @@ def clean_comments(schema_to_clean: str) -> str:
|
|
|
552
558
|
if i + 1 < len(line) and line[i] == "-" and line[i + 1] == "-" and not inside_json_path:
|
|
553
559
|
return line[:i].strip()
|
|
554
560
|
|
|
555
|
-
if not inside_json_path and line
|
|
561
|
+
if not inside_json_path and line.startswith("`json:", i):
|
|
556
562
|
inside_json_path = True
|
|
557
563
|
elif inside_json_path and line[i] == "`":
|
|
558
564
|
inside_json_path = False
|
|
@@ -562,12 +568,12 @@ def clean_comments(schema_to_clean: str) -> str:
|
|
|
562
568
|
if schema_to_clean is None:
|
|
563
569
|
return schema_to_clean
|
|
564
570
|
|
|
565
|
-
|
|
571
|
+
out_lines: List[str] = []
|
|
566
572
|
for line in schema_to_clean.splitlines():
|
|
567
573
|
cleaned_line = clean_line_comments(line)
|
|
568
574
|
if cleaned_line:
|
|
569
|
-
|
|
570
|
-
return
|
|
575
|
+
out_lines.append(cleaned_line)
|
|
576
|
+
return "\n".join(out_lines).strip()
|
|
571
577
|
|
|
572
578
|
|
|
573
579
|
SyntaxExpr = namedtuple("SyntaxExpr", ["name", "regex"])
|
|
@@ -608,9 +614,9 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
608
614
|
|
|
609
615
|
# Find the first SyntaxExpr in lookup that matches the schema at the current offset
|
|
610
616
|
def lookahead_matches(lookup: Iterable) -> Optional[SyntaxExpr]:
|
|
617
|
+
# Use substring to preserve semantics of patterns anchored to end ($)
|
|
611
618
|
s = schema[i:]
|
|
612
|
-
|
|
613
|
-
return match
|
|
619
|
+
return next((x for x in lookup if x.regex.match(s)), None)
|
|
614
620
|
|
|
615
621
|
def advance_single_char() -> None:
|
|
616
622
|
nonlocal i, line, pos
|
|
@@ -647,7 +653,7 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
647
653
|
c = schema[i]
|
|
648
654
|
if c in " \t\r\n":
|
|
649
655
|
return schema[begin:i]
|
|
650
|
-
if c not in
|
|
656
|
+
if c not in _VALID_CHARS_NAME_SET:
|
|
651
657
|
raise ValueError(
|
|
652
658
|
format_parse_error(schema, i, pos, "wrong value, please check the schema syntax", line=line)
|
|
653
659
|
)
|
|
@@ -677,7 +683,9 @@ def _parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
677
683
|
context_stack.append("(")
|
|
678
684
|
elif context is None and lookahead_matches(lookup):
|
|
679
685
|
return schema[begin:i].strip(" \t\r\n")
|
|
680
|
-
elif (context is None and c not in
|
|
686
|
+
elif (context is None and c not in _VALID_CHARS_FN_SET) or (
|
|
687
|
+
context == "(" and c not in _VALID_CHARS_FN_SET
|
|
688
|
+
):
|
|
681
689
|
raise ValueError(
|
|
682
690
|
format_parse_error(schema, i, pos, "wrong value, please check the schema syntax", line=line)
|
|
683
691
|
)
|
|
@@ -884,7 +892,7 @@ def engine_replicated_to_local(engine: str) -> str:
|
|
|
884
892
|
if "Replicated" not in engine:
|
|
885
893
|
return engine
|
|
886
894
|
|
|
887
|
-
return
|
|
895
|
+
return _RE_REPLICATED_MT.sub(_replace, engine.strip())
|
|
888
896
|
|
|
889
897
|
|
|
890
898
|
def engine_patch_replicated_engine(engine: str, engine_full: Optional[str], new_table_name: str) -> Optional[str]:
|
|
@@ -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__ = '0.0.1.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '0.0.1.dev292'
|
|
8
|
+
__revision__ = '78dba1d'
|
|
@@ -34,10 +34,12 @@ from tinybird.tb.modules.agent.mock_agent import MockAgent
|
|
|
34
34
|
from tinybird.tb.modules.agent.models import create_model
|
|
35
35
|
from tinybird.tb.modules.agent.prompts import (
|
|
36
36
|
agent_system_prompt,
|
|
37
|
+
fixtures_prompt,
|
|
37
38
|
load_custom_project_rules,
|
|
38
39
|
resources_prompt,
|
|
39
40
|
secrets_prompt,
|
|
40
41
|
service_datasources_prompt,
|
|
42
|
+
vendor_files_prompt,
|
|
41
43
|
)
|
|
42
44
|
from tinybird.tb.modules.agent.testing_agent import TestingAgent
|
|
43
45
|
from tinybird.tb.modules.agent.tools.analyze import analyze_file, analyze_url
|
|
@@ -322,6 +324,14 @@ class TinybirdAgent:
|
|
|
322
324
|
def get_project_files(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
323
325
|
return resources_prompt(self.project)
|
|
324
326
|
|
|
327
|
+
@self.agent.instructions
|
|
328
|
+
def get_vendor_files(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
329
|
+
return vendor_files_prompt(self.project)
|
|
330
|
+
|
|
331
|
+
@self.agent.instructions
|
|
332
|
+
def get_fixture_files(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
333
|
+
return fixtures_prompt(self.project)
|
|
334
|
+
|
|
325
335
|
@self.agent.instructions
|
|
326
336
|
def get_service_datasources(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
327
337
|
return service_datasources_prompt()
|
|
@@ -12,6 +12,7 @@ from tinybird.tb.modules.agent.prompts import (
|
|
|
12
12
|
resources_prompt,
|
|
13
13
|
service_datasources_prompt,
|
|
14
14
|
tone_and_style_instructions,
|
|
15
|
+
vendor_files_prompt,
|
|
15
16
|
)
|
|
16
17
|
from tinybird.tb.modules.agent.tools.diff_resource import diff_resource
|
|
17
18
|
from tinybird.tb.modules.agent.tools.execute_query import execute_query
|
|
@@ -76,6 +77,10 @@ Once you finish the task, return a valid response for the task to complete.
|
|
|
76
77
|
def get_project_files(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
77
78
|
return resources_prompt(self.project)
|
|
78
79
|
|
|
80
|
+
@self.agent.instructions
|
|
81
|
+
def get_vendor_files(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
82
|
+
return vendor_files_prompt(self.project)
|
|
83
|
+
|
|
79
84
|
@self.agent.instructions
|
|
80
85
|
def get_service_datasources(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
81
86
|
return service_datasources_prompt()
|
|
@@ -6,7 +6,7 @@ from pydantic_ai.usage import Usage
|
|
|
6
6
|
|
|
7
7
|
from tinybird.tb.modules.agent.animations import ThinkingAnimation
|
|
8
8
|
from tinybird.tb.modules.agent.models import create_model
|
|
9
|
-
from tinybird.tb.modules.agent.prompts import resources_prompt
|
|
9
|
+
from tinybird.tb.modules.agent.prompts import fixtures_prompt, resources_prompt
|
|
10
10
|
from tinybird.tb.modules.agent.tools.mock import generate_mock_fixture
|
|
11
11
|
from tinybird.tb.modules.agent.utils import TinybirdAgentContext
|
|
12
12
|
from tinybird.tb.modules.project import Project
|
|
@@ -194,6 +194,10 @@ Today is {datetime.now().strftime("%Y-%m-%d")}
|
|
|
194
194
|
def get_project_files(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
195
195
|
return resources_prompt(self.project)
|
|
196
196
|
|
|
197
|
+
@self.agent.instructions
|
|
198
|
+
def get_fixture_files(ctx: RunContext[TinybirdAgentContext]) -> str:
|
|
199
|
+
return fixtures_prompt(self.project)
|
|
200
|
+
|
|
197
201
|
def run(self, task: str, deps: TinybirdAgentContext, usage: Usage):
|
|
198
202
|
result = self.agent.run_sync(
|
|
199
203
|
task,
|
|
@@ -35,8 +35,10 @@ available_commands = [
|
|
|
35
35
|
"`tb sink ls`: List all sinks",
|
|
36
36
|
"`tb workspace current`: Show the current workspace",
|
|
37
37
|
"`tb workspace clear --yes`: Delete all resources in the workspace (Only available in Tinybird Local)",
|
|
38
|
+
"`tb workspace ls`: List all workspaces",
|
|
38
39
|
"`tb local start --skip-new-version`: Start Tinybird Local container in non-interactive mode",
|
|
39
40
|
"`tb local restart --skip-new-version --yes`: Restart Tinybird Local container in non-interactive mode",
|
|
41
|
+
"`tb pull --only-vendored`: Pull only the vendored datasources from other workspaces",
|
|
40
42
|
]
|
|
41
43
|
|
|
42
44
|
plan_instructions = """
|
|
@@ -166,7 +168,6 @@ SQL >
|
|
|
166
168
|
|
|
167
169
|
def resources_prompt(project: Project) -> str:
|
|
168
170
|
files = project.get_project_files()
|
|
169
|
-
fixture_files = project.get_fixture_files()
|
|
170
171
|
|
|
171
172
|
resources_content = "# Existing resources in the project:\n"
|
|
172
173
|
if files:
|
|
@@ -184,7 +185,36 @@ def resources_prompt(project: Project) -> str:
|
|
|
184
185
|
else:
|
|
185
186
|
resources_content += "No resources found"
|
|
186
187
|
|
|
188
|
+
return resources_content
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def vendor_files_prompt(project: Project) -> str:
|
|
192
|
+
files = project.get_vendored_files()
|
|
193
|
+
content = "# Datasources shared from other workspaces:\n"
|
|
194
|
+
if files:
|
|
195
|
+
resources: list[dict[str, Any]] = []
|
|
196
|
+
for filename in files:
|
|
197
|
+
file_path = Path(filename)
|
|
198
|
+
workspace_name = file_path.parent.parent.name
|
|
199
|
+
resource = {
|
|
200
|
+
"path": str(file_path.relative_to(project.folder)),
|
|
201
|
+
"type": get_resource_type(file_path),
|
|
202
|
+
"name": f"{workspace_name}.{file_path.stem}",
|
|
203
|
+
"content": file_path.read_text(),
|
|
204
|
+
"origin_workspace": workspace_name,
|
|
205
|
+
}
|
|
206
|
+
resources.append(resource)
|
|
207
|
+
content += format_as_xml(resources, root_tag="resources", item_tag="resource")
|
|
208
|
+
else:
|
|
209
|
+
content += "No datasources shared from other workspaces"
|
|
210
|
+
|
|
211
|
+
return content
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def fixtures_prompt(project: Project) -> str:
|
|
215
|
+
fixture_files = project.get_fixture_files()
|
|
187
216
|
fixture_content = "# Fixture files in the project:\n"
|
|
217
|
+
|
|
188
218
|
if fixture_files:
|
|
189
219
|
fixtures: list[dict[str, Any]] = []
|
|
190
220
|
for filename in fixture_files:
|
|
@@ -199,7 +229,7 @@ def resources_prompt(project: Project) -> str:
|
|
|
199
229
|
else:
|
|
200
230
|
fixture_content += "No fixture files found"
|
|
201
231
|
|
|
202
|
-
return
|
|
232
|
+
return fixture_content
|
|
203
233
|
|
|
204
234
|
|
|
205
235
|
def service_datasources_prompt() -> str:
|
|
@@ -954,6 +984,23 @@ After changes have been deployed and promoted, if you want to deploy other chang
|
|
|
954
984
|
If after running a deployment, the error contains a recommended forward query, use it to update the .datasource file.
|
|
955
985
|
</dev_notes>
|
|
956
986
|
|
|
987
|
+
## Sharing datasources with other workspaces
|
|
988
|
+
To share a Data Source, in the .datasource file you want to share, add the destination workspace(s). For example:
|
|
989
|
+
|
|
990
|
+
```
|
|
991
|
+
SHARED_WITH >
|
|
992
|
+
destination_workspace,
|
|
993
|
+
other_destination_workspace
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
## Working with shared datasources:
|
|
997
|
+
|
|
998
|
+
The following limitations apply to shared datasources:
|
|
999
|
+
- Shared datasources are read-only.
|
|
1000
|
+
- You can't share a shared datasource, only the original.
|
|
1001
|
+
- You can't check the quarantine of a shared datasource.
|
|
1002
|
+
- You can't create a Materialized View from a shared datasource.
|
|
1003
|
+
|
|
957
1004
|
# Working with any type of pipe file:
|
|
958
1005
|
{pipe_instructions}
|
|
959
1006
|
{pipe_example}
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/run_command.py
RENAMED
|
@@ -3,6 +3,7 @@ import subprocess
|
|
|
3
3
|
import click
|
|
4
4
|
from pydantic_ai import RunContext
|
|
5
5
|
|
|
6
|
+
from tinybird.tb.modules.agent.prompts import available_commands
|
|
6
7
|
from tinybird.tb.modules.agent.utils import (
|
|
7
8
|
AgentRunCancelled,
|
|
8
9
|
SubAgentRunCancelled,
|
|
@@ -20,6 +21,14 @@ def run_command(ctx: RunContext[TinybirdAgentContext], command: str):
|
|
|
20
21
|
command (str): The command to run. Required. Examples: `tb --local sql "select 1"`, `tb --cloud datasource ls`, `tb --help`
|
|
21
22
|
"""
|
|
22
23
|
try:
|
|
24
|
+
clean_commands = [cmd.split(":")[0].replace("`", "").split("[")[0] for cmd in available_commands]
|
|
25
|
+
available_commands_to_cloud = [f"tb --cloud {command.replace('tb ', '')}" for command in clean_commands]
|
|
26
|
+
available_commands_to_local = [f"tb --local {command.replace('tb ', '')}" for command in clean_commands]
|
|
27
|
+
all_commands = clean_commands + available_commands_to_cloud + available_commands_to_local
|
|
28
|
+
|
|
29
|
+
if not any(cmd.startswith(command) for cmd in all_commands):
|
|
30
|
+
raise SubAgentRunCancelled(f"Command {command} not found in the list of available commands")
|
|
31
|
+
|
|
23
32
|
ctx.deps.thinking_animation.stop()
|
|
24
33
|
force_confirmation = " deploy" in command.lower() or " truncate" in command.lower()
|
|
25
34
|
confirmation = show_confirmation(
|
|
@@ -212,16 +212,39 @@ def cli(
|
|
|
212
212
|
|
|
213
213
|
|
|
214
214
|
@cli.command(hidden=True)
|
|
215
|
+
@click.option("--only-vendored", is_flag=True, default=False, help="Only update vendored files")
|
|
215
216
|
@click.option("-f", "--force", is_flag=True, default=False, help="Override existing files")
|
|
216
217
|
@click.option("--fmt", is_flag=True, default=False, help="Format files before saving")
|
|
217
218
|
@click.pass_context
|
|
218
|
-
def pull(ctx: Context, force: bool, fmt: bool) -> None:
|
|
219
|
+
def pull(ctx: Context, only_vendored: bool, force: bool, fmt: bool) -> None:
|
|
219
220
|
"""Retrieve latest versions for project files from Tinybird."""
|
|
220
221
|
|
|
221
222
|
client = ctx.ensure_object(dict)["client"]
|
|
222
223
|
project = ctx.ensure_object(dict)["project"]
|
|
223
224
|
|
|
224
|
-
|
|
225
|
+
if only_vendored:
|
|
226
|
+
force = True
|
|
227
|
+
|
|
228
|
+
written_files = folder_pull(client, project.path, force, only_vendored=only_vendored, fmt=fmt)
|
|
229
|
+
|
|
230
|
+
if only_vendored:
|
|
231
|
+
for_user_to_delete = set(project.get_vendored_files()) - set(written_files)
|
|
232
|
+
if for_user_to_delete:
|
|
233
|
+
# TODO(eclbg): this prints the full path of the files. Let's print the relative path from the project root
|
|
234
|
+
display_paths = []
|
|
235
|
+
for full_path in for_user_to_delete:
|
|
236
|
+
try:
|
|
237
|
+
display_paths.append(str(Path(full_path).relative_to(project.path)))
|
|
238
|
+
except:
|
|
239
|
+
display_paths.append(full_path)
|
|
240
|
+
click.echo(
|
|
241
|
+
FeedbackManager.warning(
|
|
242
|
+
message=(
|
|
243
|
+
f"This workspace no longer has access to the following files: {display_paths}. "
|
|
244
|
+
"Please remove them manually to be able to deploy."
|
|
245
|
+
)
|
|
246
|
+
)
|
|
247
|
+
)
|
|
225
248
|
|
|
226
249
|
|
|
227
250
|
@cli.command()
|
|
@@ -392,7 +415,7 @@ def create_ctx_client(
|
|
|
392
415
|
if not command or command in commands_without_ctx_client:
|
|
393
416
|
return None
|
|
394
417
|
|
|
395
|
-
commands_always_cloud = ["
|
|
418
|
+
commands_always_cloud = ["infra"]
|
|
396
419
|
commands_always_local = ["build", "dev"]
|
|
397
420
|
command_always_test = ["test"]
|
|
398
421
|
|
|
@@ -121,12 +121,12 @@ def diff_command(
|
|
|
121
121
|
if filenames:
|
|
122
122
|
if len(filenames) == 1:
|
|
123
123
|
filenames = [filenames[0], *get_project_filenames(filenames[0])]
|
|
124
|
-
folder_pull(client, target_dir, True, verbose=False)
|
|
124
|
+
folder_pull(client, target_dir, True, only_vendored=False, verbose=False)
|
|
125
125
|
else:
|
|
126
126
|
filenames = get_project_filenames(".")
|
|
127
127
|
if verbose:
|
|
128
128
|
click.echo("Saving remote resources in .diff_tmp folder.\n")
|
|
129
|
-
folder_pull(client, target_dir, True, verbose=verbose, progress_bar=progress_bar)
|
|
129
|
+
folder_pull(client, target_dir, True, verbose=verbose, only_vendored=False, progress_bar=progress_bar)
|
|
130
130
|
|
|
131
131
|
remote_datasources: List[Dict[str, Any]] = client.datasources()
|
|
132
132
|
remote_pipes: List[Dict[str, Any]] = client.pipes()
|
|
@@ -13,10 +13,11 @@ def folder_pull(
|
|
|
13
13
|
client: TinyB,
|
|
14
14
|
folder: str,
|
|
15
15
|
force: bool,
|
|
16
|
+
only_vendored: bool,
|
|
16
17
|
verbose: bool = True,
|
|
17
18
|
progress_bar: bool = False,
|
|
18
19
|
fmt: bool = False,
|
|
19
|
-
):
|
|
20
|
+
) -> list[str]:
|
|
20
21
|
def get_file_folder(extension: str, resource_type: Optional[str]):
|
|
21
22
|
if extension == "datasource":
|
|
22
23
|
return "datasources"
|
|
@@ -40,8 +41,8 @@ def folder_pull(
|
|
|
40
41
|
get_resource_function: str,
|
|
41
42
|
progress_bar: bool = False,
|
|
42
43
|
fmt: bool = False,
|
|
43
|
-
):
|
|
44
|
-
def write_resource(k: dict[str, Any]):
|
|
44
|
+
) -> list[Path]:
|
|
45
|
+
def write_resource(k: dict[str, Any]) -> Optional[Path]:
|
|
45
46
|
name = f"{k['name']}.{extension}"
|
|
46
47
|
try:
|
|
47
48
|
resource = getattr(client, get_resource_function)(k["name"])
|
|
@@ -72,59 +73,71 @@ def folder_pull(
|
|
|
72
73
|
with open(f, "w") as fd:
|
|
73
74
|
if resource_to_write:
|
|
74
75
|
fd.write(resource_to_write)
|
|
76
|
+
return f
|
|
75
77
|
else:
|
|
76
78
|
if verbose:
|
|
77
79
|
click.echo(FeedbackManager.info_skip_already_exists())
|
|
80
|
+
return None
|
|
78
81
|
except Exception as e:
|
|
79
82
|
raise click.ClickException(FeedbackManager.error_exception(error=e))
|
|
80
83
|
|
|
81
84
|
if progress_bar:
|
|
85
|
+
written_files = []
|
|
82
86
|
with click.progressbar(resources, label=f"Pulling {extension}s") as resources: # type: ignore
|
|
83
87
|
for k in resources:
|
|
84
|
-
write_resource(k)
|
|
88
|
+
written_file = write_resource(k)
|
|
89
|
+
if written_file:
|
|
90
|
+
written_files.append(written_file)
|
|
85
91
|
else:
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
written_files = list(filter(None, (write_resource(k) for k in resources)))
|
|
93
|
+
|
|
94
|
+
return written_files
|
|
88
95
|
|
|
89
96
|
try:
|
|
90
97
|
datasources = client.datasources()
|
|
91
98
|
pipes = client.pipes()
|
|
92
99
|
connections = client.connections()
|
|
93
100
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
101
|
+
if only_vendored:
|
|
102
|
+
written_files = write_files(
|
|
103
|
+
resources=[ds for ds in datasources if "shared_from" in ds],
|
|
104
|
+
extension="datasource",
|
|
105
|
+
get_resource_function="datasource_file",
|
|
106
|
+
progress_bar=progress_bar,
|
|
107
|
+
fmt=fmt,
|
|
108
|
+
)
|
|
109
|
+
else:
|
|
110
|
+
written_files = []
|
|
111
|
+
written_files.extend(
|
|
112
|
+
write_files(
|
|
113
|
+
resources=datasources,
|
|
114
|
+
extension="datasource",
|
|
115
|
+
get_resource_function="datasource_file",
|
|
116
|
+
progress_bar=progress_bar,
|
|
117
|
+
fmt=fmt,
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
written_files.extend(
|
|
121
|
+
write_files(
|
|
122
|
+
resources=pipes,
|
|
123
|
+
extension="pipe",
|
|
124
|
+
get_resource_function="pipe_file",
|
|
125
|
+
progress_bar=progress_bar,
|
|
126
|
+
fmt=fmt,
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
written_files.extend(
|
|
130
|
+
write_files(
|
|
131
|
+
resources=connections,
|
|
132
|
+
extension="connection",
|
|
133
|
+
get_resource_function="connection_file",
|
|
134
|
+
progress_bar=progress_bar,
|
|
135
|
+
fmt=fmt,
|
|
136
|
+
)
|
|
137
|
+
)
|
|
138
|
+
return [str(wf) for wf in written_files]
|
|
116
139
|
|
|
117
140
|
except AuthNoTokenException:
|
|
118
141
|
raise
|
|
119
142
|
except Exception as e:
|
|
120
143
|
raise click.ClickException(FeedbackManager.error_pull(error=str(e)))
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def _gather_with_concurrency(n, *tasks):
|
|
124
|
-
results = []
|
|
125
|
-
for task in tasks:
|
|
126
|
-
if callable(task):
|
|
127
|
-
results.append(task())
|
|
128
|
-
else:
|
|
129
|
-
results.append(task)
|
|
130
|
-
return results
|
|
@@ -222,6 +222,7 @@ def create_deployment(
|
|
|
222
222
|
# TODO: This code is duplicated in build_server.py
|
|
223
223
|
# Should be refactored to be shared
|
|
224
224
|
MULTIPART_BOUNDARY_DATA_PROJECT = "data_project://"
|
|
225
|
+
MULTIPART_BOUNDARY_DATA_PROJECT_VENDORED = "data_project_vendored://"
|
|
225
226
|
DATAFILE_TYPE_TO_CONTENT_TYPE = {
|
|
226
227
|
".datasource": "text/plain",
|
|
227
228
|
".pipe": "text/plain",
|
|
@@ -248,6 +249,13 @@ def create_deployment(
|
|
|
248
249
|
with open(file_path, "rb") as fd:
|
|
249
250
|
content_type = DATAFILE_TYPE_TO_CONTENT_TYPE.get(Path(file_path).suffix, "application/unknown")
|
|
250
251
|
files.append((MULTIPART_BOUNDARY_DATA_PROJECT, (relative_path, fd.read().decode("utf-8"), content_type)))
|
|
252
|
+
for file_path in project.get_vendored_files():
|
|
253
|
+
relative_path = Path(file_path).relative_to(project.path).as_posix()
|
|
254
|
+
with open(file_path, "rb") as fd:
|
|
255
|
+
content_type = DATAFILE_TYPE_TO_CONTENT_TYPE.get(Path(file_path).suffix, "application/unknown")
|
|
256
|
+
files.append(
|
|
257
|
+
(MULTIPART_BOUNDARY_DATA_PROJECT_VENDORED, (relative_path, fd.read().decode("utf-8"), content_type))
|
|
258
|
+
)
|
|
251
259
|
|
|
252
260
|
deployment = None
|
|
253
261
|
try:
|
|
@@ -37,11 +37,13 @@ class Project:
|
|
|
37
37
|
def has_deeper_level(self) -> bool:
|
|
38
38
|
"""Check if there are folders with depth greater than max_depth in project path.
|
|
39
39
|
|
|
40
|
+
Does not consider the vendor directory.
|
|
41
|
+
|
|
40
42
|
Returns:
|
|
41
43
|
bool: True if there are folders deeper than max_depth, False otherwise
|
|
42
44
|
"""
|
|
43
45
|
for obj in glob.glob(f"{self.path}{'/*' * (self.max_depth - 1)}/*", recursive=False):
|
|
44
|
-
if Path(obj).is_dir():
|
|
46
|
+
if Path(obj).is_dir() and self.vendor_path not in obj:
|
|
45
47
|
return True
|
|
46
48
|
return False
|
|
47
49
|
|
|
@@ -54,6 +56,13 @@ class Project:
|
|
|
54
56
|
project_files.append(project_file)
|
|
55
57
|
return project_files
|
|
56
58
|
|
|
59
|
+
def get_vendored_files(self) -> List[str]:
|
|
60
|
+
vendored_files: List[str] = []
|
|
61
|
+
for extension in self.extensions:
|
|
62
|
+
for level in range(3):
|
|
63
|
+
vendored_files.extend(glob.glob(f"{self.vendor_path}{'/*' * level}/*.{extension}", recursive=True))
|
|
64
|
+
return vendored_files
|
|
65
|
+
|
|
57
66
|
def get_fixture_files(self) -> List[str]:
|
|
58
67
|
fixture_files: List[str] = []
|
|
59
68
|
for extension in [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/deploy_check.py
RENAMED
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/diff_resource.py
RENAMED
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/execute_query.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/agent/tools/request_endpoint.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/build_common.py
RENAMED
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/build_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/format_common.py
RENAMED
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/format_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/datafile/pipe_checker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb/modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/tinyunit/tinyunit.py
RENAMED
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev290 → tinybird-0.0.1.dev292}/tinybird/tb_cli_modules/workspace_members.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|