tinybird-cli 5.10.2.dev1__tar.gz → 5.10.2.dev2__tar.gz

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.
Files changed (48) hide show
  1. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/PKG-INFO +5 -1
  2. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/__cli__.py +2 -2
  3. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/client.py +5 -3
  4. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/config.py +6 -4
  5. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/datafile.py +3 -2
  6. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/branch.py +12 -11
  7. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/common.py +18 -17
  8. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/connection.py +11 -10
  9. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/fmt.py +5 -4
  10. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird_cli.egg-info/PKG-INFO +5 -1
  11. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird_cli.egg-info/requires.txt +1 -0
  12. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/setup.cfg +0 -0
  13. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/ch_utils/constants.py +0 -0
  14. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/ch_utils/engine.py +0 -0
  15. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/check_pypi.py +0 -0
  16. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/connectors.py +0 -0
  17. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/context.py +0 -0
  18. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/datatypes.py +0 -0
  19. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/feedback_manager.py +0 -0
  20. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/git_settings.py +0 -0
  21. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/sql.py +0 -0
  22. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/sql_template.py +0 -0
  23. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/sql_template_fmt.py +0 -0
  24. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/sql_toolset.py +0 -0
  25. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/syncasync.py +0 -0
  26. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli.py +0 -0
  27. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/auth.py +0 -0
  28. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/cicd.py +0 -0
  29. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/cli.py +0 -0
  30. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/config.py +0 -0
  31. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/datasource.py +0 -0
  32. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/exceptions.py +0 -0
  33. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/job.py +0 -0
  34. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/pipe.py +0 -0
  35. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/regions.py +0 -0
  36. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/tag.py +0 -0
  37. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/telemetry.py +0 -0
  38. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/test.py +0 -0
  39. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  40. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  41. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/token.py +0 -0
  42. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/workspace.py +0 -0
  43. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  44. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird/tornado_template.py +0 -0
  45. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird_cli.egg-info/SOURCES.txt +0 -0
  46. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird_cli.egg-info/dependency_links.txt +0 -0
  47. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird_cli.egg-info/entry_points.txt +0 -0
  48. {tinybird-cli-5.10.2.dev1 → tinybird-cli-5.10.2.dev2}/tinybird_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird-cli
3
- Version: 5.10.2.dev1
3
+ Version: 5.10.2.dev2
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,6 +18,10 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
+ 5.10.2.dev2
22
+ ***********
23
+
24
+ - `Changed` Use `aiofiles` for async operations
21
25
 
22
26
  5.10.2.dev1
23
27
  ***********
@@ -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__ = '5.10.2.dev1'
8
- __revision__ = '1019ea7'
7
+ __version__ = '5.10.2.dev2'
8
+ __revision__ = '7cb8efb'
@@ -6,6 +6,7 @@ from pathlib import Path
6
6
  from typing import Any, Callable, Dict, List, Mapping, Optional, Set, Union
7
7
  from urllib.parse import quote, urlencode
8
8
 
9
+ import aiofiles
9
10
  import requests
10
11
  import requests.adapters
11
12
  from requests import Response
@@ -421,11 +422,12 @@ class TinyB(object):
421
422
  for option in list(replace_options):
422
423
  params[option] = "true"
423
424
 
424
- with open(file, "rb") as content:
425
+ async with aiofiles.open(file, "rb") as content:
426
+ file_content = await content.read()
425
427
  if format == "csv":
426
- files = {"csv": ("csv", content)}
428
+ files = {"csv": ("csv", file_content)}
427
429
  else:
428
- files = {"ndjson": ("ndjson", content)}
430
+ files = {"ndjson": ("ndjson", file_content)}
429
431
 
430
432
  res = await self._req(
431
433
  f"v0/datasources?{urlencode(params, safe='')}",
@@ -3,6 +3,7 @@ from os import environ, getcwd
3
3
  from pathlib import Path
4
4
  from typing import Any, Dict, Optional
5
5
 
6
+ import aiofiles
6
7
  import click
7
8
 
8
9
  from tinybird import __cli__
@@ -79,8 +80,9 @@ async def get_config(host: str, token: Optional[str], semver: Optional[str] = No
79
80
  config_file = Path(getcwd()) / ".tinyb"
80
81
  config = {}
81
82
  try:
82
- with open(config_file) as file:
83
- config = json.loads(file.read())
83
+ async with aiofiles.open(config_file) as file:
84
+ res = await file.read()
85
+ config = json.loads(res)
84
86
  except IOError:
85
87
  pass
86
88
  except json.decoder.JSONDecodeError:
@@ -97,8 +99,8 @@ async def get_config(host: str, token: Optional[str], semver: Optional[str] = No
97
99
 
98
100
  async def write_config(config: Dict[str, Any], dest_file: str = ".tinyb"):
99
101
  config_file = Path(getcwd()) / dest_file
100
- with open(config_file, "w") as file:
101
- file.write(json.dumps(config, indent=4, sort_keys=True))
102
+ async with aiofiles.open(config_file, "w") as file:
103
+ await file.write(json.dumps(config, indent=4, sort_keys=True))
102
104
 
103
105
 
104
106
  def get_display_host(ui_host: str):
@@ -5,6 +5,7 @@ Datafile is like a Dockerfile but to describe ETL processes
5
5
  from asyncio import Semaphore, gather
6
6
  from datetime import datetime
7
7
 
8
+ import aiofiles
8
9
  from requests import Response
9
10
 
10
11
  try:
@@ -5239,7 +5240,7 @@ async def folder_pull(
5239
5240
  if verbose:
5240
5241
  click.echo(FeedbackManager.info_writing_resource(resource=f))
5241
5242
  if not f.exists() or force:
5242
- with open(f, "w") as fd:
5243
+ async with aiofiles.open(f, "w") as fd:
5243
5244
  # versions are a client only thing so
5244
5245
  # datafiles from the server do not contains information about versions
5245
5246
  if k["version"] >= 0:
@@ -5253,7 +5254,7 @@ async def folder_pull(
5253
5254
  m = match.split("__v")[0]
5254
5255
  if m in resources or m in resource_names:
5255
5256
  resource_to_write = resource_to_write.replace(match, m)
5256
- fd.write(resource_to_write)
5257
+ await fd.write(resource_to_write)
5257
5258
  else:
5258
5259
  if verbose:
5259
5260
  click.echo(FeedbackManager.info_skip_already_exists())
@@ -7,6 +7,7 @@ import os
7
7
  from os import getcwd
8
8
  from typing import List, Optional, Tuple
9
9
 
10
+ import aiofiles
10
11
  import click
11
12
  import yaml
12
13
 
@@ -79,8 +80,8 @@ async def print_releases(config: CLIConfig):
79
80
  async def release_generate(semver: str) -> None:
80
81
  click.echo(FeedbackManager.warning_deprecated_releases())
81
82
  if os.path.exists(".tinyenv"):
82
- with open(".tinyenv", "r") as env_file:
83
- lines = env_file.readlines()
83
+ async with aiofiles.open(".tinyenv", "r") as env_file:
84
+ lines = await env_file.readlines()
84
85
 
85
86
  updated_lines = []
86
87
  for line in lines:
@@ -89,18 +90,18 @@ async def release_generate(semver: str) -> None:
89
90
  else:
90
91
  updated_lines.append(line)
91
92
 
92
- with open(".tinyenv", "w") as env_file:
93
- env_file.writelines(updated_lines)
93
+ async with aiofiles.open(".tinyenv", "w") as env_file:
94
+ await env_file.writelines(updated_lines)
94
95
  else:
95
- with open(".tinyenv", "w") as env_file:
96
- env_file.write(f"VERSION={semver}\n")
96
+ async with aiofiles.open(".tinyenv", "w") as env_file:
97
+ await env_file.write(f"VERSION={semver}\n")
97
98
 
98
99
  deploy_dir = os.path.join("deploy", semver)
99
100
  os.makedirs(deploy_dir, exist_ok=True)
100
101
 
101
102
  deploy_file = os.path.join(deploy_dir, "deploy.sh")
102
- with open(deploy_file, "w") as deploy:
103
- deploy.write(
103
+ async with aiofiles.open(deploy_file, "w") as deploy:
104
+ await deploy.write(
104
105
  """\
105
106
  #!/bin/bash
106
107
  set -euxo pipefail
@@ -112,8 +113,8 @@ set -euxo pipefail
112
113
  os.chmod(deploy_file, 0o755)
113
114
 
114
115
  post_deploy_file = os.path.join(deploy_dir, "postdeploy.sh")
115
- with open(post_deploy_file, "w") as post_deploy:
116
- post_deploy.write(
116
+ async with aiofiles.open(post_deploy_file, "w") as post_deploy:
117
+ await post_deploy.write(
117
118
  """\
118
119
  #!/bin/bash
119
120
  set -euxo pipefail
@@ -550,7 +551,7 @@ async def regression_tests(
550
551
 
551
552
  if filename:
552
553
  try:
553
- with open(filename, "r") as file:
554
+ with open(filename, "r") as file: # noqa: ASYNC230
554
555
  regression_tests_commands = yaml.safe_load(file)
555
556
  except Exception as exc:
556
557
  raise CLIBranchException(FeedbackManager.error_regression_yaml_not_valid(filename=filename, error=exc))
@@ -21,6 +21,7 @@ from pathlib import Path
21
21
  from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, Set, Tuple, Union
22
22
  from urllib.parse import urlparse
23
23
 
24
+ import aiofiles
24
25
  import click
25
26
  import click.formatting
26
27
  import humanfriendly
@@ -310,13 +311,13 @@ async def _analyze(filename: str, client: TinyB, format: str, connector: Optiona
310
311
  if parsed.scheme in ("http", "https"):
311
312
  meta = await client.datasource_analyze(filename)
312
313
  else:
313
- with open(filename, "rb") as file:
314
+ async with aiofiles.open(filename, "rb") as file:
314
315
  # We need to read the whole file in binary for Parquet, while for the
315
316
  # others we just read 1KiB
316
317
  if format == "parquet":
317
- data = file.read()
318
+ data = await file.read()
318
319
  else:
319
- data = file.read(1024 * 1024)
320
+ data = await file.read(1024 * 1024)
320
321
 
321
322
  meta = await client.datasource_analyze_file(data)
322
323
  else:
@@ -360,8 +361,8 @@ async def folder_init(
360
361
  base = Path(".")
361
362
  f = base / (".tinyenv")
362
363
  if not f.exists() or force:
363
- with open(".tinyenv", "w") as file:
364
- file.write(DEFAULT_TINYENV_FILE)
364
+ async with aiofiles.open(".tinyenv", "w") as file:
365
+ await file.write(DEFAULT_TINYENV_FILE)
365
366
  click.echo(FeedbackManager.info_file_created(file=".tinyenv"))
366
367
  else:
367
368
  click.echo(FeedbackManager.info_dottinyenv_already_exists())
@@ -369,8 +370,8 @@ async def folder_init(
369
370
  base = Path(".")
370
371
  f = base / ("requirements.txt")
371
372
  if not f.exists() or force:
372
- with open("requirements.txt", "w") as file:
373
- file.write(DEFAULT_REQUIREMENTS_FILE)
373
+ async with aiofiles.open("requirements.txt", "w") as file:
374
+ await file.write(DEFAULT_REQUIREMENTS_FILE)
374
375
  click.echo(FeedbackManager.info_file_created(file="requirements.txt"))
375
376
 
376
377
  base = Path("scripts")
@@ -378,15 +379,15 @@ async def folder_init(
378
379
  base = Path()
379
380
  f = base / ("exec_test.sh")
380
381
  if not f.exists() or force:
381
- with open(f"{f}", "w") as t_file:
382
- t_file.write(EXEC_TEST_SH)
382
+ async with aiofiles.open(f"{f}", "w") as t_file:
383
+ await t_file.write(EXEC_TEST_SH)
383
384
  click.echo(FeedbackManager.info_file_created(file="scripts/exec_test.sh"))
384
385
  chmod(f, 0o755)
385
386
 
386
387
  f = base / ("append_fixtures.sh")
387
388
  if not f.exists() or force:
388
- with open(f"{f}", "w") as t_file:
389
- t_file.write(APPEND_FIXTURES_SH)
389
+ async with aiofiles.open(f"{f}", "w") as t_file:
390
+ await t_file.write(APPEND_FIXTURES_SH)
390
391
  click.echo(FeedbackManager.info_file_created(file="scripts/append_fixtures.sh"))
391
392
  chmod(f, 0o755)
392
393
 
@@ -395,8 +396,8 @@ async def folder_init(
395
396
  base = Path()
396
397
  f = base / ("example.yml")
397
398
  if not base.exists() or force:
398
- with open(f"{f}", "w") as t_file:
399
- t_file.write(
399
+ async with aiofiles.open(f"{f}", "w") as t_file:
400
+ await t_file.write(
400
401
  """
401
402
  ##############################################################################################################################
402
403
  ### Visit https://www.tinybird.co/docs/production/implementing-test-strategies.html#data-quality-tests ###
@@ -431,8 +432,8 @@ async def folder_init(
431
432
 
432
433
  f = base / ("regression.yaml")
433
434
  if not base.exists() or force:
434
- with open(f"{f}", "w") as t_file:
435
- t_file.write(
435
+ async with aiofiles.open(f"{f}", "w") as t_file:
436
+ await t_file.write(
436
437
  """
437
438
  ############################################################################################################################
438
439
  ### Visit https://www.tinybird.co/docs/production/implementing-test-strategies.html#regression-tests ###
@@ -2047,8 +2048,8 @@ async def create_aws_iamrole_connection(client: TinyB, service: str, connection_
2047
2048
  FeedbackManager.error_connection_create(connection_name=connection_name, error=str(e))
2048
2049
  )
2049
2050
 
2050
- with open(conn_file_path, "w") as f:
2051
- f.write(
2051
+ async with aiofiles.open(conn_file_path, "w") as f:
2052
+ await f.write(
2052
2053
  f"""TYPE {service}
2053
2054
 
2054
2055
  """
@@ -8,6 +8,7 @@ from os import getcwd
8
8
  from pathlib import Path
9
9
  from typing import Any, Dict, List, Optional
10
10
 
11
+ import aiofiles
11
12
  import click
12
13
  from click import Context
13
14
 
@@ -336,8 +337,8 @@ async def connection_create_snowflake(
336
337
  account, username, password, warehouse, role, connection_name, integration_name, stage_name
337
338
  )
338
339
 
339
- with open(conn_file_path, "w") as f:
340
- f.write(
340
+ async with aiofiles.open(conn_file_path, "w") as f:
341
+ await f.write(
341
342
  f"""TYPE snowflake
342
343
 
343
344
  USERNAME='{username}'
@@ -389,8 +390,8 @@ async def connection_create_bigquery(ctx: Context, no_validate: bool) -> None:
389
390
  click.echo(FeedbackManager.error_bigquery_improper_permissions())
390
391
 
391
392
  if connection_created:
392
- with open(Path(getcwd(), "bigquery.connection"), "w") as f:
393
- f.write("TYPE bigquery\n")
393
+ async with aiofiles.open(Path(getcwd(), "bigquery.connection"), "w") as f:
394
+ await f.write("TYPE bigquery\n")
394
395
  click.echo(FeedbackManager.success_connection_created(id="bigquery"))
395
396
 
396
397
 
@@ -528,8 +529,8 @@ async def connection_create_s3(
528
529
  click.echo("** Creating connection...")
529
530
  _ = await client.connection_create(params)
530
531
 
531
- with open(conn_file_path, "w") as f:
532
- f.write(
532
+ async with aiofiles.open(conn_file_path, "w") as f:
533
+ await f.write(
533
534
  """TYPE s3
534
535
 
535
536
  """
@@ -598,8 +599,8 @@ async def connection_create_gcs_hmac(
598
599
  FeedbackManager.error_connection_create(connection_name=connection_name, error=str(e))
599
600
  )
600
601
 
601
- with open(conn_file_path, "w") as f:
602
- f.write(
602
+ async with aiofiles.open(conn_file_path, "w") as f:
603
+ await f.write(
603
604
  """TYPE gcs_hmac
604
605
 
605
606
  """
@@ -700,8 +701,8 @@ async def connection_create_gcs(
700
701
  FeedbackManager.error_connection_create(connection_name=connection_name, error=str(e))
701
702
  )
702
703
 
703
- with open(conn_file_path, "w") as f:
704
- f.write(
704
+ async with aiofiles.open(conn_file_path, "w") as f:
705
+ await f.write(
705
706
  """TYPE {service}
706
707
 
707
708
  """
@@ -3,6 +3,7 @@ import sys
3
3
  from pathlib import Path
4
4
  from typing import List, Optional
5
5
 
6
+ import aiofiles
6
7
  import click
7
8
  from click import Context
8
9
 
@@ -60,8 +61,8 @@ async def fmt(
60
61
  if diff:
61
62
  result = result.rstrip("\n")
62
63
  lines_fmt = [f"{line}\n" for line in result.split("\n")]
63
- with open(filename, "r") as file:
64
- lines_file = file.readlines()
64
+ async with aiofiles.open(filename, "r") as file:
65
+ lines_file = await file.readlines()
65
66
  diff_result = difflib.unified_diff(
66
67
  lines_file, lines_fmt, fromfile=f"{Path(filename).name} local", tofile="fmt datafile"
67
68
  )
@@ -77,8 +78,8 @@ async def fmt(
77
78
  return None
78
79
 
79
80
  if yes or click.confirm(FeedbackManager.prompt_override_local_file(name=filename)):
80
- with open(f"{filename}", "w") as file:
81
- file.write(result)
81
+ async with aiofiles.open(f"{filename}", "w") as file:
82
+ await file.write(result)
82
83
 
83
84
  click.echo(FeedbackManager.success_generated_local_file(file=filename))
84
85
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird-cli
3
- Version: 5.10.2.dev1
3
+ Version: 5.10.2.dev2
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -18,6 +18,10 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
18
18
  Changelog
19
19
  ----------
20
20
 
21
+ 5.10.2.dev2
22
+ ***********
23
+
24
+ - `Changed` Use `aiofiles` for async operations
21
25
 
22
26
  5.10.2.dev1
23
27
  ***********
@@ -1,3 +1,4 @@
1
+ aiofiles==24.1.0
1
2
  click<8.2,>=8.1.6
2
3
  clickhouse-toolset==0.32.dev0
3
4
  colorama==0.4.6