From 8c05e1ebdcd415300af1415084a53b5f77896498 Mon Sep 17 00:00:00 2001 From: Leila Mansouri Date: Wed, 11 Mar 2026 14:21:31 +0100 Subject: [PATCH 1/4] fixed queue filtering --- cloudos_cli/clos.py | 69 +++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/cloudos_cli/clos.py b/cloudos_cli/clos.py index 99e751ec..bcef2c41 100644 --- a/cloudos_cli/clos.py +++ b/cloudos_cli/clos.py @@ -1179,6 +1179,24 @@ def get_job_list(self, workspace_id, last_n_jobs=None, page=None, page_size=None user_id = self.resolve_user_id(filter_owner, workspace_id, verify) params["user.id"] = user_id + # --- Resolve queue ID before pagination (for local filtering during pagination) --- + queue_id = None + if filter_queue: + try: + from cloudos_cli.queue.queue import Queue + queue_api = Queue(self.cloudos_url, self.apikey, self.cromwell_token, workspace_id, verify) + queues = queue_api.get_job_queues() + + for queue in queues: + if queue.get("label") == filter_queue or queue.get("name") == filter_queue: + queue_id = queue.get("id") or queue.get("_id") + break + + if not queue_id: + raise ValueError(f"Queue with name '{filter_queue}' not found in workspace '{workspace_id}'") + except Exception as e: + raise ValueError(f"Error resolving queue '{filter_queue}'. {str(e)}") + # --- Fetch jobs page by page --- all_jobs = [] params["limit"] = current_page_size @@ -1201,51 +1219,46 @@ def get_job_list(self, workspace_id, last_n_jobs=None, page=None, page_size=None if not page_jobs: break + # Apply queue filter during pagination (if specified) + if filter_queue and queue_id: + page_jobs = [job for job in page_jobs if job.get("batch", {}).get("jobQueue", {}) == queue_id] + all_jobs.extend(page_jobs) # Check stopping conditions based on mode if use_pagination_mode: - # In pagination mode (last_n_jobs), continue until we have enough jobs + # In pagination mode (last_n_jobs), continue until we have enough jobs (after filtering) if target_job_count != 'all' and len(all_jobs) >= target_job_count: break else: - # In direct mode (page/page_size), only get one page - break + # In direct mode (page/page_size), only get one page unless filter_queue is used + # When filter_queue is used, continue fetching pages until we have enough filtered results + if not filter_queue or len(all_jobs) >= current_page_size: + break # Check if we reached the last page (fewer jobs than requested page size) - if len(page_jobs) < params["limit"]: + # Note: For queue filter, we check the unfiltered page_jobs count from the API + # This ensures we stop when the API has exhausted results + raw_page_jobs = content.get('jobs', []) + if len(raw_page_jobs) < params["limit"]: break # Last page current_page += 1 - # --- Local queue filtering (not supported by API) --- - if filter_queue: - try: - batch_jobs=[job for job in all_jobs if job.get("batch", {})] - if batch_jobs: - from cloudos_cli.queue.queue import Queue - queue_api = Queue(self.cloudos_url, self.apikey, self.cromwell_token, workspace_id, verify) - queues = queue_api.get_job_queues() - - queue_id = None - for queue in queues: - if queue.get("label") == filter_queue or queue.get("name") == filter_queue: - queue_id = queue.get("id") or queue.get("_id") - break - - if not queue_id: - raise ValueError(f"Queue with name '{filter_queue}' not found in workspace '{workspace_id}'") - - all_jobs = [job for job in all_jobs if job.get("batch", {}).get("jobQueue", {}) == queue_id] - else: - raise ValueError(f"The environment is not a batch environment so queues do not exist. Please remove the --filter-queue option.") - except Exception as e: - raise ValueError(f"Error filtering by queue '{filter_queue}'. {str(e)}") - # --- Apply limit after all filtering --- if use_pagination_mode and target_job_count != 'all' and isinstance(target_job_count, int) and target_job_count > 0: all_jobs = all_jobs[:target_job_count] + # --- Validate queue filtering (check if environment is batch) --- + if filter_queue: + # Check if any jobs actually are batch jobs (non-batch jobs won't have jobQueue) + batch_jobs = [job for job in all_jobs if job.get("batch", {})] + if not batch_jobs: + # No batch jobs found - verify environment actually has batch capability + # by checking if any batch jobs exist in workspace at all + # Note: This is a best-effort check with the current page being fetched + raise ValueError(f"The environment is not a batch environment so queues do not exist. Please remove the --filter-queue option.") + return {'jobs': all_jobs, 'pagination_metadata': last_pagination_metadata} @staticmethod From 71278f2d4c4385e62657083c229a819910971132 Mon Sep 17 00:00:00 2001 From: Leila Mansouri Date: Wed, 11 Mar 2026 16:54:06 +0100 Subject: [PATCH 2/4] updates changelog --- CHANGELOG.md | 2 +- cloudos_cli/_version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22317db3..bcf38bcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## lifebit-ai/cloudos-cli: changelog -## v2.81.3 (2026-03-11) +## v2.82.1 (2026-03-11) ### Patch diff --git a/cloudos_cli/_version.py b/cloudos_cli/_version.py index d3fa789f..c03de08a 100644 --- a/cloudos_cli/_version.py +++ b/cloudos_cli/_version.py @@ -1 +1 @@ -__version__ = '2.81.3' +__version__ = '2.82.1' From 9da0bd7b8f146c96d0c5a894adcd7dcd0b823ece Mon Sep 17 00:00:00 2001 From: Leila Mansouri Date: Wed, 11 Mar 2026 17:26:08 +0100 Subject: [PATCH 3/4] adress cursor --- cloudos_cli/clos.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cloudos_cli/clos.py b/cloudos_cli/clos.py index bcef2c41..694b20f4 100644 --- a/cloudos_cli/clos.py +++ b/cloudos_cli/clos.py @@ -1249,16 +1249,6 @@ def get_job_list(self, workspace_id, last_n_jobs=None, page=None, page_size=None if use_pagination_mode and target_job_count != 'all' and isinstance(target_job_count, int) and target_job_count > 0: all_jobs = all_jobs[:target_job_count] - # --- Validate queue filtering (check if environment is batch) --- - if filter_queue: - # Check if any jobs actually are batch jobs (non-batch jobs won't have jobQueue) - batch_jobs = [job for job in all_jobs if job.get("batch", {})] - if not batch_jobs: - # No batch jobs found - verify environment actually has batch capability - # by checking if any batch jobs exist in workspace at all - # Note: This is a best-effort check with the current page being fetched - raise ValueError(f"The environment is not a batch environment so queues do not exist. Please remove the --filter-queue option.") - return {'jobs': all_jobs, 'pagination_metadata': last_pagination_metadata} @staticmethod From f6691b49bb72a9a82561a6c038fbd2cc33756843 Mon Sep 17 00:00:00 2001 From: Leila Mansouri Date: Wed, 11 Mar 2026 17:58:43 +0100 Subject: [PATCH 4/4] address cursor --- cloudos_cli/clos.py | 10 +++++++++- tests/test_clos/test_get_job_list_filtering.py | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cloudos_cli/clos.py b/cloudos_cli/clos.py index 694b20f4..f6a9f0a0 100644 --- a/cloudos_cli/clos.py +++ b/cloudos_cli/clos.py @@ -1220,8 +1220,16 @@ def get_job_list(self, workspace_id, last_n_jobs=None, page=None, page_size=None break # Apply queue filter during pagination (if specified) + # jobQueue is a dict with "id" and "name" keys, extract the id for comparison if filter_queue and queue_id: - page_jobs = [job for job in page_jobs if job.get("batch", {}).get("jobQueue", {}) == queue_id] + filtered_jobs = [] + for job in page_jobs: + job_queue = job.get("batch", {}).get("jobQueue", {}) + # jobQueue is a dict like {"id": "...", "name": "...", ...} + job_queue_id = job_queue.get("id") if isinstance(job_queue, dict) else job_queue + if job_queue_id == queue_id: + filtered_jobs.append(job) + page_jobs = filtered_jobs all_jobs.extend(page_jobs) diff --git a/tests/test_clos/test_get_job_list_filtering.py b/tests/test_clos/test_get_job_list_filtering.py index a29167f0..6232e5bd 100644 --- a/tests/test_clos/test_get_job_list_filtering.py +++ b/tests/test_clos/test_get_job_list_filtering.py @@ -23,7 +23,7 @@ "user": {"id": USER_ID, "name": "Test User"}, "project": {"id": PROJECT_ID, "name": "test-project"}, "workflow": {"id": WORKFLOW_ID, "name": "test-workflow"}, - "batch": {"jobQueue": QUEUE_ID} + "batch": {"jobQueue": {"id": QUEUE_ID, "name": "v41"}} }, { "_id": "job2", @@ -32,7 +32,7 @@ "user": {"id": "other_user_id", "name": "Other User"}, "project": {"id": "other_project_id", "name": "other-project"}, "workflow": {"id": "other_workflow_id", "name": "other-workflow"}, - "batch": {"jobQueue": "other_queue_id"} + "batch": {"jobQueue": {"id": "other_queue_id", "name": "other-queue"}} } ] }