tinybird 0.0.1.dev5__py3-none-any.whl → 0.0.1.dev7__py3-none-any.whl

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.

Files changed (55) hide show
  1. tinybird/__cli__.py +7 -8
  2. tinybird/tb/cli.py +28 -0
  3. tinybird/{tb_cli_modules → tb/modules}/auth.py +5 -5
  4. tinybird/{tb_cli_modules → tb/modules}/branch.py +5 -25
  5. tinybird/{tb_cli_modules → tb/modules}/build.py +10 -21
  6. tinybird/tb/modules/cicd.py +271 -0
  7. tinybird/{tb_cli_modules → tb/modules}/cli.py +20 -140
  8. tinybird/tb/modules/common.py +2110 -0
  9. tinybird/tb/modules/config.py +352 -0
  10. tinybird/{tb_cli_modules → tb/modules}/connection.py +4 -4
  11. tinybird/{tb_cli_modules → tb/modules}/create.py +20 -20
  12. tinybird/tb/modules/datafile/build.py +2103 -0
  13. tinybird/tb/modules/datafile/build_common.py +118 -0
  14. tinybird/tb/modules/datafile/build_datasource.py +403 -0
  15. tinybird/tb/modules/datafile/build_pipe.py +648 -0
  16. tinybird/tb/modules/datafile/common.py +897 -0
  17. tinybird/tb/modules/datafile/diff.py +197 -0
  18. tinybird/tb/modules/datafile/exceptions.py +23 -0
  19. tinybird/tb/modules/datafile/format_common.py +66 -0
  20. tinybird/tb/modules/datafile/format_datasource.py +160 -0
  21. tinybird/tb/modules/datafile/format_pipe.py +195 -0
  22. tinybird/tb/modules/datafile/parse_datasource.py +41 -0
  23. tinybird/tb/modules/datafile/parse_pipe.py +69 -0
  24. tinybird/tb/modules/datafile/pipe_checker.py +560 -0
  25. tinybird/tb/modules/datafile/pull.py +157 -0
  26. tinybird/{tb_cli_modules → tb/modules}/datasource.py +7 -6
  27. tinybird/tb/modules/exceptions.py +91 -0
  28. tinybird/{tb_cli_modules → tb/modules}/fmt.py +6 -3
  29. tinybird/{tb_cli_modules → tb/modules}/job.py +3 -3
  30. tinybird/{tb_cli_modules → tb/modules}/llm.py +1 -1
  31. tinybird/{tb_cli_modules → tb/modules}/local.py +9 -5
  32. tinybird/{tb_cli_modules → tb/modules}/mock.py +5 -5
  33. tinybird/{tb_cli_modules → tb/modules}/pipe.py +11 -5
  34. tinybird/{tb_cli_modules → tb/modules}/prompts.py +1 -1
  35. tinybird/tb/modules/regions.py +9 -0
  36. tinybird/{tb_cli_modules → tb/modules}/tag.py +2 -2
  37. tinybird/tb/modules/telemetry.py +310 -0
  38. tinybird/{tb_cli_modules → tb/modules}/test.py +5 -5
  39. tinybird/{tb_cli_modules → tb/modules}/tinyunit/tinyunit.py +1 -1
  40. tinybird/{tb_cli_modules → tb/modules}/token.py +3 -3
  41. tinybird/{tb_cli_modules → tb/modules}/workspace.py +5 -5
  42. tinybird/{tb_cli_modules → tb/modules}/workspace_members.py +4 -4
  43. tinybird/tb_cli_modules/common.py +9 -25
  44. tinybird/tb_cli_modules/config.py +0 -8
  45. {tinybird-0.0.1.dev5.dist-info → tinybird-0.0.1.dev7.dist-info}/METADATA +1 -1
  46. tinybird-0.0.1.dev7.dist-info/RECORD +71 -0
  47. tinybird-0.0.1.dev7.dist-info/entry_points.txt +2 -0
  48. tinybird/datafile.py +0 -6123
  49. tinybird/tb_cli.py +0 -28
  50. tinybird-0.0.1.dev5.dist-info/RECORD +0 -52
  51. tinybird-0.0.1.dev5.dist-info/entry_points.txt +0 -2
  52. /tinybird/{tb_cli_modules → tb/modules}/table.py +0 -0
  53. /tinybird/{tb_cli_modules → tb/modules}/tinyunit/tinyunit_lib.py +0 -0
  54. {tinybird-0.0.1.dev5.dist-info → tinybird-0.0.1.dev7.dist-info}/WHEEL +0 -0
  55. {tinybird-0.0.1.dev5.dist-info → tinybird-0.0.1.dev7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,157 @@
1
+ import re
2
+ from asyncio import Semaphore, gather
3
+ from pathlib import Path
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ import aiofiles
7
+ import click
8
+
9
+ from tinybird.client import AuthNoTokenException, TinyB
10
+ from tinybird.feedback_manager import FeedbackManager
11
+ from tinybird.tb.modules.datafile.common import get_name_version
12
+ from tinybird.tb.modules.datafile.format_datasource import format_datasource
13
+ from tinybird.tb.modules.datafile.format_pipe import format_pipe
14
+
15
+
16
+ async def folder_pull(
17
+ client: TinyB,
18
+ folder: str,
19
+ auto: bool,
20
+ match: Optional[str],
21
+ force: bool,
22
+ verbose: bool = True,
23
+ progress_bar: bool = False,
24
+ fmt: bool = False,
25
+ ):
26
+ pattern = re.compile(match) if match else None
27
+
28
+ def _get_latest_versions(resources: List[str]):
29
+ versions: Dict[str, Any] = {}
30
+
31
+ for x in resources:
32
+ t = get_name_version(x)
33
+ t["original_name"] = x
34
+ if t["version"] is None:
35
+ t["version"] = -1
36
+ name = t["name"]
37
+
38
+ if name not in versions or name == x or versions[name]["version"] < t["version"]:
39
+ versions[name] = t
40
+ return versions
41
+
42
+ def get_file_folder(extension: str):
43
+ if not auto:
44
+ return None
45
+ if extension == "datasource":
46
+ return "datasources"
47
+ if extension == "pipe":
48
+ return "pipes"
49
+ if extension == "token":
50
+ return "tokens"
51
+ return None
52
+
53
+ async def write_files(
54
+ versions: Dict[str, Any],
55
+ resources: List[str],
56
+ extension: str,
57
+ get_resource_function: str,
58
+ progress_bar: bool = False,
59
+ fmt: bool = False,
60
+ ):
61
+ async def write_resource(k: Dict[str, Any]):
62
+ name = f"{k['name']}.{extension}"
63
+ try:
64
+ if pattern and not pattern.search(name):
65
+ if verbose:
66
+ click.echo(FeedbackManager.info_skipping_resource(resource=name))
67
+ return
68
+
69
+ resource = await getattr(client, get_resource_function)(k["original_name"])
70
+ resource_to_write = resource
71
+
72
+ if fmt:
73
+ if extension == "datasource":
74
+ resource_to_write = await format_datasource(name, content=resource)
75
+ elif extension == "pipe":
76
+ resource_to_write = await format_pipe(name, content=resource)
77
+
78
+ dest_folder = folder
79
+ if "." in k["name"] and extension != "token":
80
+ dest_folder = Path(folder) / "vendor" / k["name"].split(".", 1)[0]
81
+ name = f"{k['name'].split('.', 1)[1]}.{extension}"
82
+
83
+ file_folder = get_file_folder(extension)
84
+ f = Path(dest_folder) / file_folder if file_folder is not None else Path(dest_folder)
85
+
86
+ if not f.exists():
87
+ f.mkdir(parents=True)
88
+
89
+ f = f / name
90
+ resource_names = [x.split(".")[-1] for x in resources]
91
+
92
+ if verbose:
93
+ click.echo(FeedbackManager.info_writing_resource(resource=f))
94
+ if not f.exists() or force:
95
+ async with aiofiles.open(f, "w") as fd:
96
+ # versions are a client only thing so
97
+ # datafiles from the server do not contains information about versions
98
+ if k["version"] >= 0:
99
+ if fmt:
100
+ resource_to_write = "\n" + resource_to_write # fmt strips the first line
101
+
102
+ resource_to_write = f"VERSION {k['version']}\n" + resource_to_write
103
+ if resource_to_write:
104
+ matches = re.findall(r"([^\s\.]*__v\d+)", resource_to_write)
105
+ for match in set(matches):
106
+ m = match.split("__v")[0]
107
+ if m in resources or m in resource_names:
108
+ resource_to_write = resource_to_write.replace(match, m)
109
+ await fd.write(resource_to_write)
110
+ else:
111
+ if verbose:
112
+ click.echo(FeedbackManager.info_skip_already_exists())
113
+ except Exception as e:
114
+ raise click.ClickException(FeedbackManager.error_exception(error=e))
115
+
116
+ values = versions.values()
117
+
118
+ if progress_bar:
119
+ with click.progressbar(values, label=f"Pulling {extension}s") as values: # type: ignore
120
+ for k in values:
121
+ await write_resource(k)
122
+ else:
123
+ tasks = [write_resource(k) for k in values]
124
+ await _gather_with_concurrency(5, *tasks)
125
+
126
+ try:
127
+ datasources = await client.datasources()
128
+ remote_datasources = sorted([x["name"] for x in datasources])
129
+ datasources_versions = _get_latest_versions(remote_datasources)
130
+
131
+ pipes = await client.pipes()
132
+ remote_pipes = sorted([x["name"] for x in pipes])
133
+ pipes_versions = _get_latest_versions(remote_pipes)
134
+
135
+ resources = list(datasources_versions.keys()) + list(pipes_versions.keys())
136
+
137
+ await write_files(
138
+ datasources_versions, resources, "datasource", "datasource_file", progress_bar=progress_bar, fmt=fmt
139
+ )
140
+ await write_files(pipes_versions, resources, "pipe", "pipe_file", progress_bar=progress_bar, fmt=fmt)
141
+
142
+ return
143
+
144
+ except AuthNoTokenException:
145
+ raise
146
+ except Exception as e:
147
+ raise click.ClickException(FeedbackManager.error_pull(error=str(e)))
148
+
149
+
150
+ async def _gather_with_concurrency(n, *tasks):
151
+ semaphore = Semaphore(n)
152
+
153
+ async def sem_task(task):
154
+ async with semaphore:
155
+ return await task
156
+
157
+ return await gather(*(sem_task(task) for task in tasks))
@@ -15,16 +15,15 @@ from click import Context
15
15
 
16
16
  from tinybird.client import AuthNoTokenException, CanNotBeDeletedException, DoesNotExistException, TinyB
17
17
  from tinybird.config import get_display_host
18
- from tinybird.tb_cli_modules.config import CLIConfig
18
+ from tinybird.tb.modules.config import CLIConfig
19
19
 
20
20
  if TYPE_CHECKING:
21
21
  from tinybird.connectors import Connector
22
22
 
23
- from tinybird.datafile import get_name_version, wait_job
24
23
  from tinybird.feedback_manager import FeedbackManager
25
- from tinybird.tb_cli_modules.branch import warn_if_in_live
26
- from tinybird.tb_cli_modules.cli import cli
27
- from tinybird.tb_cli_modules.common import (
24
+ from tinybird.tb.modules.branch import warn_if_in_live
25
+ from tinybird.tb.modules.cli import cli
26
+ from tinybird.tb.modules.common import (
28
27
  _analyze,
29
28
  _generate_datafile,
30
29
  ask_for_user_token,
@@ -40,8 +39,10 @@ from tinybird.tb_cli_modules.common import (
40
39
  validate_kafka_auto_offset_reset,
41
40
  validate_kafka_group,
42
41
  validate_kafka_topic,
42
+ wait_job,
43
43
  )
44
- from tinybird.tb_cli_modules.exceptions import CLIDatasourceException
44
+ from tinybird.tb.modules.datafile.common import get_name_version
45
+ from tinybird.tb.modules.exceptions import CLIDatasourceException
45
46
 
46
47
 
47
48
  @cli.group()
@@ -0,0 +1,91 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ import click
4
+
5
+ from tinybird.tb.modules.telemetry import add_telemetry_event
6
+
7
+
8
+ class CLIException(click.exceptions.ClickException):
9
+ """Default exception for all exceptions raised in the CLI.
10
+
11
+ Allows to specift a custom telemetry event to be sent before
12
+ raising the exception (if not specified, it sends a generic
13
+ `error` beacon with the error message)
14
+ """
15
+
16
+ def __init__(self, message: str, telemetry_event: Optional[str] = None, **kw_telemetry_event_data: Any) -> None:
17
+ telemetry_event = telemetry_event or "error"
18
+ data: Dict[str, Any] = {"error": message}
19
+ data.update(kw_telemetry_event_data)
20
+ add_telemetry_event(telemetry_event, **data)
21
+ super().__init__(message)
22
+
23
+
24
+ class CLIAuthException(CLIException):
25
+ """Exceptions generated by the auth commands"""
26
+
27
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
28
+ super().__init__(message, "auth_error", **kw_telemetry_event_data)
29
+
30
+
31
+ class CLIReleaseException(CLIException):
32
+ """Exceptions generated by the release commands"""
33
+
34
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
35
+ super().__init__(message, "release_error", **kw_telemetry_event_data)
36
+
37
+
38
+ class CLIBranchException(CLIException):
39
+ """Exceptions generated by the branch commands"""
40
+
41
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
42
+ super().__init__(message, "branch_error", **kw_telemetry_event_data)
43
+
44
+
45
+ class CLIGitReleaseException(CLIException):
46
+ """Exceptions generated by the git release related commands"""
47
+
48
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
49
+ super().__init__(message, "git_release_error", **kw_telemetry_event_data)
50
+
51
+
52
+ class CLIConnectionException(CLIException):
53
+ """Exceptions generated by the connection commands"""
54
+
55
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
56
+ super().__init__(message, "connection_error", **kw_telemetry_event_data)
57
+
58
+
59
+ class CLIDatasourceException(CLIException):
60
+ """Exceptions generated by the datasource commands"""
61
+
62
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
63
+ super().__init__(message, "datasource_error", **kw_telemetry_event_data)
64
+
65
+
66
+ class CLIPipeException(CLIException):
67
+ """Exceptions generated by the pipe commands"""
68
+
69
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
70
+ super().__init__(message, "pipe_error", **kw_telemetry_event_data)
71
+
72
+
73
+ class CLIWorkspaceMembersException(CLIException):
74
+ """Exceptions generated by the workspace members commands"""
75
+
76
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
77
+ super().__init__(message, "workspace_members_error", **kw_telemetry_event_data)
78
+
79
+
80
+ class CLIWorkspaceException(CLIException):
81
+ """Exceptions generated by the workspace commands"""
82
+
83
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
84
+ super().__init__(message, "workspace_error", **kw_telemetry_event_data)
85
+
86
+
87
+ class CLITokenException(CLIException):
88
+ """Exceptions generated by the token commands"""
89
+
90
+ def __init__(self, message: str, **kw_telemetry_event_data: Any) -> None:
91
+ super().__init__(message, "token_error", **kw_telemetry_event_data)
@@ -7,10 +7,13 @@ import aiofiles
7
7
  import click
8
8
  from click import Context
9
9
 
10
- from tinybird.datafile import color_diff, format_datasource, format_pipe, is_file_a_datasource, peek
11
10
  from tinybird.feedback_manager import FeedbackManager
12
- from tinybird.tb_cli_modules.cli import cli
13
- from tinybird.tb_cli_modules.common import coro
11
+ from tinybird.tb.modules.cli import cli
12
+ from tinybird.tb.modules.common import coro
13
+ from tinybird.tb.modules.datafile.common import is_file_a_datasource
14
+ from tinybird.tb.modules.datafile.diff import color_diff, peek
15
+ from tinybird.tb.modules.datafile.format_datasource import format_datasource
16
+ from tinybird.tb.modules.datafile.format_pipe import format_pipe
14
17
 
15
18
 
16
19
  @cli.command()
@@ -8,9 +8,9 @@ from click import Context
8
8
 
9
9
  from tinybird.client import DoesNotExistException, TinyB
10
10
  from tinybird.feedback_manager import FeedbackManager
11
- from tinybird.tb_cli_modules.cli import cli
12
- from tinybird.tb_cli_modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table
13
- from tinybird.tb_cli_modules.exceptions import CLIException
11
+ from tinybird.tb.modules.cli import cli
12
+ from tinybird.tb.modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table
13
+ from tinybird.tb.modules.exceptions import CLIException
14
14
 
15
15
 
16
16
  @cli.group()
@@ -6,7 +6,7 @@ from openai import OpenAI
6
6
  from pydantic import BaseModel
7
7
 
8
8
  from tinybird.client import TinyB
9
- from tinybird.tb_cli_modules.prompts import create_project_prompt, sample_data_sql_prompt
9
+ from tinybird.tb.modules.prompts import create_project_prompt, sample_data_sql_prompt
10
10
 
11
11
 
12
12
  class DataFile(BaseModel):
@@ -6,12 +6,12 @@ import requests
6
6
 
7
7
  import docker
8
8
  from tinybird.feedback_manager import FeedbackManager
9
- from tinybird.tb_cli_modules.cli import cli
10
- from tinybird.tb_cli_modules.common import (
9
+ from tinybird.tb.modules.cli import cli
10
+ from tinybird.tb.modules.common import (
11
11
  coro,
12
12
  )
13
- from tinybird.tb_cli_modules.config import CLIConfig
14
- from tinybird.tb_cli_modules.exceptions import CLIException
13
+ from tinybird.tb.modules.config import CLIConfig
14
+ from tinybird.tb.modules.exceptions import CLIException
15
15
 
16
16
  # TODO: Use the official Tinybird image once it's available 'tinybirdco/tinybird-local:latest'
17
17
  TB_IMAGE_NAME = "registry.gitlab.com/tinybird/analytics/tinybird-local-jammy-3.11:latest"
@@ -114,7 +114,11 @@ def remove_tinybird_local(docker_client):
114
114
  def get_tinybird_local_client():
115
115
  """Get a Tinybird client connected to the local environment."""
116
116
  config = CLIConfig.get_project_config()
117
- tokens = requests.get(f"{TB_LOCAL_HOST}/tokens").json()
117
+ try:
118
+ tokens = requests.get(f"{TB_LOCAL_HOST}/tokens").json()
119
+ except Exception:
120
+ raise CLIException("Tinybird local environment is not running. Please start it with `tb local start`.")
121
+
118
122
  token = tokens["workspace_admin_token"]
119
123
  config.set_token(token)
120
124
  config.set_host(TB_LOCAL_HOST)
@@ -4,11 +4,11 @@ from pathlib import Path
4
4
  import click
5
5
 
6
6
  from tinybird.feedback_manager import FeedbackManager
7
- from tinybird.tb_cli_modules.cli import cli
8
- from tinybird.tb_cli_modules.common import CLIException, coro
9
- from tinybird.tb_cli_modules.config import CLIConfig
10
- from tinybird.tb_cli_modules.llm import LLM
11
- from tinybird.tb_cli_modules.local import get_tinybird_local_client
7
+ from tinybird.tb.modules.cli import cli
8
+ from tinybird.tb.modules.common import CLIException, coro
9
+ from tinybird.tb.modules.config import CLIConfig
10
+ from tinybird.tb.modules.llm import LLM
11
+ from tinybird.tb.modules.local import get_tinybird_local_client
12
12
 
13
13
 
14
14
  @cli.command()
@@ -16,12 +16,18 @@ from click import Context
16
16
  import tinybird.context as context
17
17
  from tinybird.client import AuthNoTokenException, DoesNotExistException, TinyB
18
18
  from tinybird.config import DEFAULT_API_HOST, FeatureFlags
19
- from tinybird.datafile import PipeNodeTypes, PipeTypes, folder_push, get_name_version, process_file, wait_job
20
19
  from tinybird.feedback_manager import FeedbackManager
21
- from tinybird.tb_cli_modules.branch import warn_if_in_live
22
- from tinybird.tb_cli_modules.cli import cli
23
- from tinybird.tb_cli_modules.common import coro, create_tb_client, echo_safe_humanfriendly_tables_format_smart_table
24
- from tinybird.tb_cli_modules.exceptions import CLIPipeException
20
+ from tinybird.tb.modules.branch import warn_if_in_live
21
+ from tinybird.tb.modules.cli import cli
22
+ from tinybird.tb.modules.common import (
23
+ coro,
24
+ create_tb_client,
25
+ echo_safe_humanfriendly_tables_format_smart_table,
26
+ wait_job,
27
+ )
28
+ from tinybird.tb.modules.datafile.build import folder_push, process_file
29
+ from tinybird.tb.modules.datafile.common import PipeNodeTypes, PipeTypes, get_name_version
30
+ from tinybird.tb.modules.exceptions import CLIPipeException
25
31
 
26
32
 
27
33
  @cli.group()
@@ -44,7 +44,7 @@ SQL >
44
44
  - Create multiple pipes to show different use cases over the same datasource.
45
45
  - The SQL query must be a valid ClickHouse SQL query that mixes ClickHouse syntax and Tinybird templating syntax.
46
46
  - If you need to use dynamic parameters you must start the whole sql query ALWAYS with "%" symbol on top. e.g: SQL >\n %\n SELECT * FROM <table> WHERE <condition> LIMIT 10
47
- - The Parameter functions like this one {{String(<my_param_name>,<default_value>)}} can be one of the following: String, DateTime, Date, Float32, Float64, Int, Integer, UInt8, UInt16, UInt32, UInt64, UInt128, UInt256, Int8, Int16, Int32, Int64, Int128, Int256
47
+ - The Parameter functions like this one {{String(my_param_name,default_value)}} can be one of the following: String, DateTime, Date, Float32, Float64, Int, Integer, UInt8, UInt16, UInt32, UInt64, UInt128, UInt256, Int8, Int16, Int32, Int64, Int128, Int256
48
48
  - Parameter names must be different from column names. Pass always the param name and a default value to the function.
49
49
  - Nodes can't have the same exact name as the Pipe they belong to.
50
50
  </instructions>
@@ -0,0 +1,9 @@
1
+ from typing import Optional, TypedDict
2
+
3
+
4
+ class Region(TypedDict):
5
+ name: str
6
+ provider: str
7
+ api_host: str
8
+ host: str
9
+ default_password: Optional[str]
@@ -4,8 +4,8 @@ import click
4
4
  from click import Context
5
5
 
6
6
  from tinybird.feedback_manager import FeedbackManager
7
- from tinybird.tb_cli_modules.cli import cli
8
- from tinybird.tb_cli_modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table
7
+ from tinybird.tb.modules.cli import cli
8
+ from tinybird.tb.modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table
9
9
 
10
10
 
11
11
  @cli.group()