From 94b9452eba709702d86dfd414b407cac1a26840e Mon Sep 17 00:00:00 2001 From: Seyit Zor Date: Tue, 1 Oct 2024 12:28:47 +0200 Subject: [PATCH] Wrapper for async CLI commands (#105) * wrapper for async download cli * wrapper for async upload cli * version bump --- .pyproject_generation/pyproject_custom.toml | 2 +- README.md | 6 ++-- pyproject.toml | 2 +- src/ghga_connector/cli.py | 34 ++++++++++++++++++--- tests/integration/test_cli.py | 10 +++--- 5 files changed, 40 insertions(+), 14 deletions(-) diff --git a/.pyproject_generation/pyproject_custom.toml b/.pyproject_generation/pyproject_custom.toml index 44a2186..dafdbd1 100644 --- a/.pyproject_generation/pyproject_custom.toml +++ b/.pyproject_generation/pyproject_custom.toml @@ -1,6 +1,6 @@ [project] name = "ghga_connector" -version = "1.5.0" +version = "1.5.1" description = "GHGA Connector - A CLI client application for interacting with the GHGA system." dependencies = [ "typer~=0.12", diff --git a/README.md b/README.md index 7339005..99ee003 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,13 @@ We recommend using the provided Docker container. A pre-build version is available at [docker hub](https://hub.docker.com/repository/docker/ghga/ghga-connector): ```bash -docker pull ghga/ghga-connector:1.5.0 +docker pull ghga/ghga-connector:1.5.1 ``` Or you can build the container yourself from the [`./Dockerfile`](./Dockerfile): ```bash # Execute in the repo's root dir: -docker build -t ghga/ghga-connector:1.5.0 . +docker build -t ghga/ghga-connector:1.5.1 . ``` For production-ready deployment, we recommend using Kubernetes, however, @@ -40,7 +40,7 @@ for simple use cases, you could execute the service using docker on a single server: ```bash # The entrypoint is preconfigured: -docker run -p 8080:8080 ghga/ghga-connector:1.5.0 --help +docker run -p 8080:8080 ghga/ghga-connector:1.5.1 --help ``` If you prefer not to use containers, you may install the service from source: diff --git a/pyproject.toml b/pyproject.toml index 356494d..54f6027 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ classifiers = [ "Intended Audience :: Developers", ] name = "ghga_connector" -version = "1.5.0" +version = "1.5.1" description = "GHGA Connector - A CLI client application for interacting with the GHGA system." dependencies = [ "typer~=0.12", diff --git a/src/ghga_connector/cli.py b/src/ghga_connector/cli.py index f81e5b4..a8987c5 100644 --- a/src/ghga_connector/cli.py +++ b/src/ghga_connector/cli.py @@ -15,6 +15,7 @@ # """CLI-specific wrappers around core functions.""" +import asyncio import os import sys from dataclasses import dataclass @@ -181,7 +182,7 @@ def get_work_package_information( cli = typer.Typer(no_args_is_help=True) -async def upload( +def upload( *, file_id: str = typer.Option(..., help="The id of the file to upload"), file_path: Path = typer.Option(..., help="The path to the file to upload"), @@ -199,7 +200,20 @@ async def upload( False, help="Set this option in order to view traceback for errors." ), ): - """Command to upload a file""" + """Wrapper for the async upload function""" + asyncio.run( + async_upload(file_id, file_path, my_public_key_path, my_private_key_path, debug) + ) + + +async def async_upload( + file_id: str, + file_path: Path, + my_public_key_path: Path, + my_private_key_path: Path, + debug: bool = False, +): + """Upload a file asynchronously""" message_display = init_message_display(debug=debug) HttpxClientConfigurator.configure( exponential_backoff_max=CONFIG.exponential_backoff_max, @@ -226,7 +240,7 @@ async def upload( @cli.command(no_args_is_help=True) -async def download( +def download( *, output_dir: Path = typer.Option( ..., help="The directory to put the downloaded files into." @@ -247,7 +261,19 @@ async def download( False, help="Set this option in order to view traceback for errors." ), ): - """Command to download files""" + """Wrapper for the async download function""" + asyncio.run( + async_download(output_dir, my_public_key_path, my_private_key_path, debug) + ) + + +async def async_download( + output_dir: Path, + my_public_key_path: Path, + my_private_key_path: Path, + debug: bool = False, +): + """Download files asynchronously""" if not my_public_key_path.is_file(): raise exceptions.PubKeyFileDoesNotExistError(public_key_path=my_public_key_path) diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py index d5be340..ebd6c22 100644 --- a/tests/integration/test_cli.py +++ b/tests/integration/test_cli.py @@ -36,7 +36,7 @@ from pytest_httpx import HTTPXMock, httpx_mock # noqa: F401 from ghga_connector.cli import ( - download, + async_download, init_message_display, retrieve_upload_parameters, ) @@ -162,7 +162,7 @@ async def test_multipart_download( wps_api_url=api_url, ), ): - await download( + await async_download( output_dir=tmp_path, my_public_key_path=Path(PUBLIC_KEY_FILE), my_private_key_path=Path(PRIVATE_KEY_FILE), @@ -274,7 +274,7 @@ async def test_download( exceptions.UnauthorizedAPICallError, match="This is not the token you're looking for.", ): - await download( + await async_download( output_dir=output_dir, my_public_key_path=Path(PUBLIC_KEY_FILE), my_private_key_path=Path(PRIVATE_KEY_FILE), @@ -288,7 +288,7 @@ async def test_download( match="Endpoint file ID did not match file ID" " announced in work order token", ): - await download( + await async_download( output_dir=output_dir, my_public_key_path=Path(PUBLIC_KEY_FILE), my_private_key_path=Path(PRIVATE_KEY_FILE), @@ -301,7 +301,7 @@ async def test_download( if expected_exception else nullcontext() ): - await download( + await async_download( output_dir=output_dir, my_public_key_path=Path(PUBLIC_KEY_FILE), my_private_key_path=Path(PRIVATE_KEY_FILE),