tinybird 0.0.1.dev234__py3-none-any.whl → 0.0.1.dev236__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 (49) hide show
  1. tinybird/tb/__cli__.py +2 -2
  2. tinybird/tb/check_pypi.py +3 -8
  3. tinybird/tb/cli.py +0 -6
  4. tinybird/tb/client.py +314 -340
  5. tinybird/tb/config.py +4 -5
  6. tinybird/tb/modules/build.py +21 -24
  7. tinybird/tb/modules/cicd.py +2 -2
  8. tinybird/tb/modules/cli.py +18 -28
  9. tinybird/tb/modules/common.py +123 -138
  10. tinybird/tb/modules/config.py +2 -4
  11. tinybird/tb/modules/connection.py +21 -26
  12. tinybird/tb/modules/copy.py +7 -9
  13. tinybird/tb/modules/create.py +18 -21
  14. tinybird/tb/modules/datafile/build.py +39 -39
  15. tinybird/tb/modules/datafile/build_common.py +9 -9
  16. tinybird/tb/modules/datafile/build_datasource.py +24 -24
  17. tinybird/tb/modules/datafile/build_pipe.py +11 -13
  18. tinybird/tb/modules/datafile/diff.py +12 -12
  19. tinybird/tb/modules/datafile/format_datasource.py +5 -5
  20. tinybird/tb/modules/datafile/format_pipe.py +6 -6
  21. tinybird/tb/modules/datafile/playground.py +42 -42
  22. tinybird/tb/modules/datafile/pull.py +24 -26
  23. tinybird/tb/modules/datasource.py +42 -56
  24. tinybird/tb/modules/endpoint.py +14 -19
  25. tinybird/tb/modules/info.py +14 -15
  26. tinybird/tb/modules/infra.py +43 -48
  27. tinybird/tb/modules/job.py +7 -10
  28. tinybird/tb/modules/local.py +22 -18
  29. tinybird/tb/modules/local_common.py +13 -4
  30. tinybird/tb/modules/login.py +9 -10
  31. tinybird/tb/modules/materialization.py +7 -10
  32. tinybird/tb/modules/mock.py +8 -9
  33. tinybird/tb/modules/open.py +1 -3
  34. tinybird/tb/modules/pipe.py +2 -4
  35. tinybird/tb/modules/secret.py +12 -16
  36. tinybird/tb/modules/shell.py +7 -20
  37. tinybird/tb/modules/sink.py +6 -8
  38. tinybird/tb/modules/test.py +9 -14
  39. tinybird/tb/modules/tinyunit/tinyunit.py +3 -3
  40. tinybird/tb/modules/token.py +16 -24
  41. tinybird/tb/modules/watch.py +3 -7
  42. tinybird/tb/modules/workspace.py +26 -37
  43. tinybird/tb/modules/workspace_members.py +16 -23
  44. {tinybird-0.0.1.dev234.dist-info → tinybird-0.0.1.dev236.dist-info}/METADATA +1 -1
  45. tinybird-0.0.1.dev236.dist-info/RECORD +89 -0
  46. tinybird-0.0.1.dev234.dist-info/RECORD +0 -89
  47. {tinybird-0.0.1.dev234.dist-info → tinybird-0.0.1.dev236.dist-info}/WHEEL +0 -0
  48. {tinybird-0.0.1.dev234.dist-info → tinybird-0.0.1.dev236.dist-info}/entry_points.txt +0 -0
  49. {tinybird-0.0.1.dev234.dist-info → tinybird-0.0.1.dev236.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,6 @@
5
5
  # the function to the proper command file.
6
6
  # - Please, **do not** define commands here.
7
7
 
8
- import asyncio
9
8
  import json
10
9
  import os
11
10
  import re
@@ -16,13 +15,11 @@ import uuid
16
15
  from contextlib import closing
17
16
  from copy import deepcopy
18
17
  from enum import Enum
19
- from functools import wraps
20
18
  from os import environ, getcwd, getenv
21
19
  from pathlib import Path
22
20
  from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Literal, Optional, Set, Tuple, TypedDict, Union
23
21
  from urllib.parse import urlparse
24
22
 
25
- import aiofiles
26
23
  import click
27
24
  import click.formatting
28
25
  import humanfriendly
@@ -58,7 +55,6 @@ from tinybird.tb.modules.table import format_table
58
55
  if TYPE_CHECKING:
59
56
  from tinybird.connectors import Connector
60
57
 
61
- from tinybird.syncasync import async_to_sync, sync_to_async
62
58
  from tinybird.tb.modules.config import CLIConfig
63
59
  from tinybird.tb.modules.exceptions import (
64
60
  CLIAuthException,
@@ -97,22 +93,14 @@ def create_connector(connector: str, options: Dict[str, Any]):
97
93
  return _create_connector(connector, options)
98
94
 
99
95
 
100
- def coro(f):
101
- @wraps(f)
102
- def wrapper(*args, **kwargs):
103
- return asyncio.run(f(*args, **kwargs))
104
-
105
- return wrapper
106
-
107
-
108
- async def gather_with_concurrency(n, *tasks):
109
- semaphore = asyncio.Semaphore(n)
110
-
111
- async def sem_task(task):
112
- async with semaphore:
113
- return await task
114
-
115
- return await asyncio.gather(*(sem_task(task) for task in tasks))
96
+ def gather_with_concurrency(n, *tasks):
97
+ results = []
98
+ for task in tasks:
99
+ if callable(task):
100
+ results.append(task())
101
+ else:
102
+ results.append(task)
103
+ return results
116
104
 
117
105
 
118
106
  def format_robust_table(data: Iterable[Any], column_names: List[str]):
@@ -201,9 +189,9 @@ def generate_datafile(
201
189
  return f
202
190
 
203
191
 
204
- async def get_current_workspace(config: CLIConfig) -> Optional[Dict[str, Any]]:
192
+ def get_current_workspace(config: CLIConfig) -> Optional[Dict[str, Any]]:
205
193
  client = config.get_client()
206
- workspaces: List[Dict[str, Any]] = (await client.user_workspaces_and_branches(version="v1")).get("workspaces", [])
194
+ workspaces: List[Dict[str, Any]] = (client.user_workspaces_and_branches(version="v1")).get("workspaces", [])
207
195
  return _get_current_workspace_common(workspaces, config["id"])
208
196
 
209
197
 
@@ -217,8 +205,8 @@ def _get_current_workspace_common(
217
205
  return next((workspace for workspace in workspaces if workspace["id"] == current_workspace_id), None)
218
206
 
219
207
 
220
- async def get_current_environment(client, config):
221
- workspaces: List[Dict[str, Any]] = (await client.user_workspaces_and_branches(version="v1")).get("workspaces", [])
208
+ def get_current_environment(client, config):
209
+ workspaces: List[Dict[str, Any]] = (client.user_workspaces_and_branches(version="v1")).get("workspaces", [])
222
210
  return next((workspace for workspace in workspaces if workspace["id"] == config["id"]), None)
223
211
 
224
212
 
@@ -383,36 +371,36 @@ def create_tb_client(ctx: Context) -> TinyB:
383
371
  return _get_tb_client(token, host)
384
372
 
385
373
 
386
- async def _analyze(filename: str, client: TinyB, format: str, connector: Optional["Connector"] = None):
374
+ def _analyze(filename: str, client: TinyB, format: str, connector: Optional["Connector"] = None):
387
375
  data: Optional[bytes] = None
388
376
  if not connector:
389
377
  parsed = urlparse(filename)
390
378
  if parsed.scheme in ("http", "https"):
391
- meta = await client.datasource_analyze(filename)
379
+ meta = client.datasource_analyze(filename)
392
380
  else:
393
- async with aiofiles.open(filename, "rb") as file:
381
+ with open(filename, "rb") as file:
394
382
  # We need to read the whole file in binary for Parquet, while for the
395
383
  # others we just read 1KiB
396
384
  if format == "parquet":
397
- data = await file.read()
385
+ data = file.read()
398
386
  else:
399
- data = await file.read(1024 * 1024)
387
+ data = file.read(1024 * 1024)
400
388
 
401
- meta = await client.datasource_analyze_file(data)
389
+ meta = client.datasource_analyze_file(data)
402
390
  else:
403
391
  meta = connector.datasource_analyze(filename)
404
392
  return meta, data
405
393
 
406
394
 
407
- async def analyze_file(filename: str, client: TinyB, format: str):
408
- meta, data = await _analyze(filename, client, format)
395
+ def analyze_file(filename: str, client: TinyB, format: str):
396
+ meta, data = _analyze(filename, client, format)
409
397
  schema = meta["analysis"]["schema"]
410
398
  schema = schema.replace(", ", ",\n ")
411
399
  content = f"""DESCRIPTION >\n Generated from {filename}\n\nSCHEMA >\n {schema}"""
412
400
  return content
413
401
 
414
402
 
415
- async def _generate_datafile(
403
+ def _generate_datafile(
416
404
  filename: str,
417
405
  client: TinyB,
418
406
  format: str,
@@ -420,14 +408,14 @@ async def _generate_datafile(
420
408
  force: Optional[bool] = False,
421
409
  folder: Optional[str] = None,
422
410
  ):
423
- meta, data = await _analyze(filename, client, format, connector=connector)
411
+ meta, data = _analyze(filename, client, format, connector=connector)
424
412
  schema = meta["analysis"]["schema"]
425
413
  schema = schema.replace(", ", ",\n ")
426
414
  datafile = f"""DESCRIPTION >\n Generated from {filename}\n\nSCHEMA >\n {schema}"""
427
415
  return generate_datafile(datafile, filename, data, force, _format=format, folder=folder)
428
416
 
429
417
 
430
- async def configure_connector(connector):
418
+ def configure_connector(connector):
431
419
  if connector not in SUPPORTED_CONNECTORS:
432
420
  raise CLIException(FeedbackManager.error_invalid_connector(connectors=", ".join(SUPPORTED_CONNECTORS)))
433
421
 
@@ -443,7 +431,7 @@ async def configure_connector(connector):
443
431
 
444
432
  try:
445
433
  config = {"project_id": project, "service_account": service_account, "bucket_name": bucket_name}
446
- await write_config(config, file_name)
434
+ write_config(config, file_name)
447
435
  except Exception:
448
436
  raise CLIException(FeedbackManager.error_file_config(config_file=config_file))
449
437
  elif connector == "snowflake":
@@ -483,7 +471,7 @@ async def configure_connector(connector):
483
471
  "bucket_name": bucket_name,
484
472
  "project_id": project,
485
473
  }
486
- await write_config(config, file_name)
474
+ write_config(config, file_name)
487
475
  except Exception:
488
476
  raise CLIException(FeedbackManager.error_file_config(config_file=config_file))
489
477
 
@@ -592,13 +580,13 @@ def ask_for_user_token(action: str, ui_host: str) -> str:
592
580
  )
593
581
 
594
582
 
595
- async def check_user_token(ctx: Context, token: str):
583
+ def check_user_token(ctx: Context, token: str):
596
584
  client: TinyB = ctx.ensure_object(dict)["client"]
597
585
  try:
598
586
  user_client: TinyB = deepcopy(client)
599
587
  user_client.token = token
600
588
 
601
- is_authenticated = await user_client.check_auth_login()
589
+ is_authenticated = user_client.check_auth_login()
602
590
  except Exception as e:
603
591
  raise CLIWorkspaceException(FeedbackManager.error_exception(error=str(e)))
604
592
 
@@ -616,12 +604,12 @@ async def check_user_token(ctx: Context, token: str):
616
604
  )
617
605
 
618
606
 
619
- async def check_user_token_with_client(client: TinyB, token: str):
607
+ def check_user_token_with_client(client: TinyB, token: str):
620
608
  try:
621
609
  user_client: TinyB = deepcopy(client)
622
610
  user_client.token = token
623
611
 
624
- is_authenticated = await user_client.check_auth_login()
612
+ is_authenticated = user_client.check_auth_login()
625
613
  except Exception as e:
626
614
  raise CLIWorkspaceException(FeedbackManager.error_exception(error=str(e)))
627
615
 
@@ -639,15 +627,15 @@ async def check_user_token_with_client(client: TinyB, token: str):
639
627
  )
640
628
 
641
629
 
642
- async def fork_workspace(client: TinyB, user_client: TinyB, created_workspace):
630
+ def fork_workspace(client: TinyB, user_client: TinyB, created_workspace):
643
631
  config = CLIConfig.get_project_config()
644
632
 
645
- datasources = await client.datasources()
633
+ datasources = client.datasources()
646
634
  for datasource in datasources:
647
- await user_client.datasource_share(datasource["id"], config["id"], created_workspace["id"])
635
+ user_client.datasource_share(datasource["id"], config["id"], created_workspace["id"])
648
636
 
649
637
 
650
- async def create_workspace_non_interactive(
638
+ def create_workspace_non_interactive(
651
639
  ctx: Context,
652
640
  workspace_name: str,
653
641
  user_token: str,
@@ -662,7 +650,7 @@ async def create_workspace_non_interactive(
662
650
  user_client: TinyB = deepcopy(client)
663
651
  user_client.token = user_token
664
652
 
665
- created_workspace = await user_client.create_workspace(workspace_name, organization_id, version="v1")
653
+ created_workspace = user_client.create_workspace(workspace_name, organization_id, version="v1")
666
654
  if organization_id and organization_name:
667
655
  click.echo(
668
656
  FeedbackManager.success_workspace_created_with_organization(
@@ -673,13 +661,13 @@ async def create_workspace_non_interactive(
673
661
  click.echo(FeedbackManager.success_workspace_created(workspace_name=workspace_name))
674
662
 
675
663
  if fork:
676
- await fork_workspace(client, user_client, created_workspace)
664
+ fork_workspace(client, user_client, created_workspace)
677
665
 
678
666
  except Exception as e:
679
667
  raise CLIWorkspaceException(FeedbackManager.error_exception(error=str(e)))
680
668
 
681
669
 
682
- async def create_workspace_interactive(
670
+ def create_workspace_interactive(
683
671
  ctx: Context,
684
672
  workspace_name: Optional[str],
685
673
  user_token: str,
@@ -697,7 +685,7 @@ async def create_workspace_interactive(
697
685
  if not workspace_name:
698
686
  raise CLIException(FeedbackManager.error_workspace_name_required())
699
687
 
700
- await create_workspace_non_interactive(
688
+ create_workspace_non_interactive(
701
689
  ctx,
702
690
  workspace_name,
703
691
  user_token,
@@ -707,8 +695,8 @@ async def create_workspace_interactive(
707
695
  )
708
696
 
709
697
 
710
- async def print_data_branch_summary(client, job_id, response=None):
711
- response = await client.job(job_id) if job_id else response or {"partitions": []}
698
+ def print_data_branch_summary(client, job_id, response=None):
699
+ response = client.job(job_id) if job_id else response or {"partitions": []}
712
700
  columns = ["Data Source", "Partition", "Status", "Error"]
713
701
  table = []
714
702
  for partition in response["partitions"]:
@@ -717,7 +705,7 @@ async def print_data_branch_summary(client, job_id, response=None):
717
705
  echo_safe_humanfriendly_tables_format_smart_table(table, column_names=columns)
718
706
 
719
707
 
720
- async def print_branch_regression_tests_summary(client, job_id, host, response=None):
708
+ def print_branch_regression_tests_summary(client, job_id, host, response=None):
721
709
  def format_metric(metric: Union[str, float], is_percentage: bool = False) -> str:
722
710
  if isinstance(metric, float):
723
711
  if is_percentage:
@@ -728,7 +716,7 @@ async def print_branch_regression_tests_summary(client, job_id, host, response=N
728
716
  return metric
729
717
 
730
718
  failed = False
731
- response = await client.job(job_id) if job_id else response or {"progress": []}
719
+ response = client.job(job_id) if job_id else response or {"progress": []}
732
720
  output = "\n"
733
721
  for step in response["progress"]:
734
722
  run = step["run"]
@@ -927,7 +915,7 @@ def get_format_from_filename_or_url(filename_or_url: str) -> str:
927
915
  return "csv"
928
916
 
929
917
 
930
- async def push_data(
918
+ def push_data(
931
919
  client: TinyB,
932
920
  datasource_name: str,
933
921
  url,
@@ -966,14 +954,14 @@ async def push_data(
966
954
  else:
967
955
  urls = [url]
968
956
 
969
- async def process_url(
957
+ def process_url(
970
958
  datasource_name: str, url: str, mode: str, sql_condition: Optional[str], replace_options: Optional[Set[str]]
971
959
  ):
972
960
  parsed = urlparse(url)
973
961
  # poor man's format detection
974
962
  _format = get_format_from_filename_or_url(url)
975
963
  if parsed.scheme in ("http", "https"):
976
- res = await client.datasource_create_from_url(
964
+ res = client.datasource_create_from_url(
977
965
  datasource_name,
978
966
  url,
979
967
  mode=mode,
@@ -983,7 +971,7 @@ async def push_data(
983
971
  replace_options=replace_options,
984
972
  )
985
973
  else:
986
- res = await client.datasource_append_data(
974
+ res = client.datasource_append_data(
987
975
  datasource_name,
988
976
  file=url,
989
977
  mode=mode,
@@ -994,7 +982,7 @@ async def push_data(
994
982
 
995
983
  datasource_name = res["datasource"]["name"]
996
984
  try:
997
- datasource = await client.get_datasource(datasource_name)
985
+ datasource = client.get_datasource(datasource_name)
998
986
  except DoesNotExistException:
999
987
  raise CLIException(FeedbackManager.error_datasource_does_not_exist(datasource=datasource_name))
1000
988
  except Exception as e:
@@ -1021,7 +1009,7 @@ async def push_data(
1021
1009
 
1022
1010
  try:
1023
1011
  tasks = [process_url(datasource_name, url, mode, sql_condition, replace_options) for url in urls]
1024
- output = await gather_with_concurrency(concurrency, *tasks)
1012
+ output = gather_with_concurrency(concurrency, *tasks)
1025
1013
  parser, total_rows, appended_rows = list(output)[-1]
1026
1014
  except AuthNoTokenException:
1027
1015
  raise
@@ -1040,9 +1028,9 @@ async def push_data(
1040
1028
  click.echo(FeedbackManager.success_progress_blocks())
1041
1029
 
1042
1030
 
1043
- async def sync_data(ctx, datasource_name: str, yes: bool):
1031
+ def sync_data(ctx, datasource_name: str, yes: bool):
1044
1032
  client: TinyB = ctx.obj["client"]
1045
- datasource = await client.get_datasource(datasource_name)
1033
+ datasource = client.get_datasource(datasource_name)
1046
1034
 
1047
1035
  VALID_DATASOURCES = ["bigquery", "snowflake", "s3", "gcs"]
1048
1036
  if datasource["type"] not in VALID_DATASOURCES:
@@ -1056,17 +1044,17 @@ async def sync_data(ctx, datasource_name: str, yes: bool):
1056
1044
  )
1057
1045
  )
1058
1046
  if yes or click.confirm(warning_message):
1059
- await client.datasource_sync(datasource["id"])
1047
+ client.datasource_sync(datasource["id"])
1060
1048
  click.echo(FeedbackManager.success_sync_datasource(datasource=datasource_name))
1061
1049
 
1062
1050
 
1063
1051
  # eval "$(_TB_COMPLETE=source_bash tb)"
1064
1052
  def autocomplete_topics(ctx: Context, args, incomplete):
1065
1053
  try:
1066
- config = async_to_sync(get_config)(None, None)
1054
+ config = get_config(None, None)
1067
1055
  ctx.ensure_object(dict)["config"] = config
1068
1056
  client = create_tb_client(ctx)
1069
- topics = async_to_sync(client.kafka_list_topics)(args[2])
1057
+ topics = client.kafka_list_topics(args[2])
1070
1058
  return [t for t in topics if incomplete in t]
1071
1059
  except Exception:
1072
1060
  return []
@@ -1148,8 +1136,8 @@ def validate_string_connector_param(param, s):
1148
1136
  raise CLIConnectionException(param + " format is not correct, it must be a string")
1149
1137
 
1150
1138
 
1151
- async def validate_connection_name(client, connection_name, service):
1152
- if await client.get_connector(connection_name, service) is not None:
1139
+ def validate_connection_name(client, connection_name, service):
1140
+ if client.get_connector(connection_name, service) is not None:
1153
1141
  raise CLIConnectionException(FeedbackManager.error_connection_already_exists(name=connection_name))
1154
1142
 
1155
1143
 
@@ -1159,9 +1147,9 @@ def _get_setting_value(connection, setting, sensitive_settings):
1159
1147
  return connection.get(setting, "")
1160
1148
 
1161
1149
 
1162
- async def switch_workspace(config: CLIConfig, workspace_name_or_id: str) -> None:
1150
+ def switch_workspace(config: CLIConfig, workspace_name_or_id: str) -> None:
1163
1151
  try:
1164
- response = await config.get_client().user_workspaces(version="v1")
1152
+ response = config.get_client().user_workspaces(version="v1")
1165
1153
  workspaces = response["workspaces"]
1166
1154
 
1167
1155
  workspace = next(
@@ -1178,7 +1166,7 @@ async def switch_workspace(config: CLIConfig, workspace_name_or_id: str) -> None
1178
1166
 
1179
1167
  config.set_token(workspace["token"])
1180
1168
  config.set_token_for_host(workspace["token"], config.get_host())
1181
- _ = await try_update_config_with_remote(config)
1169
+ _ = try_update_config_with_remote(config)
1182
1170
 
1183
1171
  # Set the id and name afterwards.
1184
1172
  # When working with branches the call to try_update_config_with_remote above
@@ -1197,7 +1185,7 @@ async def switch_workspace(config: CLIConfig, workspace_name_or_id: str) -> None
1197
1185
  raise CLIException(FeedbackManager.error_exception(error=str(e)))
1198
1186
 
1199
1187
 
1200
- async def switch_to_workspace_by_user_workspace_data(config: CLIConfig, user_workspace_data: Dict[str, Any]):
1188
+ def switch_to_workspace_by_user_workspace_data(config: CLIConfig, user_workspace_data: Dict[str, Any]):
1201
1189
  try:
1202
1190
  config["id"] = user_workspace_data["id"]
1203
1191
  config["name"] = user_workspace_data["name"]
@@ -1210,10 +1198,10 @@ async def switch_to_workspace_by_user_workspace_data(config: CLIConfig, user_wor
1210
1198
  raise CLIException(FeedbackManager.error_exception(error=str(e)))
1211
1199
 
1212
1200
 
1213
- async def print_current_workspace(config: CLIConfig) -> None:
1214
- _ = await try_update_config_with_remote(config, only_if_needed=True)
1201
+ def print_current_workspace(config: CLIConfig) -> None:
1202
+ _ = try_update_config_with_remote(config, only_if_needed=True)
1215
1203
 
1216
- current_main_workspace = await get_current_main_workspace(config)
1204
+ current_main_workspace = get_current_main_workspace(config)
1217
1205
  assert isinstance(current_main_workspace, dict)
1218
1206
 
1219
1207
  columns = ["name", "id", "role", "plan", "current"]
@@ -1291,7 +1279,7 @@ class ConnectionReplacements:
1291
1279
  # ======
1292
1280
 
1293
1281
 
1294
- async def get_host_from_region(
1282
+ def get_host_from_region(
1295
1283
  config: CLIConfig, region_name_or_host_or_id: str, host: Optional[str] = None
1296
1284
  ) -> Tuple[List[Region], str]:
1297
1285
  regions: List[Region]
@@ -1300,7 +1288,7 @@ async def get_host_from_region(
1300
1288
  host = host or config.get_host(use_defaults_if_needed=True)
1301
1289
 
1302
1290
  try:
1303
- regions = await get_regions(config)
1291
+ regions = get_regions(config)
1304
1292
  assert isinstance(regions, list)
1305
1293
  except Exception:
1306
1294
  regions = []
@@ -1330,10 +1318,10 @@ async def get_host_from_region(
1330
1318
  return regions, host
1331
1319
 
1332
1320
 
1333
- async def get_regions(config: CLIConfig) -> List[Region]:
1321
+ def get_regions(config: CLIConfig) -> List[Region]:
1334
1322
  regions: List[Region] = []
1335
1323
  try:
1336
- response = await config.get_client().regions()
1324
+ response = config.get_client().regions()
1337
1325
  regions = response.get("regions", [])
1338
1326
  first_default_region = next((region for region in regions if region["api_host"] == DEFAULT_API_HOST), None)
1339
1327
  if first_default_region:
@@ -1353,7 +1341,7 @@ def get_region_from_host(region_name_or_host: str, regions: List[Region]) -> Opt
1353
1341
  return None
1354
1342
 
1355
1343
 
1356
- async def try_update_config_with_remote(
1344
+ def try_update_config_with_remote(
1357
1345
  config: CLIConfig, raise_on_errors: bool = True, only_if_needed: bool = False, auto_persist: bool = True
1358
1346
  ) -> bool:
1359
1347
  response: Dict[str, Any]
@@ -1367,7 +1355,7 @@ async def try_update_config_with_remote(
1367
1355
  return True
1368
1356
 
1369
1357
  try:
1370
- response = await config.get_client().workspace_info(version="v1")
1358
+ response = config.get_client().workspace_info(version="v1")
1371
1359
  except AuthException:
1372
1360
  if raise_on_errors:
1373
1361
  raise CLIAuthException(FeedbackManager.error_invalid_token_for_host(host=config.get_host()))
@@ -1406,7 +1394,7 @@ def ask_for_admin_token_interactively(ui_host: str, default_token: Optional[str]
1406
1394
  )
1407
1395
 
1408
1396
 
1409
- async def try_authenticate(
1397
+ def try_authenticate(
1410
1398
  config: CLIConfig,
1411
1399
  regions: Optional[List[Region]] = None,
1412
1400
  interactive: bool = False,
@@ -1415,7 +1403,7 @@ async def try_authenticate(
1415
1403
  host: Optional[str] = config.get_host()
1416
1404
 
1417
1405
  if not regions and interactive:
1418
- regions = await get_regions(config)
1406
+ regions = get_regions(config)
1419
1407
 
1420
1408
  selected_region: Optional[Region] = None
1421
1409
  default_password: Optional[str] = None
@@ -1449,18 +1437,18 @@ async def try_authenticate(
1449
1437
  config.set_token(token)
1450
1438
 
1451
1439
  add_telemetry_event("auth_token", token=token)
1452
- authenticated: bool = await try_update_config_with_remote(config, raise_on_errors=not try_all_regions)
1440
+ authenticated: bool = try_update_config_with_remote(config, raise_on_errors=not try_all_regions)
1453
1441
 
1454
1442
  # No luck? Let's try auth in all other regions
1455
1443
  if not authenticated and try_all_regions and not interactive:
1456
1444
  if not regions:
1457
- regions = await get_regions(config)
1445
+ regions = get_regions(config)
1458
1446
 
1459
1447
  # Check other regions, ignoring the previously tested region
1460
1448
  for region in [r for r in regions if r is not selected_region]:
1461
1449
  name, host, ui_host = get_region_info(config, region)
1462
1450
  config.set_host(host)
1463
- authenticated = await try_update_config_with_remote(config, raise_on_errors=False)
1451
+ authenticated = try_update_config_with_remote(config, raise_on_errors=False)
1464
1452
  if authenticated:
1465
1453
  click.echo(FeedbackManager.success_using_host(name=name, host=get_display_cloud_host(ui_host)))
1466
1454
  break
@@ -1481,7 +1469,7 @@ async def try_authenticate(
1481
1469
  return True
1482
1470
 
1483
1471
 
1484
- async def wait_job(
1472
+ def wait_job(
1485
1473
  tb_client: TinyB,
1486
1474
  job_id: str,
1487
1475
  job_url: str,
@@ -1508,12 +1496,11 @@ async def wait_job(
1508
1496
  progress_bar.update(progress_bar.length if progress_bar.length else 0)
1509
1497
 
1510
1498
  try:
1511
- # TODO: Simplify this as it's not needed to use two functions for
1512
- result = await wait_job_no_ui(tb_client, job_id, progressbar_cb)
1499
+ result = wait_job_no_ui(tb_client, job_id, progressbar_cb)
1513
1500
  if result["status"] != "done":
1514
1501
  raise CLIException(FeedbackManager.error_while_running_job(error=result["error"]))
1515
1502
  return result
1516
- except asyncio.TimeoutError:
1503
+ except TimeoutError:
1517
1504
  raise CLIException(FeedbackManager.error_while_running_job(error="Reach timeout, job cancelled"))
1518
1505
  except JobException as e:
1519
1506
  raise CLIException(FeedbackManager.error_while_running_job(error=str(e)))
@@ -1521,23 +1508,23 @@ async def wait_job(
1521
1508
  raise CLIException(FeedbackManager.error_getting_job_info(error=str(e), url=job_url))
1522
1509
 
1523
1510
 
1524
- async def wait_job_no_ui(
1511
+ def wait_job_no_ui(
1525
1512
  tb_client: TinyB,
1526
1513
  job_id: str,
1527
1514
  status_callback: Optional[Callable[[Dict[str, Any]], None]] = None,
1528
1515
  ) -> Dict[str, Any]:
1529
1516
  try:
1530
- result = await asyncio.wait_for(tb_client.wait_for_job(job_id, status_callback=status_callback), None)
1517
+ result = tb_client.wait_for_job(job_id, status_callback=status_callback)
1531
1518
  if result["status"] != "done":
1532
1519
  raise JobException(result.get("error"))
1533
1520
  return result
1534
- except asyncio.TimeoutError:
1535
- await tb_client.job_cancel(job_id)
1521
+ except TimeoutError:
1522
+ tb_client.job_cancel(job_id)
1536
1523
  raise
1537
1524
 
1538
1525
 
1539
- async def get_current_main_workspace(config: CLIConfig) -> Optional[Dict[str, Any]]:
1540
- current_workspace = await config.get_client().user_workspaces_and_branches(version="v1")
1526
+ def get_current_main_workspace(config: CLIConfig) -> Optional[Dict[str, Any]]:
1527
+ current_workspace = config.get_client().user_workspaces_and_branches(version="v1")
1541
1528
  return _get_current_main_workspace_common(current_workspace, config.get("id", current_workspace["id"]))
1542
1529
 
1543
1530
 
@@ -1618,13 +1605,13 @@ def is_major_semver(new_version: Version, current_version: Version) -> bool:
1618
1605
  return new_version.major != current_version.major
1619
1606
 
1620
1607
 
1621
- async def print_release_summary(config: CLIConfig, semver: Optional[str], info: bool = False, dry_run=False):
1608
+ def print_release_summary(config: CLIConfig, semver: Optional[str], info: bool = False, dry_run=False):
1622
1609
  if not semver:
1623
1610
  click.echo(FeedbackManager.info_release_no_rollback())
1624
1611
  return
1625
1612
  try:
1626
1613
  client = config.get_client()
1627
- response = await client.release_rm(config["id"], semver, confirmation=config["name"], dry_run=True)
1614
+ response = client.release_rm(config["id"], semver, confirmation=config["name"], dry_run=True)
1628
1615
  except Exception as e:
1629
1616
  raise CLIReleaseException(FeedbackManager.error_exception(error=str(e)))
1630
1617
  else:
@@ -1660,21 +1647,21 @@ async def print_release_summary(config: CLIConfig, semver: Optional[str], info:
1660
1647
  echo_safe_humanfriendly_tables_format_smart_table(rows, column_names=columns)
1661
1648
 
1662
1649
 
1663
- async def get_oldest_rollback(config: CLIConfig, client: TinyB) -> Optional[str]:
1664
- oldest_rollback_response = await client.release_oldest_rollback(config["id"])
1650
+ def get_oldest_rollback(config: CLIConfig, client: TinyB) -> Optional[str]:
1651
+ oldest_rollback_response = client.release_oldest_rollback(config["id"])
1665
1652
  return oldest_rollback_response.get("semver") if oldest_rollback_response else None
1666
1653
 
1667
1654
 
1668
- async def remove_release(
1655
+ def remove_release(
1669
1656
  dry_run: bool, config: CLIConfig, semver: Optional[str], client: TinyB, force: bool, show_print=True
1670
1657
  ):
1671
1658
  if semver == OLDEST_ROLLBACK:
1672
- semver = await get_oldest_rollback(config, client)
1659
+ semver = get_oldest_rollback(config, client)
1673
1660
  if show_print:
1674
- await print_release_summary(config, semver, info=True, dry_run=True)
1661
+ print_release_summary(config, semver, info=True, dry_run=True)
1675
1662
  if not dry_run:
1676
1663
  if semver:
1677
- response = await client.release_rm(
1664
+ response = client.release_rm(
1678
1665
  config["id"], semver, confirmation=config["name"], dry_run=dry_run, force=force
1679
1666
  )
1680
1667
  click.echo(FeedbackManager.success_release_delete(semver=response.get("semver")))
@@ -1682,7 +1669,7 @@ async def remove_release(
1682
1669
  click.echo(FeedbackManager.info_no_release_deleted())
1683
1670
 
1684
1671
 
1685
- async def run_aws_iamrole_connection_flow(
1672
+ def run_aws_iamrole_connection_flow(
1686
1673
  client: TinyB,
1687
1674
  service: str,
1688
1675
  environment: str,
@@ -1701,7 +1688,7 @@ async def run_aws_iamrole_connection_flow(
1701
1688
  region = click.prompt("🌐 Region (the region where the bucket is located, e.g. 'us-east-1')", prompt_suffix="\n> ")
1702
1689
  validate_string_connector_param("Region", region)
1703
1690
 
1704
- access_policy, trust_policy, _ = await get_aws_iamrole_policies(
1691
+ access_policy, trust_policy, _ = get_aws_iamrole_policies(
1705
1692
  client, service=service, policy=policy, bucket=bucket_name, external_id_seed=connection_name
1706
1693
  )
1707
1694
 
@@ -1759,7 +1746,7 @@ async def run_aws_iamrole_connection_flow(
1759
1746
  return role_arn, region, bucket_name
1760
1747
 
1761
1748
 
1762
- async def run_gcp_svc_account_connection_flow(
1749
+ def run_gcp_svc_account_connection_flow(
1763
1750
  environment: str,
1764
1751
  ) -> None:
1765
1752
  click.echo(FeedbackManager.prompt_gcs_svc_account_login_gcp())
@@ -1775,7 +1762,7 @@ async def run_gcp_svc_account_connection_flow(
1775
1762
  input()
1776
1763
 
1777
1764
 
1778
- async def production_aws_iamrole_only(
1765
+ def production_aws_iamrole_only(
1779
1766
  prod_client: TinyB,
1780
1767
  service: str,
1781
1768
  region: str,
@@ -1784,7 +1771,7 @@ async def production_aws_iamrole_only(
1784
1771
  connection_name: str,
1785
1772
  policy: str,
1786
1773
  ) -> Tuple[str, str, str]:
1787
- _, trust_policy, external_id = await get_aws_iamrole_policies(
1774
+ _, trust_policy, external_id = get_aws_iamrole_policies(
1788
1775
  prod_client, service=service, policy=policy, bucket=bucket_name, external_id_seed=connection_name
1789
1776
  )
1790
1777
 
@@ -1819,7 +1806,7 @@ async def production_aws_iamrole_only(
1819
1806
  return role_arn, region, external_id
1820
1807
 
1821
1808
 
1822
- async def get_aws_iamrole_policies(
1809
+ def get_aws_iamrole_policies(
1823
1810
  client: TinyB,
1824
1811
  service: str,
1825
1812
  policy: str = "write",
@@ -1831,9 +1818,9 @@ async def get_aws_iamrole_policies(
1831
1818
  service = DataConnectorType.AMAZON_S3
1832
1819
  try:
1833
1820
  if policy == "write":
1834
- access_policy = await client.get_access_write_policy(service, bucket)
1821
+ access_policy = client.get_access_write_policy(service, bucket)
1835
1822
  elif policy == "read":
1836
- access_policy = await client.get_access_read_policy(service, bucket)
1823
+ access_policy = client.get_access_read_policy(service, bucket)
1837
1824
  else:
1838
1825
  raise Exception(f"Access policy {policy} not supported. Choose from 'read' or 'write'")
1839
1826
  if not len(access_policy) > 0:
@@ -1843,7 +1830,7 @@ async def get_aws_iamrole_policies(
1843
1830
 
1844
1831
  trust_policy: Dict[str, Any] = {}
1845
1832
  try:
1846
- trust_policy = await client.get_trust_policy(service, external_id_seed)
1833
+ trust_policy = client.get_trust_policy(service, external_id_seed)
1847
1834
  if not len(trust_policy) > 0:
1848
1835
  raise Exception(f"{service.upper()} Integration not supported in this region")
1849
1836
  except Exception as e:
@@ -1932,7 +1919,7 @@ class DataConnectorType(str, Enum):
1932
1919
  return self.value
1933
1920
 
1934
1921
 
1935
- async def create_aws_iamrole_connection(client: TinyB, service: str, connection_name, role_arn, region) -> None:
1922
+ def create_aws_iamrole_connection(client: TinyB, service: str, connection_name, role_arn, region) -> None:
1936
1923
  conn_file_name = f"{connection_name}.connection"
1937
1924
  conn_file_path = Path(getcwd(), conn_file_name)
1938
1925
 
@@ -1950,14 +1937,14 @@ async def create_aws_iamrole_connection(client: TinyB, service: str, connection_
1950
1937
 
1951
1938
  click.echo("** Creating connection...")
1952
1939
  try:
1953
- _ = await client.connection_create(params)
1940
+ _ = client.connection_create(params)
1954
1941
  except Exception as e:
1955
1942
  raise CLIConnectionException(
1956
1943
  FeedbackManager.error_connection_create(connection_name=connection_name, error=str(e))
1957
1944
  )
1958
1945
 
1959
- async with aiofiles.open(conn_file_path, "w") as f:
1960
- await f.write(
1946
+ with open(conn_file_path, "w") as f:
1947
+ f.write(
1961
1948
  f"""TYPE {service}
1962
1949
 
1963
1950
  """
@@ -1990,36 +1977,34 @@ def get_ca_pem_content(ca_pem: Optional[str], filename: Optional[str] = None) ->
1990
1977
  return ca_pem_content
1991
1978
 
1992
1979
 
1993
- requests_get = sync_to_async(requests.get, thread_sensitive=False)
1994
- requests_delete = sync_to_async(requests.delete, thread_sensitive=False)
1980
+ requests_get = requests.get
1981
+ requests_delete = requests.delete
1995
1982
 
1996
1983
 
1997
1984
  def format_data_to_ndjson(data: List[Dict[str, Any]]) -> str:
1998
1985
  return "\n".join([json.dumps(row) for row in data])
1999
1986
 
2000
1987
 
2001
- async def send_batch_events(
2002
- client: TinyB, datasource_name: str, data: List[Dict[str, Any]], batch_size: int = 10
2003
- ) -> None:
1988
+ def send_batch_events(client: TinyB, datasource_name: str, data: List[Dict[str, Any]], batch_size: int = 10) -> None:
2004
1989
  rows = len(data)
2005
1990
  time_start = time.time()
2006
1991
  for i in range(0, rows, batch_size):
2007
1992
  batch = data[i : i + batch_size]
2008
1993
  ndjson_data = format_data_to_ndjson(batch)
2009
- await client.datasource_events(datasource_name, ndjson_data)
1994
+ client.datasource_events(datasource_name, ndjson_data)
2010
1995
  time_end = time.time()
2011
1996
  elapsed_time = time_end - time_start
2012
1997
  cols = len(data[0].keys()) if len(data) > 0 else 0
2013
1998
  click.echo(FeedbackManager.highlight(message=f"» {rows} rows x {cols} cols in {elapsed_time:.1f}s"))
2014
1999
 
2015
2000
 
2016
- async def get_organizations_by_user(config: CLIConfig, user_token: Optional[str] = None) -> List[Dict[str, str]]:
2001
+ def get_organizations_by_user(config: CLIConfig, user_token: Optional[str] = None) -> List[Dict[str, str]]:
2017
2002
  """Fetches all organizations by user using the provided user token"""
2018
2003
  organizations = []
2019
2004
 
2020
2005
  try:
2021
2006
  user_client = config.get_client(token=user_token) if user_token else config.get_user_client()
2022
- user_workspaces = await user_client.user_workspaces_with_organization(version="v1")
2007
+ user_workspaces = user_client.user_workspaces_with_organization(version="v1")
2023
2008
  admin_org_id = user_workspaces.get("organization_id")
2024
2009
  seen_org_ids = set()
2025
2010
 
@@ -2032,7 +2017,7 @@ async def get_organizations_by_user(config: CLIConfig, user_token: Optional[str]
2032
2017
 
2033
2018
  # Case: user is admin of an organization but not a member of any workspace in it
2034
2019
  if admin_org_id and admin_org_id not in seen_org_ids:
2035
- org = await user_client.organization(admin_org_id)
2020
+ org = user_client.organization(admin_org_id)
2036
2021
  org["id"] = admin_org_id
2037
2022
  org["is_admin"] = True
2038
2023
  organizations.append(org)
@@ -2086,7 +2071,7 @@ def sort_organizations_by_user(organizations: List[Dict[str, Any]], user_email:
2086
2071
  return sorted_organizations
2087
2072
 
2088
2073
 
2089
- async def ask_for_organization_interactively(organizations: List[Organization]) -> Optional[Organization]:
2074
+ def ask_for_organization_interactively(organizations: List[Organization]) -> Optional[Organization]:
2090
2075
  rows = [(index + 1, org["name"], org["role"], org["id"]) for index, org in enumerate(organizations)]
2091
2076
 
2092
2077
  echo_safe_humanfriendly_tables_format_smart_table(rows, column_names=["Idx", "Name", "Role", "Id"])
@@ -2107,7 +2092,7 @@ async def ask_for_organization_interactively(organizations: List[Organization])
2107
2092
  return organizations[org_index - 1]
2108
2093
 
2109
2094
 
2110
- async def ask_for_organization_name(config: CLIConfig) -> str:
2095
+ def ask_for_organization_name(config: CLIConfig) -> str:
2111
2096
  user_email = config.get_user_email()
2112
2097
  default_organization_name = (
2113
2098
  user_email.split("@")[1].split(".")[0] if user_email else None
@@ -2125,28 +2110,28 @@ async def ask_for_organization_name(config: CLIConfig) -> str:
2125
2110
  )
2126
2111
 
2127
2112
 
2128
- async def create_organization_and_add_workspaces(
2113
+ def create_organization_and_add_workspaces(
2129
2114
  config: CLIConfig, organization_name: str, user_token: str
2130
2115
  ) -> Dict[str, Any]:
2131
2116
  client: TinyB = config.get_client(token=user_token)
2132
2117
  try:
2133
- organization = await client.create_organization(organization_name)
2118
+ organization = client.create_organization(organization_name)
2134
2119
  click.echo(FeedbackManager.success_organization_created(organization_name=organization_name))
2135
2120
  except Exception as e:
2136
2121
  raise CLIWorkspaceException(FeedbackManager.error_organization_creation(error=str(e)))
2137
2122
 
2138
2123
  # Add existing orphan workspaces to the organization - this is only needed for backwards compatibility
2139
- user_workspaces = await client.user_workspaces_with_organization(version="v1")
2124
+ user_workspaces = client.user_workspaces_with_organization(version="v1")
2140
2125
  workspaces_to_migrate = []
2141
2126
  for workspace in user_workspaces["workspaces"]:
2142
2127
  if workspace.get("organization") is None and workspace.get("role") == "admin":
2143
2128
  workspaces_to_migrate.append(workspace["id"])
2144
- await client.add_workspaces_to_organization(organization["id"], workspaces_to_migrate)
2129
+ client.add_workspaces_to_organization(organization["id"], workspaces_to_migrate)
2145
2130
 
2146
2131
  return organization
2147
2132
 
2148
2133
 
2149
- async def get_user_token(config: CLIConfig, user_token: Optional[str] = None) -> str:
2134
+ def get_user_token(config: CLIConfig, user_token: Optional[str] = None) -> str:
2150
2135
  client = config.get_client()
2151
2136
  host = config.get_host() or CLIConfig.DEFAULTS["host"]
2152
2137
  ui_host = get_display_cloud_host(host)
@@ -2155,7 +2140,7 @@ async def get_user_token(config: CLIConfig, user_token: Optional[str] = None) ->
2155
2140
  user_token = config.get_user_token()
2156
2141
  if user_token:
2157
2142
  try:
2158
- await check_user_token_with_client(client, user_token)
2143
+ check_user_token_with_client(client, user_token)
2159
2144
  except Exception:
2160
2145
  user_token = None
2161
2146
  pass
@@ -2168,12 +2153,12 @@ async def get_user_token(config: CLIConfig, user_token: Optional[str] = None) ->
2168
2153
  )
2169
2154
  )
2170
2155
 
2171
- await check_user_token_with_client(client, user_token)
2156
+ check_user_token_with_client(client, user_token)
2172
2157
 
2173
2158
  return user_token
2174
2159
 
2175
2160
 
2176
- async def ask_for_organization(
2161
+ def ask_for_organization(
2177
2162
  organizations: Optional[List[Dict[str, Any]]],
2178
2163
  organization_id: Optional[str] = None,
2179
2164
  user_token: Optional[str] = None,
@@ -2190,9 +2175,9 @@ async def ask_for_organization(
2190
2175
  return organization_id, organization_name
2191
2176
 
2192
2177
  if organizations is None or len(organizations) == 0:
2193
- organization_name = await ask_for_organization_name(config)
2194
- user_token = await get_user_token(config, user_token)
2195
- organization = await create_organization_and_add_workspaces(config, organization_name, user_token)
2178
+ organization_name = ask_for_organization_name(config)
2179
+ user_token = get_user_token(config, user_token)
2180
+ organization = create_organization_and_add_workspaces(config, organization_name, user_token)
2196
2181
  organization_id = organization.get("id")
2197
2182
  else:
2198
2183
  if len(organizations) == 1:
@@ -2200,7 +2185,7 @@ async def ask_for_organization(
2200
2185
  organization_id = organizations[0]["id"]
2201
2186
  else:
2202
2187
  sorted_organizations = sort_organizations_by_user(organizations, user_email=user_email)
2203
- current_organization = await ask_for_organization_interactively(sorted_organizations)
2188
+ current_organization = ask_for_organization_interactively(sorted_organizations)
2204
2189
  if current_organization:
2205
2190
  organization_id = current_organization.get("id")
2206
2191
  organization_name = current_organization.get("name")