From 5b540d02805f2305b9359462e7a1ab2d88eabb5d Mon Sep 17 00:00:00 2001 From: Shahar Epstein <60007259+shahar1@users.noreply.github.com> Date: Fri, 15 May 2026 08:13:45 +0300 Subject: [PATCH 1/3] Enable ruff PLE1205 and fix 12 logging calls with too many arguments Extra positional arguments to logging methods are silently dropped when the format string has no corresponding placeholder. Enable PLE1205 (logging-too-many-args) and fix all 12 existing instances: - Add missing %s placeholders where the value was being discarded - Merge accidentally split message strings (ssm.py) - Replace {}-style placeholders with %s (four system test files) --- airflow-core/src/airflow/utils/log/file_task_handler.py | 2 +- .../airflow/providers/amazon/aws/operators/redshift_data.py | 5 +---- .../amazon/src/airflow/providers/amazon/aws/sensors/ssm.py | 6 +----- .../airflow/providers/amazon/aws/utils/task_log_fetcher.py | 4 ++-- .../src/airflow/providers/google/cloud/operators/compute.py | 4 ++-- .../src/airflow/providers/google/suite/hooks/drive.py | 2 +- .../tests/system/google/cloud/gcs/example_gcs_to_gdrive.py | 2 +- .../tests/system/google/cloud/gcs/example_gdrive_to_gcs.py | 2 +- .../google/cloud/transfers/example_gdrive_to_local.py | 2 +- .../tests/system/google/suite/example_local_to_drive.py | 2 +- pyproject.toml | 1 + 11 files changed, 13 insertions(+), 19 deletions(-) diff --git a/airflow-core/src/airflow/utils/log/file_task_handler.py b/airflow-core/src/airflow/utils/log/file_task_handler.py index c170adc875194..e2b6bcb6165b6 100644 --- a/airflow-core/src/airflow/utils/log/file_task_handler.py +++ b/airflow-core/src/airflow/utils/log/file_task_handler.py @@ -855,7 +855,7 @@ def _init_file(self, ti, *, identifier: str | None = None): try: os.chmod(full_path, new_file_permissions) except OSError as e: - logger.warning("OSError while changing ownership of the log file. ", e) + logger.warning("OSError while changing ownership of the log file. %s", e) return full_path diff --git a/providers/amazon/src/airflow/providers/amazon/aws/operators/redshift_data.py b/providers/amazon/src/airflow/providers/amazon/aws/operators/redshift_data.py index d92febf2e7f14..3168b9f69c425 100644 --- a/providers/amazon/src/airflow/providers/amazon/aws/operators/redshift_data.py +++ b/providers/amazon/src/airflow/providers/amazon/aws/operators/redshift_data.py @@ -120,10 +120,7 @@ def __init__( if poll_interval > 0: self.poll_interval = poll_interval else: - self.log.warning( - "Invalid poll_interval:", - poll_interval, - ) + self.log.warning("Invalid poll_interval: %s", poll_interval) self.return_sql_result = return_sql_result self.deferrable = deferrable self.session_id = session_id diff --git a/providers/amazon/src/airflow/providers/amazon/aws/sensors/ssm.py b/providers/amazon/src/airflow/providers/amazon/aws/sensors/ssm.py index 2874a553d5abf..943c960873095 100644 --- a/providers/amazon/src/airflow/providers/amazon/aws/sensors/ssm.py +++ b/providers/amazon/src/airflow/providers/amazon/aws/sensors/ssm.py @@ -108,11 +108,7 @@ def poke(self, context: Context): command_invocations = response.get("CommandInvocations", []) if not command_invocations: - self.log.info( - "No command invocations found", - "command_id=%s yet, waiting...", - self.command_id, - ) + self.log.info("No command invocations found, command_id=%s yet, waiting...", self.command_id) return False for invocation in command_invocations: diff --git a/providers/amazon/src/airflow/providers/amazon/aws/utils/task_log_fetcher.py b/providers/amazon/src/airflow/providers/amazon/aws/utils/task_log_fetcher.py index 24b426a536e20..c509c2a7fa7b4 100644 --- a/providers/amazon/src/airflow/providers/amazon/aws/utils/task_log_fetcher.py +++ b/providers/amazon/src/airflow/providers/amazon/aws/utils/task_log_fetcher.py @@ -84,7 +84,7 @@ def _get_log_events(self, skip_token: AwsLogsHook.ContinuationToken | None = Non ) except ClientError as error: if error.response["Error"]["Code"] != "ResourceNotFoundException": - self.logger.warning("Error on retrieving Cloudwatch log events", error) + self.logger.warning("Error on retrieving Cloudwatch log events: %s", error) else: self.logger.info( "Cannot find log stream yet, it can take a couple of seconds to show up. " @@ -95,7 +95,7 @@ def _get_log_events(self, skip_token: AwsLogsHook.ContinuationToken | None = Non ) yield from () except ConnectionClosedError as error: - self.logger.warning("ConnectionClosedError on retrieving Cloudwatch log events", error) + self.logger.warning("ConnectionClosedError on retrieving Cloudwatch log events: %s", error) yield from () @staticmethod diff --git a/providers/google/src/airflow/providers/google/cloud/operators/compute.py b/providers/google/src/airflow/providers/google/cloud/operators/compute.py index 9ae10b5c0917c..46d448213774e 100644 --- a/providers/google/src/airflow/providers/google/cloud/operators/compute.py +++ b/providers/google/src/airflow/providers/google/cloud/operators/compute.py @@ -1042,7 +1042,7 @@ def execute(self, context: Context) -> dict: request_id=self.request_id, project_id=self.project_id, ) - self.log.info("The specified Instance Template has been created SUCCESSFULLY", self.body) + self.log.info("The specified Instance Template has been created SUCCESSFULLY: %s", self.body) new_template = hook.get_instance_template( resource_id=self.resource_id, project_id=self.project_id, @@ -1611,7 +1611,7 @@ def execute(self, context: Context) -> dict: project_id=self.project_id, zone=self.zone, ) - self.log.info("The specified Instance Group Manager has been created SUCCESSFULLY", self.body) + self.log.info("The specified Instance Group Manager has been created SUCCESSFULLY: %s", self.body) new_instance_group_manager = hook.get_instance_group_manager( resource_id=self.resource_id, project_id=self.project_id, diff --git a/providers/google/src/airflow/providers/google/suite/hooks/drive.py b/providers/google/src/airflow/providers/google/suite/hooks/drive.py index 8f97feb76ae86..70918e758b0a8 100644 --- a/providers/google/src/airflow/providers/google/suite/hooks/drive.py +++ b/providers/google/src/airflow/providers/google/suite/hooks/drive.py @@ -304,7 +304,7 @@ def upload_file( try: upload_location = self._resolve_file_path(folder_id) except GoogleApiClientError as e: - self.log.warning("A problem has been encountered when trying to resolve file path: ", e) + self.log.warning("A problem has been encountered when trying to resolve file path: %s", e) if show_full_target_path: self.log.info("File %s uploaded to gdrive://%s.", local_location, upload_location) diff --git a/providers/google/tests/system/google/cloud/gcs/example_gcs_to_gdrive.py b/providers/google/tests/system/google/cloud/gcs/example_gcs_to_gdrive.py index 2fac6ccd088c4..270231dedf0e8 100644 --- a/providers/google/tests/system/google/cloud/gcs/example_gcs_to_gdrive.py +++ b/providers/google/tests/system/google/cloud/gcs/example_gcs_to_gdrive.py @@ -170,7 +170,7 @@ def remove_files_from_drive(): if files := root_path["files"]: batch = service.new_batch_http_request() for file in files: - log.info("Preparing to remove file: {}", file) + log.info("Preparing to remove file: %s", file) batch.add(service.files().delete(fileId=file["id"])) batch.execute() log.info("Selected files removed.") diff --git a/providers/google/tests/system/google/cloud/gcs/example_gdrive_to_gcs.py b/providers/google/tests/system/google/cloud/gcs/example_gdrive_to_gcs.py index 482d7b43003c0..ec5f6ab4ccaee 100644 --- a/providers/google/tests/system/google/cloud/gcs/example_gdrive_to_gcs.py +++ b/providers/google/tests/system/google/cloud/gcs/example_gdrive_to_gcs.py @@ -136,7 +136,7 @@ def remove_files_from_drive(): response = service.files().list(q=f"name = '{DRIVE_FILE_NAME}'").execute() if files := response["files"]: file = files[0] - log.info("Deleting file {}...", file) + log.info("Deleting file %s...", file) service.files().delete(fileId=file["id"]) log.info("Done.") diff --git a/providers/google/tests/system/google/cloud/transfers/example_gdrive_to_local.py b/providers/google/tests/system/google/cloud/transfers/example_gdrive_to_local.py index 42828c20ae991..38edfa9de1919 100644 --- a/providers/google/tests/system/google/cloud/transfers/example_gdrive_to_local.py +++ b/providers/google/tests/system/google/cloud/transfers/example_gdrive_to_local.py @@ -137,7 +137,7 @@ def remove_file_from_drive(): response = service.files().list(q=f"name = '{DRIVE_FILE_NAME}'").execute() if files := response["files"]: file = files[0] - log.info("Deleting file {}...", file) + log.info("Deleting file %s...", file) service.files().delete(fileId=file["id"]) log.info("Done.") diff --git a/providers/google/tests/system/google/suite/example_local_to_drive.py b/providers/google/tests/system/google/suite/example_local_to_drive.py index c248774423b8e..04a411d984c61 100644 --- a/providers/google/tests/system/google/suite/example_local_to_drive.py +++ b/providers/google/tests/system/google/suite/example_local_to_drive.py @@ -121,7 +121,7 @@ def remove_files_from_drive(): if files := root_path["files"]: batch = service.new_batch_http_request() for file in files: - log.info("Preparing to remove file: {}", file) + log.info("Preparing to remove file: %s", file) batch.add(service.files().delete(fileId=file["id"])) batch.execute() log.info("Selected files removed.") diff --git a/pyproject.toml b/pyproject.toml index 8352ecd83b0ec..e7504f3e007cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -628,6 +628,7 @@ extend-select = [ "PLW2101", # Threading lock directly created in with statement has no effect "PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target "PLW3301", # Nested {func} calls can be flattened + "PLE1205", # Logging format string has too many arguments (extra args are silently dropped) # Per rule enables "RUF006", # Checks for asyncio dangling task "RUF015", # Checks for unnecessary iterable allocation for first element From 9ce0d72587c55575f0c0a5d274a341dfcafb259c Mon Sep 17 00:00:00 2001 From: Shahar Epstein <60007259+shahar1@users.noreply.github.com> Date: Fri, 15 May 2026 12:49:02 +0300 Subject: [PATCH 2/3] Update providers/google/src/airflow/providers/google/suite/hooks/drive.py Co-authored-by: Wei Lee --- .../google/src/airflow/providers/google/suite/hooks/drive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/google/src/airflow/providers/google/suite/hooks/drive.py b/providers/google/src/airflow/providers/google/suite/hooks/drive.py index 70918e758b0a8..8e152d2df01c0 100644 --- a/providers/google/src/airflow/providers/google/suite/hooks/drive.py +++ b/providers/google/src/airflow/providers/google/suite/hooks/drive.py @@ -304,7 +304,7 @@ def upload_file( try: upload_location = self._resolve_file_path(folder_id) except GoogleApiClientError as e: - self.log.warning("A problem has been encountered when trying to resolve file path: %s", e) + self.log.exception("A problem has been encountered when trying to resolve file path:") if show_full_target_path: self.log.info("File %s uploaded to gdrive://%s.", local_location, upload_location) From 4fa39e5a1af11d6b5ab6f56fc772ae184eebe4eb Mon Sep 17 00:00:00 2001 From: Shahar Epstein <60007259+shahar1@users.noreply.github.com> Date: Fri, 15 May 2026 19:04:42 +0300 Subject: [PATCH 3/3] Fix log.exception --- .../google/src/airflow/providers/google/suite/hooks/drive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/google/src/airflow/providers/google/suite/hooks/drive.py b/providers/google/src/airflow/providers/google/suite/hooks/drive.py index 8e152d2df01c0..7d1257cf4edc7 100644 --- a/providers/google/src/airflow/providers/google/suite/hooks/drive.py +++ b/providers/google/src/airflow/providers/google/suite/hooks/drive.py @@ -304,7 +304,7 @@ def upload_file( try: upload_location = self._resolve_file_path(folder_id) except GoogleApiClientError as e: - self.log.exception("A problem has been encountered when trying to resolve file path:") + self.log.exception("A problem has been encountered when trying to resolve file path: %s", e) if show_full_target_path: self.log.info("File %s uploaded to gdrive://%s.", local_location, upload_location)