Repository: srhoton/python-service-history
Pull request #9: ruff fixes
Author: login: srhoton
Created: 2025-05-10T00:25:43Z | Merged: 2025-05-10T00:25:49Z



Diff:
diff --git a/pyproject.toml b/pyproject.toml
index 6f768e0..a862662 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -50,9 +50,12 @@ select = [
     "A",  # flake8-builtins
     "RUF", # Ruff-specific rules
 ]
-ignore = ["ANN101", "ANN102"]
+ignore = [
+    "S101",  # Allow assert in tests
+    "B017"   # Allow pytest.raises(Exception)
+]
 
-[tool.ruff.pydocstyle]
+[tool.ruff.lint.pydocstyle]
 convention = "google"
 
 [tool.ruff.format]
diff --git a/tests/__init__.py b/tests/__init__.py
index ea81726..0c21888 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,5 +1,5 @@
 """Service history lambda function test package.
 
-This package contains tests for the AWS Lambda functions 
+This package contains tests for the AWS Lambda functions
 that handle service history logging and retrieval.
 """
diff --git a/tests/test_lambda_handler.py b/tests/test_lambda_handler.py
index 04786ea..52d6722 100644
--- a/tests/test_lambda_handler.py
+++ b/tests/test_lambda_handler.py
@@ -26,7 +26,7 @@
 @pytest.fixture
 def mock_appconfig() -> MagicMock:
     """Set up mock AppConfig client for testing.
-    
+
     Returns:
         Mock AppConfig client.
     """
@@ -43,7 +43,7 @@ def mock_appconfig() -> MagicMock:
 @pytest.fixture
 def set_environment_variables() -> None:
     """Set up environment variables for testing.
-    
+
     Sets required environment variables and cleans them up after test.
     """
     os.environ["APPCONFIG_APP_ID"] = "TestApp"
@@ -73,8 +73,8 @@ def test_extract_id_from_path(self) -> None:
             extract_id_from_path("")
 
     def test_get_log_group_name(
-        self, 
-        mock_appconfig: MagicMock, 
+        self,
+        mock_appconfig: MagicMock,
         set_environment_variables: None
     ) -> None:
         """Test retrieval of log group name from AppConfig."""
@@ -98,10 +98,10 @@ def test_validate_create_input(self) -> None:
         # Valid inputs
         validate_create_input({"key": "value"})
         validate_create_input({"multiple": "values", "number": 123})
-        
+
         # Empty dict is valid
         validate_create_input({})
-        
+
         # Invalid inputs
         with pytest.raises(ValidationError):
             validate_create_input("not a dict")  # type: ignore
@@ -141,18 +141,18 @@ def setup_method(self, method: object) -> None:
     def test_write_to_cloudwatch(self) -> None:
         """Test writing data to CloudWatch Logs."""
         test_data = {"message": "Test message", "value": 123}
-        
+
         # Mock the CloudWatch Logs client
         mock_logs_client = MagicMock()
-        
+
         # Set up the mock to return a sequence number for put_log_events
         mock_logs_client.put_log_events.return_value = {
             "nextSequenceToken": "next-token"
         }
-        
+
         # Set up a timestamp for consistent testing
         timestamp = int(time.time() * 1000)
-        
+
         # Test the write function
         with patch("src.lambda_function.lambda_handler.logs_client", mock_logs_client):
             with patch("src.lambda_function.lambda_handler.int") as mock_int:
@@ -162,24 +162,24 @@ def test_write_to_cloudwatch(self) -> None:
                     self.id_value,
                     test_data
                 )
-        
+
         # Verify create_log_stream was called with correct arguments
         mock_logs_client.create_log_stream.assert_called_once()
         call_args = mock_logs_client.create_log_stream.call_args[1]
         assert call_args['logGroupName'] == self.log_group_name
         assert self.id_value in call_args['logStreamName']
-        
+
         # Verify that put_log_events was called with correct arguments
         mock_logs_client.put_log_events.assert_called_once()
         call_args = mock_logs_client.put_log_events.call_args[1]
         assert call_args['logGroupName'] == self.log_group_name
         assert self.id_value in call_args['logStreamName']
-        
+
         # Check the log event content
         log_events = call_args['logEvents']
         assert len(log_events) == 1
         assert log_events[0]['timestamp'] == timestamp
-        
+
         # Verify the message content
         event_data = json.loads(log_events[0]['message'])
         assert event_data['id'] == self.id_value
@@ -190,12 +190,12 @@ def test_query_cloudwatch_logs(self) -> None:
         """Test querying CloudWatch Logs."""
         # Mock the CloudWatch Logs client
         mock_logs_client = MagicMock()
-        
+
         # Set up the mock to return a query ID and then results
         mock_logs_client.start_query.return_value = {
             "queryId": "test-query-id"
         }
-        
+
         mock_logs_client.get_query_results.return_value = {
             "status": "Complete",
             "results": [
@@ -206,7 +206,7 @@ def test_query_cloudwatch_logs(self) -> None:
                 ]
             ]
         }
-        
+
         # Test the query function
         with patch("src.lambda_function.lambda_handler.logs_client", mock_logs_client):
             start_time = datetime.now() - timedelta(hours=1)
@@ -245,8 +245,8 @@ class TestEventHandlers:
     @patch("src.lambda_function.lambda_handler.get_log_group_name")
     @patch("src.lambda_function.lambda_handler.write_to_cloudwatch")
     def test_handle_create_event_api_gateway(
-        self, 
-        mock_write: MagicMock, 
+        self,
+        mock_write: MagicMock,
         mock_get_log_group: MagicMock
     ) -> None:
         """Test handling create event from API Gateway."""
@@ -274,8 +274,8 @@ def test_handle_create_event_api_gateway(
     @patch("src.lambda_function.lambda_handler.get_log_group_name")
     @patch("src.lambda_function.lambda_handler.write_to_cloudwatch")
     def test_handle_create_event_appsync(
-        self, 
-        mock_write: MagicMock, 
+        self,
+        mock_write: MagicMock,
         mock_get_log_group: MagicMock
     ) -> None:
         """Test handling create event from AppSync."""
@@ -308,8 +308,8 @@ def test_handle_create_event_appsync(
     @patch("src.lambda_function.lambda_handler.get_log_group_name")
     @patch("src.lambda_function.lambda_handler.query_cloudwatch_logs")
     def test_handle_read_event_api_gateway(
-        self, 
-        mock_query: MagicMock, 
+        self,
+        mock_query: MagicMock,
         mock_get_log_group: MagicMock
     ) -> None:
         """Test handling read event from API Gateway."""
@@ -343,8 +343,8 @@ def test_handle_read_event_api_gateway(
     @patch("src.lambda_function.lambda_handler.get_log_group_name")
     @patch("src.lambda_function.lambda_handler.query_cloudwatch_logs")
     def test_handle_read_event_appsync(
-        self, 
-        mock_query: MagicMock, 
+        self,
+        mock_query: MagicMock,
         mock_get_log_group: MagicMock
     ) -> None:
         """Test handling read event from AppSync."""
@@ -380,8 +380,8 @@ class TestLambdaHandler:
     @patch("src.lambda_function.lambda_handler.handle_create_event")
     @patch("src.lambda_function.lambda_handler.handle_read_event")
     def test_lambda_handler_api_gateway(
-        self, 
-        mock_read: MagicMock, 
+        self,
+        mock_read: MagicMock,
         mock_create: MagicMock
     ) -> None:
         """Test lambda_handler with API Gateway events."""
@@ -416,8 +416,8 @@ def test_lambda_handler_api_gateway(
     @patch("src.lambda_function.lambda_handler.handle_create_event")
     @patch("src.lambda_function.lambda_handler.handle_read_event")
     def test_lambda_handler_appsync(
-        self, 
-        mock_read: MagicMock, 
+        self,
+        mock_read: MagicMock,
         mock_create: MagicMock
     ) -> None:
         """Test lambda_handler with AppSync events."""


Reviews:
user: login: amazon-q-developer[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-10T00:26:38Z
user: login: amazon-q-developer[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-10T00:27:21Z

Review comments:
diff_hunk: @@ -343,8 +343,8 @@ def test_handle_read_event_api_gateway(
     @patch("src.lambda_function.lambda_handler.get_log_group_name")
     @patch("src.lambda_function.lambda_handler.query_cloudwatch_logs")
     def test_handle_read_event_appsync(
path: tests/test_lambda_handler.py
user: login: amazon-q-developer[bot]
body: ****Description:**** The test method is quite long and could be split into smaller, more focused test cases. Consider splitting the test into separate methods for different aspects of the AppSync event handling.

****Severity:**** Low


created_at: 2025-05-10T00:26:38Z
author_association: NONE
diff_hunk: @@ -343,8 +343,8 @@ def test_handle_read_event_api_gateway(
     @patch("src.lambda_function.lambda_handler.get_log_group_name")
     @patch("src.lambda_function.lambda_handler.query_cloudwatch_logs")
     def test_handle_read_event_appsync(
path: tests/test_lambda_handler.py
user: login: amazon-q-developer[bot]
body: The fix addresses the comment by splitting the long test method `test_handle_read_event_appsync` into smaller, more focused test cases. The main test method now calls helper methods for setup, event creation, and assertion, improving readability and maintainability. This refactoring makes the test more modular and easier to understand, while still covering the same functionality.
```suggestion
def test_handle_read_event_appsync(
        self,
        mock_query: MagicMock,
        mock_get_log_group: MagicMock
    ) -> None:
        """Test handling read event from AppSync."""
        self._setup_appsync_mocks(mock_get_log_group, mock_query)
        appsync_event = self._create_appsync_event()

        response = handle_read_event(appsync_event)

        self._assert_appsync_response(response)
        mock_query.assert_called_once()

    def _setup_appsync_mocks(self, mock_get_log_group: MagicMock, mock_query: MagicMock) -> None:
        mock_get_log_group.return_value = "test-log-group"
        mock_query.return_value = [{"id": "test-id", "message": "Test AppSync record"}]

    def _create_appsync_event(self) -> dict:
        return {
            "info": {
                "fieldName": "getServiceEvents",
                "parentTypeName": "Query"
            },
            "arguments": {
                "id": "test-id",
                "start": "2023-01-01T00:00:00Z",
                "end": "2023-01-02T00:00:00Z"
            }
        }

    def _assert_appsync_response(self, response: dict) -> None:
        assert response["statusCode"] == 200
        response_body = json.loads(response["body"])
        assert response_body["id"] == "test-id"
        assert response_body["count"] == 1


class TestLambdaHandler:
    """Tests for the main Lambda handler function."""

    @patch("src.lambda_function.lambda_handler.handle_create_event")
```

created_at: 2025-05-10T00:27:21Z
author_association: NONE

PR comments:
user: login: amazon-q-developer[bot]
created_at: 2025-05-10T00:25:47Z
body: :hourglass_flowing_sand: I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done
author_association: NONE
user: login: amazon-q-developer[bot]
created_at: 2025-05-10T00:26:39Z
body: :white_check_mark: I finished the code review, and left comments with the issues I found. I will now generate code fix suggestions.
author_association: NONE