tinybird 0.0.1.dev108__py3-none-any.whl → 0.0.1.dev110__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.

tinybird/sql.py CHANGED
@@ -9,6 +9,24 @@ valid_chars_name: str = string.ascii_letters + string.digits + "._`*<>+-'"
9
9
  valid_chars_fn: str = valid_chars_name + "[](),=!?:/ \n\t\r"
10
10
 
11
11
  INDEX_WHITELIST = ["minmax", "set", "bloom_filter", "ngrambf_v1", "tokenbf_v1"]
12
+ INDEX_SUPPORTED_TYPES = {
13
+ "bloom_filter": [
14
+ "Int*",
15
+ "UInt*",
16
+ "Float*",
17
+ "Enum",
18
+ "Date",
19
+ "DateTime",
20
+ "String",
21
+ "FixedString",
22
+ "Array",
23
+ "LowCardinality",
24
+ "Nullable",
25
+ "UUID",
26
+ "Map",
27
+ ],
28
+ "ngrambf_v1": ["String", "FixedString", "Map"],
29
+ }
12
30
 
13
31
 
14
32
  @dataclass
@@ -39,12 +57,37 @@ class TableIndex:
39
57
  def clear_index_sql(self):
40
58
  return f"CLEAR INDEX IF EXISTS {self.name}"
41
59
 
42
- def validate_allowed(self):
60
+ def _validate_index_type(self, table_structure: List[Dict[str, Any]]):
61
+ for col in table_structure:
62
+ if col["normalized_name"] != self.expr:
63
+ continue
64
+ col_type = col["type"]
65
+ index_supported_types: Optional[str] = next((t for t in INDEX_SUPPORTED_TYPES if t in self.type_full), None)
66
+
67
+ if index_supported_types:
68
+ for supported_type in INDEX_SUPPORTED_TYPES.get(index_supported_types, []):
69
+ # Convert supported type to regex pattern
70
+ # Replace * with \d+ to match any number
71
+ pattern = supported_type.replace("*", r"\d+")
72
+ if re.match(f"^{pattern}$", col_type):
73
+ return
74
+ raise ValueError(
75
+ f"Not allowed data type '{col_type}' for index '{self.type_full}' for column '{self.expr}' "
76
+ )
77
+
78
+ def validate_allowed(self, table_structure: Optional[List[Dict[str, Any]]] = None):
43
79
  """
44
80
  Validate at API level not to depend on CLI version
45
81
  """
46
82
  if not any(index in self.type_full for index in INDEX_WHITELIST):
47
83
  raise ValueError(f"Not allowed index '{self.type_full}'")
84
+ try:
85
+ if table_structure:
86
+ self._validate_index_type(table_structure)
87
+ except ValueError as e:
88
+ raise e
89
+ except Exception:
90
+ logging.exception(f"Error validating index '{self.type_full}' for column '{self.expr}'")
48
91
 
49
92
 
50
93
  @dataclass
tinybird/tb/__cli__.py CHANGED
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
4
4
  __url__ = 'https://www.tinybird.co/docs/cli/introduction.html'
5
5
  __author__ = 'Tinybird'
6
6
  __author_email__ = 'support@tinybird.co'
7
- __version__ = '0.0.1.dev108'
8
- __revision__ = '1909c2e'
7
+ __version__ = '0.0.1.dev110'
8
+ __revision__ = '034b6bf'
@@ -49,7 +49,7 @@ jobs:
49
49
  steps:
50
50
  - uses: actions/checkout@v3
51
51
  - name: Install Tinybird CLI
52
- run: curl -LsSf https://api.tinybird.co/static/install.sh | sh
52
+ run: curl https://tinybird.co | sh
53
53
  - name: Build project
54
54
  run: tb build
55
55
  - name: Test project
@@ -81,7 +81,7 @@ jobs:
81
81
  steps:
82
82
  - uses: actions/checkout@v3
83
83
  - name: Install Tinybird CLI
84
- run: curl -LsSf https://api.tinybird.co/static/install.sh | sh
84
+ run: curl https://tinybird.co | sh
85
85
  - name: Deploy project
86
86
  run: tb --cloud --host ${{! env.TINYBIRD_HOST }} --token ${{! env.TINYBIRD_TOKEN }} deploy
87
87
  """
@@ -110,7 +110,7 @@ tinybird_ci_workflow:
110
110
  - {{ data_project_dir }}/**/*{% end %}
111
111
  before_script:
112
112
  - apt update && apt install -y curl
113
- - curl -LsSf https://api.tinybird.co/static/install.sh | sh
113
+ - curl https://tinybird.co | sh
114
114
  script:
115
115
  - export PATH="$HOME/.local/bin:$PATH"
116
116
  - cd $CI_PROJECT_DIR/{{ data_project_dir }}
@@ -191,6 +191,14 @@ KAFKA_PARAMS = {
191
191
 
192
192
  REQUIRED_KAFKA_PARAMS = KAFKA_PARAMS
193
193
 
194
+ S3_PARAMS = {
195
+ "import_connection_name",
196
+ "import_schedule",
197
+ "import_bucket_uri",
198
+ }
199
+
200
+ REQUIRED_S3_PARAMS = S3_PARAMS
201
+
194
202
 
195
203
  class Datafile:
196
204
  def __init__(self) -> None:
@@ -261,6 +269,7 @@ class Datafile:
261
269
  # [x] Engine is present
262
270
  # [x] Token permissions are valid
263
271
  # [x] If it's a kafka datasource, all required kafka params are present
272
+ # [x] If it's an S3 datasource, all required S3 params are present
264
273
  # [ ] ...
265
274
  if len(self.nodes) > 1:
266
275
  # Our users are not aware of data source data files being a single-node data file, hence this error
@@ -283,6 +292,12 @@ class Datafile:
283
292
  raise DatafileValidationError(
284
293
  f"Some Kafka params have been provided, but the following required ones are missing: {missing}"
285
294
  )
295
+ # Validate S3 params
296
+ if any(param in node for param in S3_PARAMS) and not all(param in node for param in REQUIRED_S3_PARAMS):
297
+ missing = [param for param in S3_PARAMS if param not in node]
298
+ raise DatafileValidationError(
299
+ f"Some S3 params have been provided, but the following required ones are missing: {missing}"
300
+ )
286
301
  else:
287
302
  # We cannot validate a datafile whose kind is unknown
288
303
  pass
@@ -1,12 +1,14 @@
1
1
  import re
2
2
  import subprocess
3
3
  import time
4
+ from typing import Optional
4
5
 
5
6
  import boto3
6
7
  import click
7
8
 
8
9
  import docker
9
10
  from docker.client import DockerClient
11
+ from docker.models.containers import Container
10
12
  from tinybird.tb.modules.cli import cli
11
13
  from tinybird.tb.modules.common import coro
12
14
  from tinybird.tb.modules.exceptions import CLIException
@@ -41,10 +43,9 @@ def start_tinybird_local(
41
43
  if pull_required:
42
44
  docker_client.images.pull(TB_IMAGE_NAME, platform="linux/amd64")
43
45
 
44
- container = None
45
- containers = docker_client.containers.list(all=True, filters={"name": TB_CONTAINER_NAME})
46
- if containers:
47
- container = containers[0]
46
+ environment = get_use_aws_creds() if use_aws_creds else {}
47
+
48
+ container = get_existing_container_with_matching_env(docker_client, TB_CONTAINER_NAME, environment)
48
49
 
49
50
  if container and not pull_required:
50
51
  # Container `start` is idempotent. It's safe to call it even if the container is already running.
@@ -53,8 +54,6 @@ def start_tinybird_local(
53
54
  if container:
54
55
  container.remove(force=True)
55
56
 
56
- environment = get_use_aws_creds() if use_aws_creds else {}
57
-
58
57
  container = docker_client.containers.run(
59
58
  TB_IMAGE_NAME,
60
59
  name=TB_CONTAINER_NAME,
@@ -82,6 +81,43 @@ def start_tinybird_local(
82
81
  image.remove(force=True)
83
82
 
84
83
 
84
+ def get_existing_container_with_matching_env(
85
+ docker_client: DockerClient, container_name: str, required_env: dict[str, str]
86
+ ) -> Optional[Container]:
87
+ """
88
+ Checks if a container with the given name exists and has matching environment variables.
89
+ If it exists but environment doesn't match, it returns None.
90
+
91
+ Args:
92
+ docker_client: The Docker client instance
93
+ container_name: The name of the container to check
94
+ required_env: Dictionary of environment variables that must be present
95
+
96
+ Returns:
97
+ The container if it exists with matching environment, None otherwise
98
+ """
99
+ container = None
100
+ containers = docker_client.containers.list(all=True, filters={"name": container_name})
101
+ if containers:
102
+ container = containers[0]
103
+
104
+ if container and required_env:
105
+ container_info = container.attrs
106
+ container_env = container_info.get("Config", {}).get("Env", [])
107
+ env_missing = False
108
+ for key, value in required_env.items():
109
+ env_var = f"{key}={value}"
110
+ if env_var not in container_env:
111
+ env_missing = True
112
+ break
113
+
114
+ if env_missing:
115
+ container.remove(force=True)
116
+ container = None
117
+
118
+ return container
119
+
120
+
85
121
  def get_docker_client() -> DockerClient:
86
122
  """Check if Docker is installed and running."""
87
123
  try:
@@ -156,7 +192,7 @@ def update_cli():
156
192
  text=True,
157
193
  )
158
194
  except FileNotFoundError:
159
- raise CLIException("Cannot find required tool: uv. Reinstall using: curl -LsSf tbrd.co/fwd | sh")
195
+ raise CLIException("Cannot find required tool: uv. Reinstall using: curl https://tinybird.co | sh")
160
196
 
161
197
  stdout, stderr = process.communicate()
162
198
  if "Nothing to upgrade" not in stdout + stderr:
@@ -208,7 +244,12 @@ async def remove() -> None:
208
244
 
209
245
  @local.command()
210
246
  @coro
211
- @click.option("--use-aws-creds", default=False, is_flag=True, help="Use local AWS credentials")
247
+ @click.option(
248
+ "--use-aws-creds",
249
+ default=False,
250
+ is_flag=True,
251
+ help="Use local AWS credentials from your environment and pass them to the Tinybird docker container",
252
+ )
212
253
  async def start(use_aws_creds: bool) -> None:
213
254
  """Start Tinybird Local"""
214
255
  click.echo(FeedbackManager.highlight(message="» Starting Tinybird Local..."))
@@ -219,7 +260,12 @@ async def start(use_aws_creds: bool) -> None:
219
260
 
220
261
  @local.command()
221
262
  @coro
222
- @click.option("--use-aws-creds", is_flag=True, help="Use local AWS credentials")
263
+ @click.option(
264
+ "--use-aws-creds",
265
+ default=False,
266
+ is_flag=True,
267
+ help="Use local AWS credentials from your environment and pass them to the Tinybird docker container",
268
+ )
223
269
  async def restart(use_aws_creds: bool) -> None:
224
270
  """Restart Tinybird Local"""
225
271
  click.echo(FeedbackManager.highlight(message="» Restarting Tinybird Local..."))
@@ -113,6 +113,9 @@ def start_server(auth_callback, auth_host):
113
113
  @coro
114
114
  async def login(host: str, auth_host: str, workspace: str):
115
115
  """Authenticate using the browser."""
116
+ host = host.rstrip("/")
117
+ auth_host = auth_host.rstrip("/")
118
+
116
119
  auth_event = threading.Event()
117
120
  auth_code: list[str] = [] # Using a list to store the code, as it's mutable
118
121
 
@@ -153,8 +156,8 @@ async def login(host: str, auth_host: str, workspace: str):
153
156
  cli_config.set_token(data.get("workspace_token", ""))
154
157
  cli_config.set_token_for_host(data.get("workspace_token", ""), host)
155
158
  cli_config.set_user_token(data.get("user_token", ""))
156
- cli_config.set_host(host or data.get("api_host", ""))
157
-
159
+ host = data.get("api_host", host)
160
+ cli_config.set_host(host)
158
161
  ws = await cli_config.get_client(token=data.get("workspace_token", ""), host=host).workspace_info(version="v1")
159
162
  for k in ("id", "name", "user_email", "user_id", "scope"):
160
163
  if k in ws:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 0.0.1.dev108
3
+ Version: 0.0.1.dev110
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -7,7 +7,7 @@ tinybird/datatypes.py,sha256=XNypumfqNjsvLJ5iNXnbVHRvAJe0aQwI3lS6Cxox-e0,10979
7
7
  tinybird/feedback_manager.py,sha256=a_ZhFX2zcB7vRknIcmHKMdQbb0c7TqlTBQ_5hPuWh88,69267
8
8
  tinybird/git_settings.py,sha256=Sw_8rGmribEFJ4Z_6idrVytxpFYk7ez8ei0qHULzs3E,3934
9
9
  tinybird/prompts.py,sha256=0i4Bzg-60lV6NlrQ1Vu6NZ_2we3GqV3rExu77YfA0V4,33889
10
- tinybird/sql.py,sha256=J35bhdpuu84HW2tiLp-cs_nzkRwPhiy1yPcFhcWMCR4,46248
10
+ tinybird/sql.py,sha256=C_B81wwv3BsqyXGhF5oTk9DcTUkrp7NwIFqSzd3Dmjc,47854
11
11
  tinybird/sql_template.py,sha256=mK0yeRFctbXTAu0VNMjIzoFBJoh9PoniAVgEatA5SG4,99832
12
12
  tinybird/sql_template_fmt.py,sha256=KUHdj5rYCYm_rKKdXYSJAE9vIyXUQLB0YSZnUXHeBlY,10196
13
13
  tinybird/sql_toolset.py,sha256=KORVbNAUTfW1qo3U9oe7Z59xQ0QMsFhB0ji3HzY2JVo,15324
@@ -15,11 +15,11 @@ tinybird/syncasync.py,sha256=IPnOx6lMbf9SNddN1eBtssg8vCLHMt76SuZ6YNYm-Yk,27761
15
15
  tinybird/tornado_template.py,sha256=jjNVDMnkYFWXflmT8KU_Ssbo5vR8KQq3EJMk5vYgXRw,41959
16
16
  tinybird/ch_utils/constants.py,sha256=aYvg2C_WxYWsnqPdZB1ZFoIr8ZY-XjUXYyHKE9Ansj0,3890
17
17
  tinybird/ch_utils/engine.py,sha256=BZuPM7MFS7vaEKK5tOMR2bwSAgJudPrJt27uVEwZmTY,40512
18
- tinybird/tb/__cli__.py,sha256=OSNR6WHHR8BSY9FOJAY3RW4JLaPIKXViXTAQ-ptYsYg,252
18
+ tinybird/tb/__cli__.py,sha256=nWZHU4E-KvHLB4OyR1gFO9T0XZFvxUwB3SRqcAoINyU,252
19
19
  tinybird/tb/cli.py,sha256=H_HaZhkimKgkryYXpBjHfY9Qtg-ZORiONU3psDNpzDk,1135
20
20
  tinybird/tb/modules/auth.py,sha256=L1IatO2arRSzys3t8px8xVt8uPWUL5EVD0sFzAV_uVU,9022
21
21
  tinybird/tb/modules/build.py,sha256=h5drdmDFX8NHts9dA2Zepao7KSgMAl3DZGyFufVZP78,11085
22
- tinybird/tb/modules/cicd.py,sha256=F0hQw-TExU9W3NpUSY-msNZ4tlaPeTXjRDpFZ2B2STU,7023
22
+ tinybird/tb/modules/cicd.py,sha256=k2hCout_N1g_rRAMWo_cf9tAGiJ1Puu5eiTV2DPob20,6939
23
23
  tinybird/tb/modules/cli.py,sha256=XtdwMI5uPoKfhlpSuCuhzODRJfTCx1oXHz_bn3x1OBg,16047
24
24
  tinybird/tb/modules/common.py,sha256=6AmvMe8Uj-5A46aUlM3wJg7AilkJEAmHt1hTOb5IH2w,82957
25
25
  tinybird/tb/modules/config.py,sha256=FqdLpLaKpYubqw3xkB4EX06ufZYDgGRxONR_9i-y-KE,11416
@@ -36,9 +36,9 @@ tinybird/tb/modules/infra.py,sha256=GA5xnYLlVItPfJu_3_5NIdHQDuyfk2Z71wtcn9NncGA,
36
36
  tinybird/tb/modules/job.py,sha256=956Pj8BEEsiD2GZsV9RKKVM3I_CveOLgS82lykO5ukk,2963
37
37
  tinybird/tb/modules/llm.py,sha256=AC0VSphTOM2t-v1_3NLvNN_FIbgMo4dTyMqIv5nniPo,835
38
38
  tinybird/tb/modules/llm_utils.py,sha256=nS9r4FAElJw8yXtmdYrx-rtI2zXR8qXfi1QqUDCfxvg,3469
39
- tinybird/tb/modules/local.py,sha256=4BhxfkSTHpckXmH4aU_BothlV5n4JyAIoBKX3wP_BZg,7863
39
+ tinybird/tb/modules/local.py,sha256=CYc35OxihraGUD3frLemz_7Tz_q6zZ9nf___CT1teuI,9332
40
40
  tinybird/tb/modules/local_common.py,sha256=RN5OEncHdq7ua4AZ--WgKtaFuEsLvIhq_ROHJadRXXA,3188
41
- tinybird/tb/modules/login.py,sha256=98b7obc1yQtDtoB-88yyEj_X99ZvVRB13q261AMKJBM,6270
41
+ tinybird/tb/modules/login.py,sha256=lLCJ1kIq3sLcoSMH1kZge5isHh-fDwHPRHApIqbaCkw,6350
42
42
  tinybird/tb/modules/logout.py,sha256=ULooy1cDBD02-r7voZmhV7udA0ML5tVuflJyShrh56Y,1022
43
43
  tinybird/tb/modules/materialization.py,sha256=r8Q9HXcYEmfrEzP4WpiasCKDJdSkTPaAKJtZMoJKhi8,5749
44
44
  tinybird/tb/modules/mock.py,sha256=2E26N8TMK1sP7eRc9N1nODdc_vU1jBeGRs8e-fbQ5Dc,4516
@@ -61,7 +61,7 @@ tinybird/tb/modules/datafile/build.py,sha256=jhfIJ2xt0N13XsLPe3iMQIyCPApHS13_Df2
61
61
  tinybird/tb/modules/datafile/build_common.py,sha256=rT7VJ5mnQ68R_8US91DAtkusfvjWuG_NObOzNgtN_ko,4562
62
62
  tinybird/tb/modules/datafile/build_datasource.py,sha256=CCU3eQ8Rax9RgHHfbAXDRL6rQ49N35h_GDQnGrUUUzA,17379
63
63
  tinybird/tb/modules/datafile/build_pipe.py,sha256=w-Wd08gZYAEcak9FdBijVfIU2_Wn_PPdgAZddPpoGTo,11382
64
- tinybird/tb/modules/datafile/common.py,sha256=4Jv20MUMaQl2NlbviRGHH41ncoDc6h9g4IWC0nl0j3M,82579
64
+ tinybird/tb/modules/datafile/common.py,sha256=4pvW92X9BXomaN3-WhQOjvnAHY96O4dTsp4USBdknzk,83192
65
65
  tinybird/tb/modules/datafile/diff.py,sha256=-0J7PsBO64T7LOZSkZ4ZFHHCPvT7cKItnJkbz2PkndU,6754
66
66
  tinybird/tb/modules/datafile/exceptions.py,sha256=8rw2umdZjtby85QbuRKFO5ETz_eRHwUY5l7eHsy1wnI,556
67
67
  tinybird/tb/modules/datafile/fixture.py,sha256=si-9LB-LdKQSWDtVW82xDrHtFfko5bgBG1cvjqqrcPU,1064
@@ -81,8 +81,8 @@ tinybird/tb_cli_modules/config.py,sha256=IsgdtFRnUrkY8-Zo32lmk6O7u3bHie1QCxLwgp4
81
81
  tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
82
82
  tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
83
83
  tinybird/tb_cli_modules/telemetry.py,sha256=Hh2Io8ZPROSunbOLuMvuIFU4TqwWPmQTqal4WS09K1A,10449
84
- tinybird-0.0.1.dev108.dist-info/METADATA,sha256=gXcf738MA5OAGkVcougBzsBLqsPi-1fff5sNv6bAjGU,1612
85
- tinybird-0.0.1.dev108.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
86
- tinybird-0.0.1.dev108.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
87
- tinybird-0.0.1.dev108.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
88
- tinybird-0.0.1.dev108.dist-info/RECORD,,
84
+ tinybird-0.0.1.dev110.dist-info/METADATA,sha256=lQOlesa4BTowVCtRXrLSiOr1GzGDu5MUncxDYbXbWgI,1612
85
+ tinybird-0.0.1.dev110.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
86
+ tinybird-0.0.1.dev110.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
87
+ tinybird-0.0.1.dev110.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
88
+ tinybird-0.0.1.dev110.dist-info/RECORD,,