tinybird 0.0.1.dev223__py3-none-any.whl → 0.0.1.dev225__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.

@@ -1710,6 +1710,8 @@ def parse(
1710
1710
  "s3_access_key": assign_var("s3_access_key"),
1711
1711
  "s3_secret": assign_var("s3_secret"),
1712
1712
  "gcs_service_account_credentials_json": assign_var_json("gcs_service_account_credentials_json"),
1713
+ "gcs_access_id": assign_var("gcs_hmac_access_id"),
1714
+ "gcs_secret": assign_var("gcs_hmac_secret"),
1713
1715
  "gcs_hmac_access_id": assign_var("gcs_hmac_access_id"),
1714
1716
  "gcs_hmac_secret": assign_var("gcs_hmac_secret"),
1715
1717
  "include": include,
tinybird/prompts.py CHANGED
@@ -420,9 +420,11 @@ You are a Tinybird expert. You will be given a prompt to generate new or update
420
420
  {pipe_example}
421
421
  {copy_pipe_instructions}
422
422
  {materialized_pipe_instructions}
423
+ {sink_pipe_instructions}
423
424
  {connection_instructions}
424
425
  {kafka_connection_example}
425
426
  {gcs_connection_example}
427
+ {gcs_hmac_connection_example}
426
428
  {s3_connection_example}
427
429
 
428
430
  {feedback_history}
@@ -445,9 +447,11 @@ Use the following format to generate the response and do not wrap it in any othe
445
447
  pipe_example=pipe_example,
446
448
  copy_pipe_instructions=copy_pipe_instructions,
447
449
  materialized_pipe_instructions=materialized_pipe_instructions,
450
+ sink_pipe_instructions=sink_pipe_instructions,
448
451
  connection_instructions=connection_instructions,
449
452
  kafka_connection_example=kafka_connection_example,
450
453
  gcs_connection_example=gcs_connection_example,
454
+ gcs_hmac_connection_example=gcs_hmac_connection_example,
451
455
  s3_connection_example=s3_connection_example,
452
456
  feedback_history=feedback_history,
453
457
  )
@@ -639,6 +643,43 @@ COPY_SCHEDULE 0 * * * *
639
643
  </copy_pipe_instructions>
640
644
  """
641
645
 
646
+ sink_pipe_instructions = """
647
+ <sink_pipe_instructions>
648
+ - Do not create sink pipes by default, unless the user asks for it.
649
+ - Sink pipes should be created in the /sinks folder.
650
+ - In a .pipe file you can define how to export the result of a Pipe to an external system, optionally with a schedule.
651
+ - Valid external systems are Kafka, S3, GCS.
652
+ - Sink pipes depend on a connection, if no connection is provided, search for an existing connection that suits the request. If none, create a new connection.
653
+ - Do not include EXPORT_SCHEDULE in the .pipe file unless is specifically requested by the user.
654
+ - EXPORT_SCHEDULE is a cron expression that defines the schedule of the sink pipe.
655
+ - EXPORT_SCHEDULE is optional and if not provided, the sink pipe will be executed only once.
656
+ - EXPORT_CONNECTION_NAME is the name of the connection used to export.
657
+ - TYPE SINK is the type of the pipe and it is mandatory for sink pipes.
658
+ - If the sink pipe uses parameters, you must include the % character and a newline on top of every query to be able to use the parameters.
659
+ - The content of the .pipe file must follow this format:
660
+ DESCRIPTION Sink Pipe to export sales hour every hour using my_connection
661
+
662
+ NODE daily_sales
663
+ SQL >
664
+ %
665
+ SELECT toStartOfDay(starting_date) day, country, sum(sales) as total_sales
666
+ FROM teams
667
+ WHERE
668
+ day BETWEEN toStartOfDay(now()) - interval 1 day AND toStartOfDay(now())
669
+ and country = {{ String(country, 'US')}}
670
+ GROUP BY day, country
671
+
672
+ TYPE sink
673
+ EXPORT_CONNECTION_NAME "my_connection"
674
+ EXPORT_BUCKET_URI "s3://tinybird-sinks"
675
+ EXPORT_FILE_TEMPLATE "daily_prices"
676
+ EXPORT_SCHEDULE "*/5 * * * *"
677
+ EXPORT_FORMAT "csv"
678
+ EXPORT_COMPRESSION "gz"
679
+ EXPORT_WRITE_STRATEGY "truncate"
680
+ </sink_pipe_instructions>
681
+ """
682
+
642
683
  materialized_pipe_instructions = """
643
684
  <materialized_pipe_instructions>
644
685
  - Do not create materialized pipes by default, unless the user asks for it.
@@ -709,6 +750,14 @@ GCS_SERVICE_ACCOUNT_CREDENTIALS_JSON {{ tb_secret("PRODUCTION_GCS_SERVICE_ACCOUN
709
750
  </gcs_connection_content>
710
751
  """
711
752
 
753
+ gcs_hmac_connection_example = """
754
+ <gcs_hmac_connection_content>
755
+ TYPE gcs
756
+ GCS_HMAC_ACCESS_ID {{ tb_secret("gcs_hmac_access_id") }}
757
+ GCS_HMAC_SECRET {{ tb_secret("gcs_hmac_secret") }}
758
+ </gcs_hmac_connection_content>
759
+ """
760
+
712
761
  s3_connection_example = """
713
762
  <s3_connection_content>
714
763
  TYPE s3
@@ -767,7 +816,7 @@ pipe_instructions = """
767
816
  - Nodes can't have the same exact name as the Pipe they belong to.
768
817
  - Avoid more than one node per pipe unless it is really necessary or requested by the user.
769
818
  - No indentation is allowed for property names: DESCRIPTION, NODE, SQL, TYPE, etc.
770
- - Allowed TYPE values are: endpoint, copy, materialized.
819
+ - Allowed TYPE values are: endpoint, copy, materialized, sink.
771
820
  - Add always the output node in the TYPE section or in the last node of the pipe.
772
821
  </pipe_file_instructions>
773
822
  """
@@ -847,17 +896,17 @@ You have commands at your disposal to develop a tinybird project:
847
896
  - {base_command} build: to build the project locally and check it works.
848
897
  - {base_command} deployment create --wait --auto: to create a deployment and promote it automatically
849
898
  - {base_command} test run: to run existing tests
850
- - {base_command} --build endpoint url <pipe_name>: to get the url of an endpoint, token included.
851
- - {base_command} --build endpoint data <pipe_name>: to get the data of an endpoint. You can pass parameters to the endpoint like this: {base_command} --build endpoint data <pipe_name> --param1 value1 --param2 value2
852
- - {base_command} --build token ls: to list all the tokens
899
+ - {base_command} endpoint url <pipe_name>: to get the url of an endpoint, token included.
900
+ - {base_command} endpoint data <pipe_name>: to get the data of an endpoint. You can pass parameters to the endpoint like this: {base_command} endpoint data <pipe_name> --param1 value1 --param2 value2
901
+ - {base_command} token ls: to list all the tokens
853
902
  There are other commands that you can use, but these are the most common ones. Run `{base_command} -h` to see all the commands if needed.
854
- When you need to work with resources or data in the Tinybird environment that you updated with the build command, add always the --build flag before the command. Example: {base_command} --build datasource ls
855
903
  When you need to work with resources or data in cloud, add always the --cloud flag before the command. Example: {base_command} --cloud datasource ls
856
904
  </command_calling>
857
905
  <development_instructions>
858
906
  - When asking to create a tinybird data project, if the needed folders are not already created, use the following structure:
859
907
  ├── connections
860
908
  ├── copies
909
+ ├── sinks
861
910
  ├── datasources
862
911
  ├── endpoints
863
912
  ├── fixtures
@@ -875,7 +924,7 @@ When asking for ingesting data, adding data or appending data do the following d
875
924
  - When building locally, create a .ndjson file with the data you want to ingest and do `{base_command} build` to ingest the data in the build env.
876
925
  - We call `cloud` the production environment.
877
926
  - When appending data in cloud, use `{base_command} --cloud datasource append <datasource_name> <file_name>`
878
- - When you have a response that says “there are rows in quarantine”, do `{base_command} --build|--cloud datasource data <datasource_name>_quarantine` to understand what is the problem.
927
+ - When you have a response that says “there are rows in quarantine”, do `{base_command} [--cloud] datasource data <datasource_name>_quarantine` to understand what is the problem.
879
928
  </ingest_data_instructions>
880
929
  <datasource_file_instructions>
881
930
  Follow these instructions when creating or updating .datasource files:
@@ -890,9 +939,11 @@ Follow these instructions when creating or updating .pipe files:
890
939
  {pipe_example}
891
940
  {copy_pipe_instructions}
892
941
  {materialized_pipe_instructions}
942
+ {sink_pipe_instructions}
893
943
  {connection_instructions}
894
944
  {kafka_connection_example}
895
945
  {gcs_connection_example}
946
+ {gcs_hmac_connection_example}
896
947
  {s3_connection_example}
897
948
  </pipe_file_instructions>
898
949
  <test_file_instructions>
@@ -912,11 +963,13 @@ Follow these instructions when evolving a datasource schema:
912
963
  pipe_example=pipe_example,
913
964
  copy_pipe_instructions=copy_pipe_instructions,
914
965
  materialized_pipe_instructions=materialized_pipe_instructions,
966
+ sink_pipe_instructions=sink_pipe_instructions,
915
967
  test_instructions=test_instructions,
916
968
  deployment_instructions=deployment_instructions,
917
969
  connection_instructions=connection_instructions,
918
970
  kafka_connection_example=kafka_connection_example,
919
971
  gcs_connection_example=gcs_connection_example,
972
+ gcs_hmac_connection_example=gcs_hmac_connection_example,
920
973
  s3_connection_example=s3_connection_example,
921
974
  )
922
975
 
tinybird/tb/__cli__.py CHANGED
@@ -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.dev223'
8
- __revision__ = '3fd90ce'
7
+ __version__ = '0.0.1.dev225'
8
+ __revision__ = 'ddc2523'
@@ -1761,18 +1761,11 @@ async def run_aws_iamrole_connection_flow(
1761
1761
 
1762
1762
  async def run_gcp_svc_account_connection_flow(
1763
1763
  environment: str,
1764
- ) -> Tuple[str, str, str]:
1765
- bucket_name = click.prompt(
1766
- "📦 Bucket name (specific name recommended, use '*' for unrestricted access in IAM policy)",
1767
- prompt_suffix="\n> ",
1768
- )
1769
- validate_string_connector_param("Bucket", bucket_name)
1770
-
1764
+ ) -> None:
1771
1765
  click.echo(FeedbackManager.prompt_gcs_svc_account_login_gcp())
1772
1766
  click.echo(FeedbackManager.click_enter_to_continue())
1773
1767
  input()
1774
1768
 
1775
- # Display message and wait for user to press Enter
1776
1769
  click.echo(FeedbackManager.prompt_gcs_service_account_creation_flow(environment=environment))
1777
1770
  click.echo(FeedbackManager.click_enter_to_continue())
1778
1771
  input()
@@ -1781,8 +1774,6 @@ async def run_gcp_svc_account_connection_flow(
1781
1774
  click.echo(FeedbackManager.click_enter_to_continue())
1782
1775
  input()
1783
1776
 
1784
- return bucket_name
1785
-
1786
1777
 
1787
1778
  async def production_aws_iamrole_only(
1788
1779
  prod_client: TinyB,
@@ -203,7 +203,10 @@ async def connection_create_s3(ctx: Context) -> None:
203
203
  )
204
204
  unique_suffix = uuid.uuid4().hex[:8] # Use first 8 chars of a UUID for brevity
205
205
  secret_name = f"s3_role_arn_{connection_name}_{unique_suffix}"
206
- save_secret_to_env_file(project=project, name=secret_name, value=role_arn)
206
+ if obj["env"] == "local":
207
+ save_secret_to_env_file(project=project, name=secret_name, value=role_arn)
208
+ else:
209
+ await client.create_secret(name=secret_name, value=role_arn)
207
210
 
208
211
  create_in_cloud = (
209
212
  click.confirm(FeedbackManager.prompt_connection_in_cloud_confirmation(), default=True)
@@ -267,15 +270,19 @@ async def connection_create_gcs(ctx: Context) -> None:
267
270
  """
268
271
  project: Project = ctx.ensure_object(dict)["project"]
269
272
  obj: Dict[str, Any] = ctx.ensure_object(dict)
273
+ client: TinyB = obj["client"]
270
274
 
271
275
  service = DataConnectorType.GCLOUD_STORAGE
272
276
  click.echo(FeedbackManager.prompt_gcs_connection_header())
273
277
  connection_name = get_gcs_connection_name(project.folder)
274
- _ = await run_gcp_svc_account_connection_flow(environment=obj["env"])
278
+ await run_gcp_svc_account_connection_flow(environment=obj["env"])
275
279
  creds_json = get_gcs_svc_account_creds()
276
280
  unique_suffix = uuid.uuid4().hex[:8] # Use first 8 chars of a UUID for brevity
277
281
  secret_name = f"gcs_svc_account_creds_{connection_name}_{unique_suffix}"
278
- save_secret_to_env_file(project=project, name=secret_name, value=creds_json)
282
+ if obj["env"] == "local":
283
+ save_secret_to_env_file(project=project, name=secret_name, value=creds_json)
284
+ else:
285
+ await client.create_secret(name=secret_name, value=creds_json)
279
286
 
280
287
  connection_path = await generate_gcs_connection_file_with_secrets(
281
288
  name=connection_name,
@@ -197,7 +197,17 @@ async def create(
197
197
  raise CLICreateException(FeedbackManager.error(message=str(e)))
198
198
 
199
199
 
200
- PROJECT_PATHS = ("datasources", "endpoints", "materializations", "copies", "pipes", "fixtures", "tests", "connections")
200
+ PROJECT_PATHS = (
201
+ "datasources",
202
+ "endpoints",
203
+ "materializations",
204
+ "copies",
205
+ "sinks",
206
+ "pipes",
207
+ "fixtures",
208
+ "tests",
209
+ "connections",
210
+ )
201
211
 
202
212
 
203
213
  def validate_project_structure(project: Project) -> bool:
@@ -248,6 +258,7 @@ def create_project_structure(folder: str):
248
258
  "endpoints →": "Expose real-time HTTP APIs of your transformed data.",
249
259
  "materializations →": "Stream continuous updates of the result of a pipe into a new data source.",
250
260
  "copies →": "Capture the result of a pipe at a moment in time and write it into a target data source.",
261
+ "sinks →": "Export your data to external systems on a scheduled or on-demand basis.",
251
262
  "pipes →": "Transform your data and reuse the logic in endpoints, materializations and copies.",
252
263
  "fixtures →": "Files with sample data for your project.",
253
264
  "tests →": "Test your pipe files with data validation tests.",
@@ -631,7 +631,12 @@ STEP 2: CREATE GCP SERVICE ACCOUNT
631
631
  1. Go to IAM & Admin > Service Accounts > + Create Service Account: https://console.cloud.google.com/iam-admin/serviceaccounts/create
632
632
  2. Provide a service account name. Name the service account something meaningful (e.g., TinybirdGCS-{environment}-svc-account)
633
633
  3. Click "Create and continue"
634
- 4. Click the "Select a role" drop down menu and select "Storage Object Viewer" (You can add IAM condition to provide access to selected buckets. More info in IAM Conditions: https://www.tinybird.co/docs/forward/get-data-in/connectors/gcs)
634
+ 4. Click the "Select a role" drop down menu and select:
635
+ - "Storage Object Viewer" for GCS Data Source (reading from GCS)
636
+ - For GCS Sink (writing to GCS), select all three roles:
637
+ • "Storage Object Creator" - Allows users to create objects
638
+ • "Storage Object Viewer" - Grants access to view objects and their metadata
639
+ (You can add IAM condition to provide access to selected buckets. More info in IAM Conditions: https://cloud.google.com/iam/docs/conditions-overview)
635
640
  5. Click "Done"
636
641
  """
637
642
  )
@@ -654,7 +659,9 @@ STEP 3: ADD KEY TO SERVICE ACCOUNT
654
659
 
655
660
  • File created at: {connection_path}
656
661
  • You can now use this connection in your Data Sources with: IMPORT_CONNECTION_NAME '{connection_name}'
662
+ • You can also use this connection in your Pipes with: EXPORT_CONNECTION_NAME '{connection_name}'
657
663
  • Learn more about our GCS Connector: https://www.tinybird.co/docs/forward/get-data-in/connectors/gcs
664
+ • Learn more about our GCS Sinks: https://www.tinybird.co/docs/forward/work-with-data/publish-data/gcs-sinks
658
665
  """)
659
666
 
660
667
  prompt_init_git_release_pull = prompt_message(
@@ -1,8 +1,10 @@
1
1
  import http.server
2
2
  import os
3
3
  import platform
4
+ import random
4
5
  import shutil
5
6
  import socketserver
7
+ import string
6
8
  import subprocess
7
9
  import sys
8
10
  import threading
@@ -127,8 +129,14 @@ def start_server(auth_callback, auth_host):
127
129
  default=False,
128
130
  help="Show available regions and select where to authenticate to",
129
131
  )
132
+ @click.option(
133
+ "--method",
134
+ type=click.Choice(["browser", "code"]),
135
+ default="browser",
136
+ help="Set the authentication method to use. Default: browser.",
137
+ )
130
138
  @coro
131
- async def login(host: Optional[str], auth_host: str, workspace: str, interactive: bool):
139
+ async def login(host: Optional[str], auth_host: str, workspace: str, interactive: bool, method: str):
132
140
  """Authenticate using the browser."""
133
141
  try:
134
142
  cli_config = CLIConfig.get_project_config()
@@ -154,6 +162,49 @@ async def login(host: Optional[str], auth_host: str, workspace: str, interactive
154
162
  host = host.rstrip("/")
155
163
  auth_host = auth_host.rstrip("/")
156
164
 
165
+ if method == "code":
166
+ display_code, one_time_code = create_one_time_code()
167
+ click.echo(FeedbackManager.info(message=f"First, copy your one-time code: {display_code}"))
168
+ click.echo(FeedbackManager.info(message="Press [Enter] to continue in the browser..."))
169
+ input()
170
+ click.echo(FeedbackManager.highlight(message="» Opening browser for authentication..."))
171
+ params = {
172
+ "apiHost": host,
173
+ "code": one_time_code,
174
+ "method": "code",
175
+ }
176
+ auth_url = f"{auth_host}/api/cli-login?{urlencode(params)}"
177
+ open_url(auth_url)
178
+ click.echo(
179
+ FeedbackManager.info(message="\nIf browser does not open, please open the following URL manually:")
180
+ )
181
+ click.echo(FeedbackManager.info(message=auth_url))
182
+
183
+ async def poll_for_tokens():
184
+ while True:
185
+ params = {
186
+ "apiHost": host,
187
+ "cliCode": one_time_code,
188
+ "method": "code",
189
+ }
190
+ response = requests.get(f"{auth_host}/api/cli-login?{urlencode(params)}") # noqa: ASYNC210
191
+
192
+ try:
193
+ if response.status_code == 200:
194
+ data = response.json()
195
+ user_token = data.get("user_token", "")
196
+ workspace_token = data.get("workspace_token", "")
197
+ if user_token and workspace_token:
198
+ await authenticate_with_tokens(data, host, cli_config)
199
+ break
200
+ except Exception:
201
+ pass
202
+
203
+ time.sleep(2) # noqa: ASYNC251
204
+
205
+ await poll_for_tokens()
206
+ return
207
+
157
208
  auth_event = threading.Event()
158
209
  auth_code: list[str] = [] # Using a list to store the code, as it's mutable
159
210
 
@@ -190,32 +241,7 @@ async def login(host: Optional[str], auth_host: str, workspace: str, interactive
190
241
  )
191
242
 
192
243
  data = response.json()
193
- cli_config.set_token(data.get("workspace_token", ""))
194
- cli_config.set_token_for_host(data.get("workspace_token", ""), host)
195
- cli_config.set_user_token(data.get("user_token", ""))
196
- host = data.get("api_host", host)
197
- cli_config.set_host(host)
198
- ws = await cli_config.get_client(token=data.get("workspace_token", ""), host=host).workspace_info(
199
- version="v1"
200
- )
201
- for k in ("id", "name", "user_email", "user_id", "scope"):
202
- if k in ws:
203
- cli_config[k] = ws[k]
204
-
205
- path = os.path.join(os.getcwd(), ".tinyb")
206
- cli_config.persist_to_file(override_with_path=path)
207
-
208
- auth_info: Dict[str, Any] = await cli_config.get_user_client().check_auth_login()
209
- if not auth_info.get("is_valid", False):
210
- raise Exception(FeedbackManager.error_auth_login_not_valid(host=cli_config.get_host()))
211
-
212
- if not auth_info.get("is_user", False):
213
- raise Exception(FeedbackManager.error_auth_login_not_user(host=cli_config.get_host()))
214
-
215
- click.echo(FeedbackManager.gray(message="\nWorkspace: ") + FeedbackManager.info(message=ws["name"]))
216
- click.echo(FeedbackManager.gray(message="User: ") + FeedbackManager.info(message=ws["user_email"]))
217
- click.echo(FeedbackManager.gray(message="Host: ") + FeedbackManager.info(message=host))
218
- click.echo(FeedbackManager.success(message="\n✓ Authentication successful!"))
244
+ await authenticate_with_tokens(data, host, cli_config)
219
245
  else:
220
246
  raise Exception("Authentication failed or timed out.")
221
247
  except Exception as e:
@@ -272,3 +298,38 @@ def open_url(url: str, *, new_tab: bool = False) -> bool:
272
298
 
273
299
  # 5. If everything failed, let the caller know.
274
300
  return False
301
+
302
+
303
+ def create_one_time_code():
304
+ """Create a random one-time code for the authentication process in the format of A2C4-D2G4 (only uppercase letters and digits)"""
305
+ seperator = "-"
306
+ full_code = "".join(random.choices(string.ascii_uppercase + string.digits, k=8))
307
+ parts = [full_code[:4], full_code[4:]]
308
+ return seperator.join(parts), full_code
309
+
310
+
311
+ async def authenticate_with_tokens(data: Dict[str, Any], host: Optional[str], cli_config: CLIConfig):
312
+ cli_config.set_token(data.get("workspace_token", ""))
313
+ host = host or data.get("api_host", "")
314
+ cli_config.set_token_for_host(data.get("workspace_token", ""), host)
315
+ cli_config.set_user_token(data.get("user_token", ""))
316
+ cli_config.set_host(host)
317
+ ws = await cli_config.get_client(token=data.get("workspace_token", ""), host=host).workspace_info(version="v1")
318
+ for k in ("id", "name", "user_email", "user_id", "scope"):
319
+ if k in ws:
320
+ cli_config[k] = ws[k]
321
+
322
+ path = os.path.join(os.getcwd(), ".tinyb")
323
+ cli_config.persist_to_file(override_with_path=path)
324
+
325
+ auth_info: Dict[str, Any] = await cli_config.get_user_client().check_auth_login()
326
+ if not auth_info.get("is_valid", False):
327
+ raise Exception(FeedbackManager.error_auth_login_not_valid(host=cli_config.get_host()))
328
+
329
+ if not auth_info.get("is_user", False):
330
+ raise Exception(FeedbackManager.error_auth_login_not_user(host=cli_config.get_host()))
331
+
332
+ click.echo(FeedbackManager.gray(message="\nWorkspace: ") + FeedbackManager.info(message=ws["name"]))
333
+ click.echo(FeedbackManager.gray(message="User: ") + FeedbackManager.info(message=ws["user_email"]))
334
+ click.echo(FeedbackManager.gray(message="Host: ") + FeedbackManager.info(message=host))
335
+ click.echo(FeedbackManager.success(message="\n✓ Authentication successful!"))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 0.0.1.dev223
3
+ Version: 0.0.1.dev225
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/forward/commands
6
6
  Author: Tinybird
@@ -3,7 +3,7 @@ tinybird/context.py,sha256=FfqYfrGX_I7PKGTQo93utaKPDNVYWelg4Hsp3evX5wM,1291
3
3
  tinybird/datatypes.py,sha256=r4WCvspmrXTJHiPjjyOTiZyZl31FO3Ynkwq4LQsYm6E,11059
4
4
  tinybird/feedback_manager.py,sha256=1INQFfRfuMCb9lfB8KNf4r6qC2khW568hoHjtk-wshI,69305
5
5
  tinybird/git_settings.py,sha256=Sw_8rGmribEFJ4Z_6idrVytxpFYk7ez8ei0qHULzs3E,3934
6
- tinybird/prompts.py,sha256=XScvI-IUOJ1gdXBdENUUCu13dHSepSnCliGXlvsKS4Q,38880
6
+ tinybird/prompts.py,sha256=VELVeJzSyGJULFML9eXytMG_3Ett0xKwNVRLBNP6TIs,40954
7
7
  tinybird/sql.py,sha256=BufnOgclQokDyihtuXesOwHBsebN6wRXIxO5wKRkOwE,48299
8
8
  tinybird/sql_template.py,sha256=WjsTBjpQLVBHGZbY2dZuhZUurFR-rbJ_KRRy5vx4Y5E,99967
9
9
  tinybird/sql_template_fmt.py,sha256=KUHdj5rYCYm_rKKdXYSJAE9vIyXUQLB0YSZnUXHeBlY,10196
@@ -12,12 +12,12 @@ tinybird/syncasync.py,sha256=IPnOx6lMbf9SNddN1eBtssg8vCLHMt76SuZ6YNYm-Yk,27761
12
12
  tinybird/tornado_template.py,sha256=jjNVDMnkYFWXflmT8KU_Ssbo5vR8KQq3EJMk5vYgXRw,41959
13
13
  tinybird/ch_utils/constants.py,sha256=yEKR11gLCL-irEXXF9QwShaR0JLXiBTlaxfolcCIoqY,4097
14
14
  tinybird/ch_utils/engine.py,sha256=X4tE9OrfaUy6kO9cqVEzyI9cDcmOF3IAssRRzsTsfEQ,40781
15
- tinybird/datafile/common.py,sha256=9hC1APatnfFeYXyTm_s47VmXP0JUajvpkw1vsrSXo70,91664
15
+ tinybird/datafile/common.py,sha256=W8HtbKVLe8Fr8Q1x3xw2DA-vroi8EZfvDJptAxiJVzQ,91784
16
16
  tinybird/datafile/exceptions.py,sha256=8rw2umdZjtby85QbuRKFO5ETz_eRHwUY5l7eHsy1wnI,556
17
17
  tinybird/datafile/parse_connection.py,sha256=tRyn2Rpr1TeWet5BXmMoQgaotbGdYep1qiTak_OqC5E,1825
18
18
  tinybird/datafile/parse_datasource.py,sha256=ssW8QeFSgglVFi3sDZj_HgkJiTJ2069v2JgqnH3CkDE,1825
19
19
  tinybird/datafile/parse_pipe.py,sha256=xf4m0Tw44QWJzHzAm7Z7FwUoUUtr7noMYjU1NiWnX0k,3880
20
- tinybird/tb/__cli__.py,sha256=MLMlpIY_kNVaKk4136zv78wFe159HhB0f9z8sGk6MbI,247
20
+ tinybird/tb/__cli__.py,sha256=yoNIdYpjihCJBWlrVYhBKJ8YPmuz0F1l8T1UsPRwrqQ,247
21
21
  tinybird/tb/check_pypi.py,sha256=i3l2L8IajeB7sreikR7oPlYJki9MtS3c_M4crnmbByc,760
22
22
  tinybird/tb/cli.py,sha256=0xYk2Ip4vb3nNFbxfTdG3VoIgdRvUKVbUVU_mviErPA,1107
23
23
  tinybird/tb/client.py,sha256=FKj61vY9STPW03kfVcxYuY1_csI-kP-mc1ERQfqJtg8,56505
@@ -25,18 +25,18 @@ tinybird/tb/config.py,sha256=jT9xndpeCY_g0HdB5qE2EquC0TFRRnkPnQFWZWd04jo,3998
25
25
  tinybird/tb/modules/build.py,sha256=T36msoBK5g9AZlrJnFRPvlZbrdE265LY1q3Y4YqvS3w,20067
26
26
  tinybird/tb/modules/cicd.py,sha256=Njb6eZOHHbUkoJJx6KoixO9PsfA_T-3Ybkya9-50Ca8,7328
27
27
  tinybird/tb/modules/cli.py,sha256=zTUob6oSZszCx-lk6MJbQ_VuNOXBo8b0DOHPWezzMOg,15997
28
- tinybird/tb/modules/common.py,sha256=WWvbDSQmyYUy9Xyc_BqtrdRzpDdzLuE9i_pWhoA1a8k,83440
28
+ tinybird/tb/modules/common.py,sha256=F6oaoFZ3aBxEMjiDKYhthsEIUqSFPkcdlMJ7h7A49Ac,83114
29
29
  tinybird/tb/modules/config.py,sha256=VnzYVUo4q1RBEEMMce4_OCrKp4erhgkRPHElydVlKj0,11488
30
- tinybird/tb/modules/connection.py,sha256=rdEsdcP-AqyHiW3KNoETGPeTjk7Wt3It6z_SnmInGcc,18648
30
+ tinybird/tb/modules/connection.py,sha256=dAOv8z3ym9Tt62j7AI8R9PgFwgiCIFdgIMpUiMdtxaQ,18906
31
31
  tinybird/tb/modules/copy.py,sha256=zHN1d5NA-MFsgbk2kKJq2P9qA8dNOnIsIa60QpVnSwc,4458
32
- tinybird/tb/modules/create.py,sha256=l3Q3QG8R-CXP-gj5rIXI3uD9tPBnQmzdklgkxt_ggNY,22106
32
+ tinybird/tb/modules/create.py,sha256=dRpzwv1GWqu1BqZtl1-AkFbap52adA-GwY-xf0qxIcw,22262
33
33
  tinybird/tb/modules/datasource.py,sha256=4a50A_qwB-3FUEUeB3ps6tUCJvn02rMUUwW-vHaMjTw,40846
34
34
  tinybird/tb/modules/deployment.py,sha256=ByXIgEvwxB49pJEKKj0EJIfORWyflCYr04k8961nBkA,28391
35
35
  tinybird/tb/modules/deprecations.py,sha256=rrszC1f_JJeJ8mUxGoCxckQTJFBCR8wREf4XXXN-PRc,4507
36
36
  tinybird/tb/modules/dev_server.py,sha256=57FCKuWpErwYUYgHspYDkLWEm9F4pbvVOtMrFXX1fVU,10129
37
37
  tinybird/tb/modules/endpoint.py,sha256=rC1CZiEZDMb5chByf4xZhv5PsfkoLeIVDScHQ-QcBsE,12072
38
38
  tinybird/tb/modules/exceptions.py,sha256=5jK91w1LPmtqIUfDpHe_Op5OxGz8-p1BPgtLREMIni0,5217
39
- tinybird/tb/modules/feedback_manager.py,sha256=Bw4xudrpVEb5x70JxtsxmvWkQfnWx_eKD2rTAOgjJvs,77433
39
+ tinybird/tb/modules/feedback_manager.py,sha256=AR7spZdOO_ya_5C8cGN3zb3vzAeu--HvAfj6pFGuw5k,77882
40
40
  tinybird/tb/modules/info.py,sha256=NqSsoyzFqbtUEGH_tSowNOI_jSsNuixibln6-plsfOY,6810
41
41
  tinybird/tb/modules/infra.py,sha256=fve30Gj3mG9zbquGxS2e4ipcOYOxviWQCpNFfEzJN_Q,33195
42
42
  tinybird/tb/modules/job.py,sha256=AsUCRNzy7HG5oJ4fyk9NpIm5NtNJgBZSy8MtJdXBe5A,3167
@@ -44,7 +44,7 @@ tinybird/tb/modules/llm.py,sha256=KfsCYmKeW1VQz0iDZhGKCRkQv_Y3kTHh6JuxvofOguE,10
44
44
  tinybird/tb/modules/llm_utils.py,sha256=nS9r4FAElJw8yXtmdYrx-rtI2zXR8qXfi1QqUDCfxvg,3469
45
45
  tinybird/tb/modules/local.py,sha256=TWT7pGXQ3cOy0M_piyw7WhrzoxZE18PmfOLzHD5CoEc,6096
46
46
  tinybird/tb/modules/local_common.py,sha256=8CSEVygFi0fIISatYxCStcHizugXCA9WNTLO_zDKmXw,17195
47
- tinybird/tb/modules/login.py,sha256=qfY17J3FryTPl8A0ucQgxiyJ7jLy81qHdlHXgqohi0c,10170
47
+ tinybird/tb/modules/login.py,sha256=VxxCzyjG5dpFm1lmlNPVcM-0-jqURAFp4HEkMMBdiGo,12617
48
48
  tinybird/tb/modules/logout.py,sha256=sniI4JNxpTrVeRCp0oGJuQ3yRerG4hH5uz6oBmjv724,1009
49
49
  tinybird/tb/modules/materialization.py,sha256=neugOziGfh50GSOgfZJX8giVPKgauoE313LUw6kXowo,5467
50
50
  tinybird/tb/modules/mock.py,sha256=IyHweMUM6bUH8IhyiX2tTMpdVpTFUeAJ41lZ5P42-HQ,5303
@@ -82,8 +82,8 @@ tinybird/tb_cli_modules/config.py,sha256=IsgdtFRnUrkY8-Zo32lmk6O7u3bHie1QCxLwgp4
82
82
  tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
83
83
  tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
84
84
  tinybird/tb_cli_modules/telemetry.py,sha256=Hh2Io8ZPROSunbOLuMvuIFU4TqwWPmQTqal4WS09K1A,10449
85
- tinybird-0.0.1.dev223.dist-info/METADATA,sha256=zlNXkkGzvZwDAbA5oEXPTubPsR0M0-jPbEVix8550bQ,1682
86
- tinybird-0.0.1.dev223.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
87
- tinybird-0.0.1.dev223.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
88
- tinybird-0.0.1.dev223.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
89
- tinybird-0.0.1.dev223.dist-info/RECORD,,
85
+ tinybird-0.0.1.dev225.dist-info/METADATA,sha256=tYgd7QaNE9_KOU6StAufP4rIYWwLAcZ7hHWI1vL8pro,1682
86
+ tinybird-0.0.1.dev225.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
87
+ tinybird-0.0.1.dev225.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
88
+ tinybird-0.0.1.dev225.dist-info/top_level.txt,sha256=VqqqEmkAy7UNaD8-V51FCoMMWXjLUlR0IstvK7tJYVY,54
89
+ tinybird-0.0.1.dev225.dist-info/RECORD,,