From 1a1b8602dd8db88188fe2c00b84a7cefc878de71 Mon Sep 17 00:00:00 2001 From: jaik950 Date: Wed, 29 Oct 2025 18:19:03 -0400 Subject: [PATCH 1/2] fix lint issues --- .../age_and_gender_detection/main.py | 5 +-- .../age_and_gender_detection/model.py | 3 +- .../tests/test_main_age_gender.py | 37 ++++++++++++------- .../deepfake_detection/main.py | 14 ++++--- src/deepfake-detection/tests/test_server.py | 12 ++++-- .../test/test_app_main.py | 9 +++-- src/rb-api/rb/api/models.py | 3 +- src/rb-api/rb/api/routes/cli.py | 2 +- src/rb-lib/rb/lib/typer.py | 3 +- 9 files changed, 55 insertions(+), 33 deletions(-) diff --git a/src/age_and_gender_detection/age_and_gender_detection/main.py b/src/age_and_gender_detection/age_and_gender_detection/main.py index b6e1aae3..3996596f 100644 --- a/src/age_and_gender_detection/age_and_gender_detection/main.py +++ b/src/age_and_gender_detection/age_and_gender_detection/main.py @@ -78,13 +78,13 @@ def predict(inputs: Inputs) -> ResponseBody: for i, pred in enumerate(predictions): face_num = i + 1 image_basename = Path(image_path).name - + metadata = { "Image Path": image_path, "Gender": pred["gender"], "Age": pred["age"], "Bounding Box": str(pred["box"]), - #"Face Number": face_num, + # "Face Number": face_num, } file_responses.append( @@ -100,7 +100,6 @@ def predict(inputs: Inputs) -> ResponseBody: return ResponseBody(root=TextResponse(value="No faces detected in any images.")) return ResponseBody(root=BatchFileResponse(files=file_responses)) - def cli_parser(path: str): diff --git a/src/age_and_gender_detection/age_and_gender_detection/model.py b/src/age_and_gender_detection/age_and_gender_detection/model.py index 1c17b14a..3b2b53da 100644 --- a/src/age_and_gender_detection/age_and_gender_detection/model.py +++ b/src/age_and_gender_detection/age_and_gender_detection/model.py @@ -62,7 +62,8 @@ def __init__( ] session_options = ort.SessionOptions() self.runtime_providers = [ - "CUDAExecutionProvider", "CPUExecutionProvider", + "CUDAExecutionProvider", + "CPUExecutionProvider", ] self.genderList = ["Male", "Female"] self.image_file_extensions = [".jpg", ".jpeg", ".png", ".bmp", ".tiff"] diff --git a/src/age_and_gender_detection/tests/test_main_age_gender.py b/src/age_and_gender_detection/tests/test_main_age_gender.py index 100c618e..5b3a8a07 100644 --- a/src/age_and_gender_detection/tests/test_main_age_gender.py +++ b/src/age_and_gender_detection/tests/test_main_age_gender.py @@ -91,16 +91,24 @@ def test_age_gender_command(self, caplog): ] # Combine all log messages into one string for easier searching all_messages = " ".join(caplog.messages) - + for expected_file in expected_files: # Create multiple path representations to check for cross-platform compatibility - posix_path = expected_file.as_posix() # Forward slashes: src/age_and_gender_detection/test_images/gela.jpg - native_path = str(expected_file) # OS-native: src\age_and_gender_detection\test_images\gela.jpg on Windows - escaped_path = native_path.replace("\\", "\\\\") # Double-escaped: src\\\\age_and_gender_detection\\\\test_images\\\\gela.jpg - + posix_path = ( + expected_file.as_posix() + ) # Forward slashes: src/age_and_gender_detection/test_images/gela.jpg + native_path = str( + expected_file + ) # OS-native: src\age_and_gender_detection\test_images\gela.jpg on Windows + escaped_path = native_path.replace( + "\\", "\\\\" + ) # Double-escaped: src\\\\age_and_gender_detection\\\\test_images\\\\gela.jpg + # Check if any path representation appears in the log messages - assert any(path_repr in all_messages for path_repr in [posix_path, native_path, escaped_path]), \ - f"Expected file {expected_file} not found in log messages. Checked: {posix_path}, {native_path}, {escaped_path}" + assert any( + path_repr in all_messages + for path_repr in [posix_path, native_path, escaped_path] + ), f"Expected file {expected_file} not found in log messages. Checked: {posix_path}, {native_path}, {escaped_path}" def test_invalid_path(self): age_gender_api = f"/{APP_NAME}/predict" @@ -123,18 +131,21 @@ def test_age_gender_api(self): body = ResponseBody(**response.json()) print(f"Response body: {body}") assert body.root is not None - assert hasattr(body.root, 'files'), "Expected BatchFileResponse with files attribute" - + assert hasattr( + body.root, "files" + ), "Expected BatchFileResponse with files attribute" + # Convert BatchFileResponse to the old dict format for comparison files = body.root.files assert len(files) == 4, f"Expected 4 files, got {len(files)}" - + # Check that all expected images are present in the response returned_paths = {file_resp.path for file_resp in files} expected_paths = set(EXPECTED_OUTPUT.keys()) - assert returned_paths == expected_paths, \ - f"Mismatch in returned paths. Expected: {expected_paths}, Got: {returned_paths}" - + assert ( + returned_paths == expected_paths + ), f"Mismatch in returned paths. Expected: {expected_paths}, Got: {returned_paths}" + # Verify each file's predictions match expectations for file_resp in files: image_path = file_resp.path diff --git a/src/deepfake-detection/deepfake_detection/main.py b/src/deepfake-detection/deepfake_detection/main.py index 6bbc7c2a..57d6c73f 100644 --- a/src/deepfake-detection/deepfake_detection/main.py +++ b/src/deepfake-detection/deepfake_detection/main.py @@ -200,7 +200,7 @@ def give_prediction(inputs: Inputs, parameters: Parameters) -> ResponseBody: model_name = model_results[0]["model_name"] predictions = model_results[1:] model_data.append({"name": model_name, "predictions": predictions}) - + file_responses: List[FileResponse] = [] if model_data and model_data[0]["predictions"]: num_images = len(model_data[0]["predictions"]) @@ -217,20 +217,22 @@ def give_prediction(inputs: Inputs, parameters: Parameters) -> ResponseBody: model_name = m["name"] row_metadata["Prediction"] = pred row_metadata["Confidence"] = f"{conf * 100:.0f}%" - + file_responses.append( FileResponse( file_type="img", path=full_image_path, title=f"Prediction for {path_basename}", - metadata=row_metadata + metadata=row_metadata, ) ) if not file_responses: - return ResponseBody(root=TextResponse(value="No predictions generated or no images found.")) - + return ResponseBody( + root=TextResponse(value="No predictions generated or no images found.") + ) + return ResponseBody(root=BatchFileResponse(files=file_responses)) - + # ---------------------------- # Server Setup Below diff --git a/src/deepfake-detection/tests/test_server.py b/src/deepfake-detection/tests/test_server.py index 1ed09cbf..40f59028 100644 --- a/src/deepfake-detection/tests/test_server.py +++ b/src/deepfake-detection/tests/test_server.py @@ -64,8 +64,12 @@ def test_cli_predict(self, run_models_mock, defaultDataset_mock, caplog, tmp_pat # Verify the structured response in the log output # The CLI logs the BatchFileResponse which should contain our prediction assert "BatchFileResponse" in caplog.text, "Expected BatchFileResponse in logs" - assert "'Prediction': 'fake'" in caplog.text, "Expected prediction 'fake' in metadata" - assert "'Confidence': '100%'" in caplog.text, "Expected confidence '100%' in metadata" + assert ( + "'Prediction': 'fake'" in caplog.text + ), "Expected prediction 'fake' in metadata" + assert ( + "'Confidence': '100%'" in caplog.text + ), "Expected confidence '100%' in metadata" assert "img1.jpg" in caplog.text, "Expected img1.jpg in response" def test_invalid_path(self): @@ -112,7 +116,9 @@ def test_api_predict(self, run_models_mock, defaultDataset_mock, tmp_path): response = self.client.post(predict_api, json=payload) assert response.status_code == 200 body = ResponseBody(**response.json()) - assert hasattr(body.root, 'files'), "Expected BatchFileResponse with files attribute" + assert hasattr( + body.root, "files" + ), "Expected BatchFileResponse with files attribute" files = body.root.files assert len(files) == 1, f"Expected 1 file response, got {len(files)}" file_resp = files[0] diff --git a/src/face-detection-recognition/test/test_app_main.py b/src/face-detection-recognition/test/test_app_main.py index ce84b656..f232e319 100644 --- a/src/face-detection-recognition/test/test_app_main.py +++ b/src/face-detection-recognition/test/test_app_main.py @@ -349,15 +349,16 @@ def test_06_find_face_bulk_endpoint(self): assert response.status_code == 200 body = ResponseBody(**response.json()) - assert isinstance(body.root, BatchFileResponse), \ - f"Expected BatchFileResponse with matches, got {type(body.root)}" + assert isinstance( + body.root, BatchFileResponse + ), f"Expected BatchFileResponse with matches, got {type(body.root)}" # BatchFileResponse with matches print(f"Find face bulk result: {len(body.root.files)} matches found") # Verify the structure of file responses for file_resp in body.root.files: assert file_resp.file_type.value == "img" - assert hasattr(file_resp, 'metadata') - assert 'query_image' in file_resp.metadata + assert hasattr(file_resp, "metadata") + assert "query_image" in file_resp.metadata print(f" - {file_resp.title}") # @pytest.mark.skipif(not has_test_images, reason="Test images not available") diff --git a/src/rb-api/rb/api/models.py b/src/rb-api/rb/api/models.py index 33fcbbd1..eb8062e7 100644 --- a/src/rb-api/rb/api/models.py +++ b/src/rb-api/rb/api/models.py @@ -246,7 +246,8 @@ class FileResponse(BaseModel): path: str title: Optional[str] = None subtitle: Optional[str] = None - metadata: Optional[Dict[str, Any]] = None # additional columns like prediction + metadata: Optional[Dict[str, Any]] = None # additional columns like prediction + class DirectoryResponse(BaseModel): model_config = ConfigDict( diff --git a/src/rb-api/rb/api/routes/cli.py b/src/rb-api/rb/api/routes/cli.py index 0ade101c..4206e405 100644 --- a/src/rb-api/rb/api/routes/cli.py +++ b/src/rb-api/rb/api/routes/cli.py @@ -211,7 +211,7 @@ def is_get_request(command: typer.models.CommandInfo) -> bool: endpoint=command_callback(command), methods=["POST"], name=command.callback.__name__, - response_model=Any, # for internal use + response_model=Any, # for internal use ) logger.debug( f"Registering FastAPI route for {plugin.name} command: {command.callback.__name__}" diff --git a/src/rb-lib/rb/lib/typer.py b/src/rb-lib/rb/lib/typer.py index aadf3b73..38b80863 100644 --- a/src/rb-lib/rb/lib/typer.py +++ b/src/rb-lib/rb/lib/typer.py @@ -89,13 +89,14 @@ def get_inputs_from_signature( result.append(data) return result + def typer_app_to_tree(app: typer.Typer) -> dict: # Create root node root = Node("rescuebox", command=None, is_group=True) schema_commands = {} def add_commands_to_node(typer_app: typer.Typer, parent_node: Node): - + for group in getattr(typer_app, "registered_groups", []): group_node = Node( group.name, From 40b1464404ad0ea605e60b34ce4850fa1dbbf323 Mon Sep 17 00:00:00 2001 From: jaik950 Date: Wed, 29 Oct 2025 18:21:49 -0400 Subject: [PATCH 2/2] fix lint error in facematch --- .../face_detection_recognition/face_match_server.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/face-detection-recognition/face_detection_recognition/face_match_server.py b/src/face-detection-recognition/face_detection_recognition/face_match_server.py index 518ea620..d66d3ff6 100644 --- a/src/face-detection-recognition/face_detection_recognition/face_match_server.py +++ b/src/face-detection-recognition/face_detection_recognition/face_match_server.py @@ -314,18 +314,21 @@ def find_face_bulk_endpoint( file_type="img", path=matched_path, title=f"Match for {query_img_name}: {matched_filename}", - metadata={"query_image": query_img_name} + metadata={"query_image": query_img_name}, ) ) - + if not status or not file_responses: # If results is a string (e.g., an error message), use it directly # Otherwise, convert the dictionary to a string representation - error_message = str(results) if isinstance(results, str) else json.dumps(results, indent=2) + error_message = ( + str(results) if isinstance(results, str) else json.dumps(results, indent=2) + ) return ResponseBody(root=TextResponse(value=error_message)) - + return ResponseBody(root=BatchFileResponse(files=file_responses)) + server.add_ml_service( rule="/findfacebulk", ml_function=find_face_bulk_endpoint,