tinybird 0.0.1.dev212__py3-none-any.whl → 0.0.1.dev214__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 (36) hide show
  1. tinybird/{tb/modules/datafile → datafile}/common.py +26 -26
  2. tinybird/datafile/parse_connection.py +60 -0
  3. tinybird/{tb/modules/datafile → datafile}/parse_datasource.py +3 -3
  4. tinybird/{tb/modules/datafile → datafile}/parse_pipe.py +3 -3
  5. tinybird/tb/__cli__.py +2 -2
  6. tinybird/tb/cli.py +1 -0
  7. tinybird/tb/client.py +3 -3
  8. tinybird/tb/modules/build.py +3 -3
  9. tinybird/tb/modules/common.py +4 -2
  10. tinybird/tb/modules/connection.py +30 -5
  11. tinybird/tb/modules/copy.py +2 -43
  12. tinybird/tb/modules/datafile/build.py +15 -15
  13. tinybird/tb/modules/datafile/build_datasource.py +1 -1
  14. tinybird/tb/modules/datafile/build_pipe.py +1 -1
  15. tinybird/tb/modules/datafile/diff.py +1 -1
  16. tinybird/tb/modules/datafile/format_common.py +1 -1
  17. tinybird/tb/modules/datafile/format_datasource.py +2 -2
  18. tinybird/tb/modules/datafile/format_pipe.py +3 -3
  19. tinybird/tb/modules/datafile/pipe_checker.py +1 -1
  20. tinybird/tb/modules/datafile/playground.py +17 -17
  21. tinybird/tb/modules/datasource.py +1 -1
  22. tinybird/tb/modules/endpoint.py +1 -1
  23. tinybird/tb/modules/feedback_manager.py +9 -1
  24. tinybird/tb/modules/local.py +8 -237
  25. tinybird/tb/modules/local_common.py +5 -1
  26. tinybird/tb/modules/materialization.py +1 -1
  27. tinybird/tb/modules/pipe.py +1 -1
  28. tinybird/tb/modules/project.py +5 -3
  29. tinybird/tb/modules/sink.py +105 -0
  30. tinybird/tb/modules/watch.py +1 -1
  31. {tinybird-0.0.1.dev212.dist-info → tinybird-0.0.1.dev214.dist-info}/METADATA +1 -1
  32. {tinybird-0.0.1.dev212.dist-info → tinybird-0.0.1.dev214.dist-info}/RECORD +36 -34
  33. /tinybird/{tb/modules/datafile → datafile}/exceptions.py +0 -0
  34. {tinybird-0.0.1.dev212.dist-info → tinybird-0.0.1.dev214.dist-info}/WHEEL +0 -0
  35. {tinybird-0.0.1.dev212.dist-info → tinybird-0.0.1.dev214.dist-info}/entry_points.txt +0 -0
  36. {tinybird-0.0.1.dev212.dist-info → tinybird-0.0.1.dev214.dist-info}/top_level.txt +0 -0
@@ -11,20 +11,7 @@ from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union
11
11
  import click
12
12
  from toposort import toposort
13
13
 
14
- from tinybird.sql import parse_table_structure, schema_to_sql_columns
15
- from tinybird.sql_template import get_used_tables_in_template, render_sql_template
16
- from tinybird.tb.client import TinyB
17
- from tinybird.tb.modules.common import get_ca_pem_content
18
- from tinybird.tb.modules.config import CLIConfig
19
- from tinybird.tb.modules.datafile.build_datasource import is_datasource
20
- from tinybird.tb.modules.datafile.build_pipe import (
21
- get_target_materialized_data_source_name,
22
- is_endpoint,
23
- is_endpoint_with_no_dependencies,
24
- is_materialized,
25
- new_pipe,
26
- )
27
- from tinybird.tb.modules.datafile.common import (
14
+ from tinybird.datafile.common import (
28
15
  DEFAULT_CRON_PERIOD,
29
16
  INTERNAL_TABLES,
30
17
  ON_DEMAND,
@@ -40,9 +27,22 @@ from tinybird.tb.modules.datafile.common import (
40
27
  get_project_filenames,
41
28
  pp,
42
29
  )
43
- from tinybird.tb.modules.datafile.exceptions import AlreadyExistsException, IncludeFileNotFoundException
44
- from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
45
- from tinybird.tb.modules.datafile.parse_pipe import parse_pipe
30
+ from tinybird.datafile.exceptions import AlreadyExistsException, IncludeFileNotFoundException
31
+ from tinybird.datafile.parse_datasource import parse_datasource
32
+ from tinybird.datafile.parse_pipe import parse_pipe
33
+ from tinybird.sql import parse_table_structure, schema_to_sql_columns
34
+ from tinybird.sql_template import get_used_tables_in_template, render_sql_template
35
+ from tinybird.tb.client import TinyB
36
+ from tinybird.tb.modules.common import get_ca_pem_content
37
+ from tinybird.tb.modules.config import CLIConfig
38
+ from tinybird.tb.modules.datafile.build_datasource import is_datasource
39
+ from tinybird.tb.modules.datafile.build_pipe import (
40
+ get_target_materialized_data_source_name,
41
+ is_endpoint,
42
+ is_endpoint_with_no_dependencies,
43
+ is_materialized,
44
+ new_pipe,
45
+ )
46
46
  from tinybird.tb.modules.feedback_manager import FeedbackManager
47
47
  from tinybird.tb.modules.project import Project
48
48
 
@@ -18,6 +18,7 @@ import humanfriendly
18
18
  import requests
19
19
  from click import Context
20
20
 
21
+ from tinybird.datafile.common import get_name_version
21
22
  from tinybird.prompts import quarantine_prompt
22
23
  from tinybird.syncasync import sync_to_async
23
24
  from tinybird.tb.client import AuthNoTokenException, DoesNotExistException, TinyB
@@ -40,7 +41,6 @@ from tinybird.tb.modules.create import (
40
41
  generate_aws_iamrole_connection_file_with_secret,
41
42
  generate_gcs_connection_file_with_secrets,
42
43
  )
43
- from tinybird.tb.modules.datafile.common import get_name_version
44
44
  from tinybird.tb.modules.datafile.fixture import persist_fixture
45
45
  from tinybird.tb.modules.exceptions import CLIDatasourceException
46
46
  from tinybird.tb.modules.feedback_manager import FeedbackManager
@@ -14,10 +14,10 @@ import pyperclip
14
14
  import requests
15
15
  from click import Context
16
16
 
17
+ from tinybird.datafile.common import get_name_version
17
18
  from tinybird.tb.client import AuthNoTokenException, DoesNotExistException, TinyB
18
19
  from tinybird.tb.modules.cli import cli
19
20
  from tinybird.tb.modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table
20
- from tinybird.tb.modules.datafile.common import get_name_version
21
21
  from tinybird.tb.modules.exceptions import CLIPipeException
22
22
  from tinybird.tb.modules.feedback_manager import FeedbackManager
23
23
 
@@ -587,7 +587,7 @@ STEP {step}: CREATE IAM ROLE FOR {environment} ENVIRONMENT
587
587
  Please enter the ARN of the role you just created"""
588
588
  )
589
589
 
590
- prompt_s3_iamrole_success = success_message("""
590
+ prompt_s3_iamrole_success_read = success_message("""
591
591
  ✅ S3 CONNECTION CONFIGURED SUCCESSFULLY
592
592
 
593
593
  • File created at: {connection_path}
@@ -595,6 +595,14 @@ Please enter the ARN of the role you just created"""
595
595
  • Learn more about our S3 Connector: https://www.tinybird.co/docs/forward/get-data-in/connectors/s3
596
596
  """)
597
597
 
598
+ prompt_s3_iamrole_success_write = success_message("""
599
+ ✅ S3 CONNECTION CONFIGURED SUCCESSFULLY
600
+
601
+ • File created at: {connection_path}
602
+ • You can now use this connection in your Data Sources with: EXPORT_CONNECTION_NAME '{connection_name}'
603
+ • Learn more about our S3 Sinks: https://www.tinybird.co/docs/forward/work-with-data/publish-data/s3-sinks
604
+ """)
605
+
598
606
  # S3 IAM Role Connection Messages
599
607
  prompt_gcs_connection_header = info_highlight_message("""
600
608
  ──────────────────────────────────────────────────────────────
@@ -1,249 +1,20 @@
1
- import json
2
- import os
3
- import re
4
1
  import subprocess
5
- import time
6
- from typing import Optional
7
2
 
8
- import boto3
9
3
  import click
10
4
  import requests
11
5
 
12
- import docker
13
6
  from docker.client import DockerClient
14
- from docker.models.containers import Container
15
7
  from tinybird.tb.modules.cli import cli
16
8
  from tinybird.tb.modules.common import coro
17
- from tinybird.tb.modules.exceptions import CLIException, CLILocalException
9
+ from tinybird.tb.modules.exceptions import CLIException
18
10
  from tinybird.tb.modules.feedback_manager import FeedbackManager
19
- from tinybird.tb.modules.local_common import TB_CONTAINER_NAME, TB_IMAGE_NAME, TB_LOCAL_ADDRESS, TB_LOCAL_PORT
20
- from tinybird.tb.modules.telemetry import add_telemetry_event
21
-
22
-
23
- def start_tinybird_local(
24
- docker_client: DockerClient,
25
- use_aws_creds: bool,
26
- ) -> None:
27
- """Start the Tinybird container."""
28
- pull_show_prompt = False
29
- pull_required = False
30
- try:
31
- local_image = docker_client.images.get(TB_IMAGE_NAME)
32
- local_image_id = local_image.attrs["RepoDigests"][0].split("@")[1]
33
- remote_image = docker_client.images.get_registry_data(TB_IMAGE_NAME)
34
- pull_show_prompt = local_image_id != remote_image.id
35
- except Exception:
36
- pull_show_prompt = False
37
- pull_required = True
38
-
39
- if pull_show_prompt and click.confirm(
40
- FeedbackManager.warning(message="△ New version detected, download? [y/N]:"),
41
- show_default=False,
42
- prompt_suffix="",
43
- ):
44
- click.echo(FeedbackManager.info(message="* Downloading latest version of Tinybird Local..."))
45
- pull_required = True
46
-
47
- if pull_required:
48
- docker_client.images.pull(TB_IMAGE_NAME, platform="linux/amd64")
49
-
50
- environment = get_use_aws_creds() if use_aws_creds else {}
51
-
52
- container = get_existing_container_with_matching_env(docker_client, TB_CONTAINER_NAME, environment)
53
-
54
- if container and not pull_required:
55
- # Container `start` is idempotent. It's safe to call it even if the container is already running.
56
- container.start()
57
- else:
58
- if container:
59
- container.remove(force=True)
60
-
61
- container = docker_client.containers.run(
62
- TB_IMAGE_NAME,
63
- name=TB_CONTAINER_NAME,
64
- detach=True,
65
- ports={"7181/tcp": TB_LOCAL_PORT},
66
- remove=False,
67
- platform="linux/amd64",
68
- environment=environment,
69
- )
70
-
71
- click.echo(FeedbackManager.info(message="* Waiting for Tinybird Local to be ready..."))
72
- while True:
73
- container.reload() # Refresh container attributes
74
- health = container.attrs.get("State", {}).get("Health", {}).get("Status")
75
- if health == "healthy":
76
- break
77
- if health == "unhealthy":
78
- raise CLILocalException(
79
- FeedbackManager.error(
80
- message="Tinybird Local is unhealthy. Try running `tb local restart` in a few seconds."
81
- )
82
- )
83
-
84
- time.sleep(5)
85
-
86
- # Remove tinybird-local dangling images to avoid running out of disk space
87
- images = docker_client.images.list(name=re.sub(r":.*$", "", TB_IMAGE_NAME), all=True, filters={"dangling": True})
88
- for image in images:
89
- image.remove(force=True)
90
-
91
-
92
- def get_existing_container_with_matching_env(
93
- docker_client: DockerClient, container_name: str, required_env: dict[str, str]
94
- ) -> Optional[Container]:
95
- """
96
- Checks if a container with the given name exists and has matching environment variables.
97
- If it exists but environment doesn't match, it returns None.
98
-
99
- Args:
100
- docker_client: The Docker client instance
101
- container_name: The name of the container to check
102
- required_env: Dictionary of environment variables that must be present
103
-
104
- Returns:
105
- The container if it exists with matching environment, None otherwise
106
- """
107
- container = None
108
- containers = docker_client.containers.list(all=True, filters={"name": container_name})
109
- if containers:
110
- container = containers[0]
111
-
112
- if container and required_env:
113
- container_info = container.attrs
114
- container_env = container_info.get("Config", {}).get("Env", [])
115
- env_missing = False
116
- for key, value in required_env.items():
117
- env_var = f"{key}={value}"
118
- if env_var not in container_env:
119
- env_missing = True
120
- break
121
-
122
- if env_missing:
123
- container.remove(force=True)
124
- container = None
125
-
126
- return container
127
-
128
-
129
- def get_docker_client() -> DockerClient:
130
- """Check if Docker is installed and running."""
131
- try:
132
- docker_host = os.getenv("DOCKER_HOST")
133
- if not docker_host:
134
- # Try to get docker host from docker context
135
- try:
136
- try:
137
- output = subprocess.check_output(["docker", "context", "inspect"], text=True)
138
- except Exception as e:
139
- add_telemetry_event(
140
- "docker_error",
141
- error=f"docker_context_inspect_error: {str(e)}",
142
- )
143
- raise e
144
- try:
145
- context = json.loads(output)
146
- except Exception as e:
147
- add_telemetry_event(
148
- "docker_error",
149
- error=f"docker_context_inspect_parse_output_error: {str(e)}",
150
- data={
151
- "docker_context_inspect_output": output,
152
- },
153
- )
154
- raise e
155
- if context and len(context) > 0:
156
- try:
157
- docker_host = context[0].get("Endpoints", {}).get("docker", {}).get("Host")
158
- if docker_host:
159
- os.environ["DOCKER_HOST"] = docker_host
160
- except Exception as e:
161
- add_telemetry_event(
162
- "docker_error",
163
- error=f"docker_context_parse_host_error: {str(e)}",
164
- data={
165
- "context": json.dumps(context),
166
- },
167
- )
168
- raise e
169
- except Exception:
170
- pass
171
- try:
172
- client = docker.from_env() # type: ignore
173
- except Exception as e:
174
- add_telemetry_event(
175
- "docker_error",
176
- error=f"docker_get_client_from_env_error: {str(e)}",
177
- )
178
- raise e
179
- try:
180
- client.ping()
181
- except Exception as e:
182
- client_dict_non_sensitive = {k: v for k, v in client.api.__dict__.items() if "auth" not in k}
183
- add_telemetry_event(
184
- "docker_error",
185
- error=f"docker_ping_error: {str(e)}",
186
- data={
187
- "client": repr(client_dict_non_sensitive),
188
- },
189
- )
190
- raise e
191
- return client
192
- except Exception:
193
- docker_location_message = ""
194
- if docker_host:
195
- docker_location_message = f"Trying to connect to Docker-compatible runtime at {docker_host}"
196
-
197
- raise CLILocalException(
198
- FeedbackManager.error(
199
- message=(
200
- f"No container runtime is running. Make sure a Docker-compatible runtime is installed and running. "
201
- f"{docker_location_message}\n\n"
202
- "If you're using a custom location, please provide it using the DOCKER_HOST environment variable."
203
- )
204
- )
205
- )
206
-
207
-
208
- def get_use_aws_creds() -> dict[str, str]:
209
- credentials: dict[str, str] = {}
210
- try:
211
- # Get the boto3 session and credentials
212
- session = boto3.Session()
213
- creds = session.get_credentials()
214
-
215
- if creds:
216
- # Create environment variables for the container based on boto credentials
217
- credentials["AWS_ACCESS_KEY_ID"] = creds.access_key
218
- credentials["AWS_SECRET_ACCESS_KEY"] = creds.secret_key
219
-
220
- # Add session token if it exists (for temporary credentials)
221
- if creds.token:
222
- credentials["AWS_SESSION_TOKEN"] = creds.token
223
-
224
- # Add region if available
225
- if session.region_name:
226
- credentials["AWS_DEFAULT_REGION"] = session.region_name
227
-
228
- click.echo(
229
- FeedbackManager.success(
230
- message=f"✓ AWS credentials found and will be passed to Tinybird Local (region: {session.region_name or 'not set'})"
231
- )
232
- )
233
- else:
234
- click.echo(
235
- FeedbackManager.warning(
236
- message="△ No AWS credentials found. S3 operations will not work in Tinybird Local."
237
- )
238
- )
239
- except Exception as e:
240
- click.echo(
241
- FeedbackManager.warning(
242
- message=f"△ Error retrieving AWS credentials: {str(e)}. S3 operations will not work in Tinybird Local."
243
- )
244
- )
245
-
246
- return credentials
11
+ from tinybird.tb.modules.local_common import (
12
+ TB_CONTAINER_NAME,
13
+ TB_LOCAL_ADDRESS,
14
+ get_docker_client,
15
+ get_existing_container_with_matching_env,
16
+ start_tinybird_local,
17
+ )
247
18
 
248
19
 
249
20
  def stop_tinybird_local(docker_client: DockerClient) -> None:
@@ -384,11 +384,15 @@ def get_docker_client() -> DockerClient:
384
384
  raise e
385
385
  return client
386
386
  except Exception:
387
+ docker_location_message = ""
388
+ if docker_host:
389
+ docker_location_message = f"Trying to connect to Docker-compatible runtime at {docker_host}"
390
+
387
391
  raise CLILocalException(
388
392
  FeedbackManager.error(
389
393
  message=(
390
394
  f"No container runtime is running. Make sure a Docker-compatible runtime is installed and running. "
391
- f"Trying to connect to Docker-compatible runtime at {docker_host}\n\n"
395
+ f"{docker_location_message}\n\n"
392
396
  "If you're using a custom location, please provide it using the DOCKER_HOST environment variable."
393
397
  )
394
398
  )
@@ -3,6 +3,7 @@ import re
3
3
 
4
4
  import click
5
5
 
6
+ from tinybird.datafile.common import PipeTypes, get_name_version
6
7
  from tinybird.tb.client import TinyB
7
8
  from tinybird.tb.modules.cli import cli
8
9
  from tinybird.tb.modules.common import (
@@ -10,7 +11,6 @@ from tinybird.tb.modules.common import (
10
11
  echo_safe_humanfriendly_tables_format_smart_table,
11
12
  wait_job,
12
13
  )
13
- from tinybird.tb.modules.datafile.common import PipeTypes, get_name_version
14
14
  from tinybird.tb.modules.exceptions import CLIPipeException
15
15
  from tinybird.tb.modules.feedback_manager import FeedbackManager
16
16
 
@@ -9,13 +9,13 @@ import re
9
9
  import click
10
10
  from click import Context
11
11
 
12
+ from tinybird.datafile.common import get_name_version
12
13
  from tinybird.tb.client import TinyB
13
14
  from tinybird.tb.modules.cli import cli
14
15
  from tinybird.tb.modules.common import (
15
16
  coro,
16
17
  echo_safe_humanfriendly_tables_format_smart_table,
17
18
  )
18
- from tinybird.tb.modules.datafile.common import get_name_version
19
19
  from tinybird.tb.modules.exceptions import CLIPipeException
20
20
  from tinybird.tb.modules.feedback_manager import FeedbackManager
21
21
 
@@ -3,9 +3,9 @@ import re
3
3
  from pathlib import Path
4
4
  from typing import Dict, List, Optional
5
5
 
6
- from tinybird.tb.modules.datafile.common import Datafile
7
- from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
8
- from tinybird.tb.modules.datafile.parse_pipe import parse_pipe
6
+ from tinybird.datafile.common import Datafile
7
+ from tinybird.datafile.parse_datasource import parse_datasource
8
+ from tinybird.datafile.parse_pipe import parse_pipe
9
9
 
10
10
 
11
11
  class Project:
@@ -125,6 +125,8 @@ class Project:
125
125
  return "materialization"
126
126
  elif re.search(r"TYPE copy", content, re.IGNORECASE):
127
127
  return "copy"
128
+ elif re.search(r"TYPE sink", content, re.IGNORECASE):
129
+ return "sink"
128
130
  return "pipe"
129
131
  except Exception:
130
132
  return "pipe"
@@ -0,0 +1,105 @@
1
+ import json
2
+ import re
3
+ from typing import Optional, Tuple
4
+
5
+ import click
6
+ from click import Context
7
+
8
+ from tinybird.datafile.common import get_name_version
9
+ from tinybird.tb.client import AuthNoTokenException, TinyB
10
+ from tinybird.tb.modules.cli import cli
11
+ from tinybird.tb.modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table, wait_job
12
+ from tinybird.tb.modules.exceptions import CLIPipeException
13
+ from tinybird.tb.modules.feedback_manager import FeedbackManager
14
+
15
+
16
+ @cli.group()
17
+ @click.pass_context
18
+ def sink(ctx):
19
+ """Sink pipe commands."""
20
+
21
+
22
+ @sink.command(name="ls")
23
+ @click.option("--match", default=None, help="Retrieve any resourcing matching the pattern. eg --match _test")
24
+ @click.option(
25
+ "--format",
26
+ "format_",
27
+ type=click.Choice(["json"], case_sensitive=False),
28
+ default=None,
29
+ help="Force a type of the output",
30
+ )
31
+ @click.pass_context
32
+ @coro
33
+ async def sink_ls(ctx: Context, match: str, format_: str):
34
+ """List sink pipes"""
35
+
36
+ client: TinyB = ctx.ensure_object(dict)["client"]
37
+ pipes = await client.pipes(dependencies=False, node_attrs="name", attrs="name,updated_at,type")
38
+ sinks = [p for p in pipes if p.get("type") == "sink"]
39
+ sinks = sorted(sinks, key=lambda p: p["updated_at"])
40
+ columns = ["name", "updated at", "nodes"]
41
+ table_human_readable = []
42
+ table_machine_readable = []
43
+ pattern = re.compile(match) if match else None
44
+ for t in sinks:
45
+ tk = get_name_version(t["name"])
46
+ if pattern and not pattern.search(tk["name"]):
47
+ continue
48
+ table_human_readable.append((tk["name"], t["updated_at"][:-7], len(t["nodes"])))
49
+ table_machine_readable.append(
50
+ {
51
+ "name": tk["name"],
52
+ "updated at": t["updated_at"][:-7],
53
+ "nodes": len(t["nodes"]),
54
+ }
55
+ )
56
+
57
+ if not format_:
58
+ click.echo(FeedbackManager.info_pipes())
59
+ echo_safe_humanfriendly_tables_format_smart_table(table_human_readable, column_names=columns)
60
+ click.echo("\n")
61
+ elif format_ == "json":
62
+ click.echo(json.dumps({"pipes": table_machine_readable}, indent=2))
63
+ else:
64
+ raise CLIPipeException(FeedbackManager.error_pipe_ls_type())
65
+
66
+
67
+ @sink.command(name="run", short_help="Run an on-demand sink job")
68
+ @click.argument("pipe_name_or_id")
69
+ @click.option("--wait", is_flag=True, default=False, help="Wait for the sink job to finish")
70
+ @click.option(
71
+ "--mode", type=click.Choice(["append", "replace"], case_sensitive=True), default=None, help="Sink strategy"
72
+ )
73
+ @click.option(
74
+ "--param",
75
+ nargs=1,
76
+ type=str,
77
+ multiple=True,
78
+ default=None,
79
+ help="Key and value of the params you want the Sink pipe to be called with. For example: tb pipe sink run <my_sink_pipe> --param foo=bar",
80
+ )
81
+ @click.pass_context
82
+ @coro
83
+ async def sink_run(ctx: click.Context, pipe_name_or_id: str, wait: bool, mode: str, param: Optional[Tuple[str]]):
84
+ """Run a sink pipe"""
85
+
86
+ params = dict(key_value.split("=") for key_value in param) if param else {}
87
+ click.echo(FeedbackManager.highlight(message=f"\n» Running sink '{pipe_name_or_id}'"))
88
+ client: TinyB = ctx.ensure_object(dict)["client"]
89
+
90
+ try:
91
+ response = await client.pipe_run(pipe_name_or_id, "sink", params, mode)
92
+ job_id = response["job"]["id"]
93
+ job_url = response["job"]["job_url"]
94
+ click.echo(FeedbackManager.gray(message="Job URL: ") + FeedbackManager.info(message=f"{job_url}"))
95
+ click.echo(FeedbackManager.success(message="✓ Sink job created"))
96
+
97
+ if wait:
98
+ click.echo("\n")
99
+ await wait_job(client, job_id, job_url, FeedbackManager.highlight(message="» Exporting data"))
100
+ click.echo(FeedbackManager.success(message="✓ Data exported"))
101
+
102
+ except AuthNoTokenException:
103
+ raise
104
+ except Exception as e:
105
+ raise CLIPipeException(FeedbackManager.error_creating_sink_job(error=e))
@@ -15,7 +15,7 @@ from watchdog.events import (
15
15
  )
16
16
  from watchdog.observers import Observer
17
17
 
18
- from tinybird.tb.modules.datafile.common import Datafile, DatafileKind
18
+ from tinybird.datafile.common import Datafile, DatafileKind
19
19
  from tinybird.tb.modules.datafile.fixture import FixtureExtension
20
20
  from tinybird.tb.modules.feedback_manager import FeedbackManager
21
21
  from tinybird.tb.modules.project import Project
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 0.0.1.dev212
3
+ Version: 0.0.1.dev214
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/forward/commands
6
6
  Author: Tinybird