From bc8dac3b0b106a04526f0385b5d30d6569f39234 Mon Sep 17 00:00:00 2001 From: Nathan Thorpe Date: Mon, 6 Oct 2025 11:54:07 -0700 Subject: [PATCH 1/4] override user agent and cleanup --- cirro/cirro_client.py | 4 +-- cirro/cli/controller.py | 57 +++++++++++++++++------------------------ 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/cirro/cirro_client.py b/cirro/cirro_client.py index 2deeef12..63a46b5b 100644 --- a/cirro/cirro_client.py +++ b/cirro/cirro_client.py @@ -12,7 +12,7 @@ class CirroApi: """ Client for interacting directly with the Cirro API """ - def __init__(self, auth_info: AuthInfo = None, base_url: str = None): + def __init__(self, auth_info: AuthInfo = None, base_url: str = None, user_agent = 'Cirro SDK'): """ Instantiates the Cirro API object @@ -40,7 +40,7 @@ def __init__(self, auth_info: AuthInfo = None, base_url: str = None): self._api_client = CirroApiClient( base_url=self._configuration.rest_endpoint, auth_method=auth_info.get_auth_method(), - client_name='Cirro SDK', + client_name=user_agent, package_name='cirro' ) diff --git a/cirro/cli/controller.py b/cirro/cli/controller.py index 8f61d5f5..c601aecb 100644 --- a/cirro/cli/controller.py +++ b/cirro/cli/controller.py @@ -22,7 +22,6 @@ from cirro.models.process import PipelineDefinition, ConfigAppStatus, CONFIG_APP_URL from cirro.services.service_helpers import list_all_datasets -NO_PROJECTS = "No projects available" # Log to STDOUT log_formatter = logging.Formatter( '%(asctime)s %(levelname)-8s [Cirro CLI] %(message)s' @@ -36,13 +35,8 @@ def run_list_datasets(input_params: ListArguments, interactive=False): """List the datasets available in a particular project.""" - _check_configure() - cirro = CirroApi() - logger.info(f"Collecting data from {cirro.configuration.base_url}") - projects = cirro.projects.list() - - if len(projects) == 0: - raise InputError(NO_PROJECTS) + cirro = _init_cirro_client() + projects = _get_projects(cirro) if interactive: # Prompt the user for the project @@ -62,17 +56,10 @@ def run_list_datasets(input_params: ListArguments, interactive=False): def run_ingest(input_params: UploadArguments, interactive=False): - _check_configure() - cirro = CirroApi() - logger.info(f"Collecting data from {cirro.configuration.base_url}") + cirro = _init_cirro_client() + projects = _get_projects(cirro) processes = cirro.processes.list(process_type=Executor.INGEST) - logger.info("Listing available projects") - projects = cirro.projects.list() - - if len(projects) == 0: - raise InputError(NO_PROJECTS) - if interactive: input_params, files = gather_upload_arguments(input_params, projects, processes) directory = input_params['data_directory'] @@ -120,15 +107,8 @@ def run_ingest(input_params: UploadArguments, interactive=False): def run_download(input_params: DownloadArguments, interactive=False): - _check_configure() - cirro = CirroApi() - logger.info(f"Collecting data from {cirro.configuration.base_url}") - - logger.info("Listing available projects") - projects = cirro.projects.list() - - if len(projects) == 0: - raise InputError(NO_PROJECTS) + cirro = _init_cirro_client() + projects = _get_projects(cirro) files_to_download = None if interactive: @@ -176,15 +156,9 @@ def run_download(input_params: DownloadArguments, interactive=False): def run_upload_reference(input_params: UploadReferenceArguments, interactive=False): - _check_configure() - cirro = CirroApi() - logger.info(f"Collecting data from {cirro.configuration.base_url}") - + cirro = _init_cirro_client() + projects = _get_projects(cirro) reference_types = cirro.references.get_types() - projects = cirro.projects.list() - - if len(projects) == 0: - raise InputError(NO_PROJECTS) if interactive: input_params, files = gather_reference_upload_arguments(input_params, projects, reference_types) @@ -255,6 +229,21 @@ def run_create_pipeline_config(input_params: CreatePipelineConfigArguments, inte f"{CONFIG_APP_URL}") +def _init_cirro_client(): + _check_configure() + cirro = CirroApi(user_agent="Cirro CLI") + logger.info(f"Collecting data from {cirro.configuration.base_url}") + return cirro + + +def _get_projects(cirro: CirroApi): + logger.info("Listing available projects") + projects = cirro.projects.list() + if len(projects) == 0: + raise InputError("No projects available") + return projects + + def _check_configure(): """ Prompts the user to do initial configuration if needed From 29d3cb62741469f3ce290c5bdcf995a6c13693ee Mon Sep 17 00:00:00 2001 From: Nathan Thorpe Date: Mon, 6 Oct 2025 11:55:01 -0700 Subject: [PATCH 2/4] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a7d2aac1..d8afb95f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "cirro" -version = "1.8.0" +version = "1.9.0" description = "CLI tool and SDK for interacting with the Cirro platform" authors = ["Cirro Bio "] license = "MIT" From df75e0b73e5f02f49d4603dc901c15455461116b Mon Sep 17 00:00:00 2001 From: Nathan Thorpe Date: Mon, 6 Oct 2025 12:05:02 -0700 Subject: [PATCH 3/4] merge --- cirro/cli/controller.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cirro/cli/controller.py b/cirro/cli/controller.py index 5398b1b8..d3724372 100644 --- a/cirro/cli/controller.py +++ b/cirro/cli/controller.py @@ -108,15 +108,8 @@ def run_ingest(input_params: UploadArguments, interactive=False): def run_validate_folder(input_params: ValidateArguments, interactive=False): - _check_configure() - cirro = CirroApi() - logger.info(f"Collecting data from {cirro.configuration.base_url}") - - logger.info("Listing available projects") - projects = cirro.projects.list() - - if len(projects) == 0: - raise InputError(NO_PROJECTS) + cirro = _init_cirro_client() + projects = _get_projects(cirro) if interactive: input_params = gather_validate_arguments(input_params, projects) From d9941d29a5b87b170bdce300848f9f9029532dbc Mon Sep 17 00:00:00 2001 From: Nathan Thorpe Date: Mon, 6 Oct 2025 12:08:41 -0700 Subject: [PATCH 4/4] lint --- cirro/cirro_client.py | 2 +- cirro/cli/controller.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cirro/cirro_client.py b/cirro/cirro_client.py index 63a46b5b..fc19d74c 100644 --- a/cirro/cirro_client.py +++ b/cirro/cirro_client.py @@ -12,7 +12,7 @@ class CirroApi: """ Client for interacting directly with the Cirro API """ - def __init__(self, auth_info: AuthInfo = None, base_url: str = None, user_agent = 'Cirro SDK'): + def __init__(self, auth_info: AuthInfo = None, base_url: str = None, user_agent: str = 'Cirro SDK'): """ Instantiates the Cirro API object diff --git a/cirro/cli/controller.py b/cirro/cli/controller.py index d3724372..d62095d9 100644 --- a/cirro/cli/controller.py +++ b/cirro/cli/controller.py @@ -134,18 +134,18 @@ def run_validate_folder(input_params: ValidateArguments, interactive=False): logger.info("Validating files") - validation_results = cirro.datasets.validate_folder( + results = cirro.datasets.validate_folder( project_id=project_id, dataset_id=dataset_id, local_folder=input_params['data_directory'] ) for file_list, label, log_level in [ - (validation_results.files_matching, "✅ Matched Files (identical in Cirro and locally)", logging.INFO), - (validation_results.files_not_matching, "⚠️ Checksum Mismatches (same file name, different content)", logging.WARNING), - (validation_results.files_missing, "⚠️ Missing Locally (present in system but not found locally)", logging.WARNING), - (validation_results.local_only_files, "⚠️ Unexpected Local Files (present locally but not in system)", logging.WARNING), - (validation_results.validate_errors, "⚠️ Validation Failed (checksums may not be available)", logging.WARNING) + (results.files_matching, "✅ Matched Files (identical in Cirro and locally)", logging.INFO), + (results.files_not_matching, "⚠️ Checksum Mismatches (same file name, different content)", logging.WARNING), + (results.files_missing, "⚠️ Missing Locally (present in system but not found locally)", logging.WARNING), + (results.local_only_files, "⚠️ Unexpected Local Files (present locally but not in system)", logging.WARNING), + (results.validate_errors, "⚠️ Validation Failed (checksums may not be available)", logging.WARNING) ]: logger.log(level=log_level, msg=f"{label}: {len(file_list):,}") for file in file_list: