This is an automated email from the ASF dual-hosted git repository.

shahar1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 2ed6805b0b6 Enable ruff B015 to catch silent no-op comparisons in 
tests (#66977)
2ed6805b0b6 is described below

commit 2ed6805b0b6a8c6b9b2bbb138f6a2fb9d22020bb
Author: Shahar Epstein <[email protected]>
AuthorDate: Sat May 16 08:24:45 2026 +0300

    Enable ruff B015 to catch silent no-op comparisons in tests (#66977)
---
 .../unit/cli/commands/test_api_server_command.py   |  2 +-
 airflow-core/tests/unit/jobs/test_scheduler_job.py |  6 ++---
 airflow-core/tests/unit/models/test_dag.py         |  2 +-
 .../unit/serialization/test_dag_serialization.py   |  4 +--
 .../airflow_aux/test_pod_template_file.py          |  2 +-
 .../aws/executors/batch/test_batch_executor.py     |  4 +--
 .../unit/amazon/aws/operators/test_bedrock.py      | 11 ++++++--
 .../amazon/aws/operators/test_emr_serverless.py    | 10 ++------
 .../aws/operators/test_sagemaker_processing.py     |  2 +-
 .../aws/operators/test_sagemaker_transform.py      |  2 +-
 .../amazon/aws/utils/test_waiter_with_logging.py   |  2 +-
 .../executors/test_kubernetes_executor.py          |  2 +-
 .../tests/unit/google/cloud/hooks/test_bigquery.py |  2 +-
 .../unit/google/cloud/transfers/test_sql_to_gcs.py | 29 ++++++++--------------
 pyproject.toml                                     |  1 +
 .../observability/metrics/test_otel_logger.py      |  4 +--
 .../tests/task_sdk/definitions/test_taskgroup.py   |  4 +--
 17 files changed, 41 insertions(+), 48 deletions(-)

diff --git a/airflow-core/tests/unit/cli/commands/test_api_server_command.py 
b/airflow-core/tests/unit/cli/commands/test_api_server_command.py
index 93c2c43e27b..4d6e3f62d5b 100644
--- a/airflow-core/tests/unit/cli/commands/test_api_server_command.py
+++ b/airflow-core/tests/unit/cli/commands/test_api_server_command.py
@@ -302,7 +302,7 @@ class TestCliApiServer(_CommonCLIUvicornTestClass):
                 ]
         else:
             assert mock_daemon.mock_calls == []
-            mock_setup_locations.mock_calls == []
+            assert mock_setup_locations.mock_calls == []
             mock_pid_file.assert_not_called()
             mock_open.assert_not_called()
 
diff --git a/airflow-core/tests/unit/jobs/test_scheduler_job.py 
b/airflow-core/tests/unit/jobs/test_scheduler_job.py
index eb763635ddf..ff1222c1222 100644
--- a/airflow-core/tests/unit/jobs/test_scheduler_job.py
+++ b/airflow-core/tests/unit/jobs/test_scheduler_job.py
@@ -3743,7 +3743,7 @@ class TestSchedulerJob:
 
         dr = dag_maker.create_dagrun(start_date=timezone.utcnow() - 
datetime.timedelta(days=1))
         # check that next_dagrun is dr.logical_date
-        dag_maker.dag_model.next_dagrun == dr.logical_date
+        assert dag_maker.dag_model.next_dagrun == dr.logical_date
         scheduler_job = Job()
         self.job_runner = SchedulerJobRunner(job=scheduler_job, 
executors=[self.null_exec])
 
@@ -4600,7 +4600,7 @@ class TestSchedulerJob:
         dr = drs[0]
 
         self.job_runner._schedule_dag_run(dag_run=dr, session=session)
-        len(self.job_runner.scheduler_dag_bag.get_dag_for_run(dr, 
session).tasks) == 1
+        assert len(self.job_runner.scheduler_dag_bag.get_dag_for_run(dr, 
session).tasks) == 1
         dag_version_1 = DagVersion.get_latest_version(dr.dag_id, 
session=session)
         assert dr.dag_versions[-1].id == dag_version_1.id
 
@@ -5799,7 +5799,7 @@ class TestSchedulerJob:
         dag_models = query.all()
         self.job_runner._create_dag_runs(dag_models, session)
         dr = session.scalars(select(DagRun)).one()
-        dr.state == DagRunState.QUEUED
+        assert dr.state == DagRunState.QUEUED
         assert session.scalar(select(func.count()).select_from(DagRun)) == 1
         assert dag_maker.dag_model.next_dagrun_create_after == DEFAULT_DATE + 
timedelta(days=2)
         assert dag_maker.dag_model.next_dagrun == DEFAULT_DATE + 
timedelta(days=1)
diff --git a/airflow-core/tests/unit/models/test_dag.py 
b/airflow-core/tests/unit/models/test_dag.py
index b34ab12dd4a..f9751684e35 100644
--- a/airflow-core/tests/unit/models/test_dag.py
+++ b/airflow-core/tests/unit/models/test_dag.py
@@ -3567,7 +3567,7 @@ class TestTaskClearingSetupTeardownBehavior:
         # now, we know that t1 is the teardown for s1, so now we know that s1 
will be "torn down"
         # by the time w4 runs, so we now know that w4 no longer requires s1, 
so when we clear w4,
         # s1 will not also be cleared
-        self.cleared_downstream(w4) == {w4}
+        assert self.cleared_downstream(w4) == {w4}
         assert set(w1.get_upstreams_only_setups_and_teardowns()) == {s1, t1}
         assert self.cleared_downstream(w1) == {s1, w1, w2, w3, t1, w4}
         assert self.cleared_upstream(w1) == {s1, w1, t1}
diff --git a/airflow-core/tests/unit/serialization/test_dag_serialization.py 
b/airflow-core/tests/unit/serialization/test_dag_serialization.py
index 0a40f67314e..8d8cb113c2e 100644
--- a/airflow-core/tests/unit/serialization/test_dag_serialization.py
+++ b/airflow-core/tests/unit/serialization/test_dag_serialization.py
@@ -935,9 +935,9 @@ class TestStringifiedDAGs:
         if isinstance(task, MappedOperator):
             # MappedOperator.operator_class now stores only minimal type 
information
             # for memory efficiency (task_type and _operator_name).
-            serialized_task.operator_class["task_type"] == type(task).__name__
+            assert serialized_task.operator_class["task_type"] == 
task.operator_class.__name__
             if isinstance(serialized_task.operator_class, DecoratedOperator):
-                serialized_task.operator_class["_operator_name"] == 
task._operator_name
+                assert serialized_task.operator_class["_operator_name"] == 
task._operator_name
 
             # Serialization cleans up default values in partial_kwargs, this
             # adds them back to both sides.
diff --git a/chart/tests/helm_tests/airflow_aux/test_pod_template_file.py 
b/chart/tests/helm_tests/airflow_aux/test_pod_template_file.py
index 579235cf7bf..bbad368fcb3 100644
--- a/chart/tests/helm_tests/airflow_aux/test_pod_template_file.py
+++ b/chart/tests/helm_tests/airflow_aux/test_pod_template_file.py
@@ -1600,7 +1600,7 @@ class TestPodTemplateFile:
             show_only=["templates/pod-template-file.yaml"],
             chart_dir=self.temp_chart_dir,
         )
-        jmespath.search("spec.containers[1].name", docs[0]) == 
"worker-kerberos"
+        assert jmespath.search("spec.containers[1].name", docs[0]) == 
"worker-kerberos"
 
         assert {
             "name": "config",
diff --git 
a/providers/amazon/tests/unit/amazon/aws/executors/batch/test_batch_executor.py 
b/providers/amazon/tests/unit/amazon/aws/executors/batch/test_batch_executor.py
index 00af3ca330d..00c3d622dcb 100644
--- 
a/providers/amazon/tests/unit/amazon/aws/executors/batch/test_batch_executor.py
+++ 
b/providers/amazon/tests/unit/amazon/aws/executors/batch/test_batch_executor.py
@@ -397,7 +397,7 @@ class TestAwsBatchExecutor:
             submit_job_args["containerOverrides"]["command"] = 
airflow_commands[i]
             assert mock_executor.batch.submit_job.call_args_list[i].kwargs == 
submit_job_args
         assert len(mock_executor.pending_jobs) == 1
-        mock_executor.pending_jobs[0].command == airflow_cmd1
+        assert mock_executor.pending_jobs[0].command == airflow_cmd1
         assert len(mock_executor.active_workers.get_all_jobs()) == 1
 
         # Add more tasks to pending_jobs. This simulates tasks being scheduled 
by Airflow
@@ -417,7 +417,7 @@ class TestAwsBatchExecutor:
             submit_job_args["containerOverrides"]["command"] = 
airflow_commands[i]
             assert mock_executor.batch.submit_job.call_args_list[i].kwargs == 
submit_job_args
         assert len(mock_executor.pending_jobs) == 1
-        mock_executor.pending_jobs[0].command == airflow_cmd1
+        assert mock_executor.pending_jobs[0].command == airflow_cmd1
         assert len(mock_executor.active_workers.get_all_jobs()) == 3
 
         airflow_commands.append(airflow_cmd1)
diff --git a/providers/amazon/tests/unit/amazon/aws/operators/test_bedrock.py 
b/providers/amazon/tests/unit/amazon/aws/operators/test_bedrock.py
index 0fb0eba8f08..7c6b1531fa4 100644
--- a/providers/amazon/tests/unit/amazon/aws/operators/test_bedrock.py
+++ b/providers/amazon/tests/unit/amazon/aws/operators/test_bedrock.py
@@ -174,13 +174,20 @@ class TestBedrockCustomizeModelOperator:
     @mock.patch.object(BedrockHook, "get_waiter")
     def test_ensure_unique_job_name(self, _, side_effect, ensure_unique_name, 
mock_conn, bedrock_hook):
         mock_conn.create_model_customization_job.side_effect = side_effect
-        expected_call_count = len(side_effect) if ensure_unique_name else 1
+        self.operator.ensure_unique_job_name = ensure_unique_name
         self.operator.wait_for_completion = False
+        expected_call_count = len(side_effect) if ensure_unique_name else 1
+
+        if not ensure_unique_name and any(isinstance(e, ClientError) for e in 
side_effect):
+            with pytest.raises(ClientError):
+                self.operator.execute({})
+            assert mock_conn.create_model_customization_job.call_count == 
expected_call_count
+            return
 
         response = self.operator.execute({})
 
         assert response == self.CUSTOMIZE_JOB_ARN
-        mock_conn.create_model_customization_job.call_count == 
expected_call_count
+        assert mock_conn.create_model_customization_job.call_count == 
expected_call_count
         bedrock_hook.get_waiter.assert_not_called()
         self.operator.defer.assert_not_called()
 
diff --git 
a/providers/amazon/tests/unit/amazon/aws/operators/test_emr_serverless.py 
b/providers/amazon/tests/unit/amazon/aws/operators/test_emr_serverless.py
index c851114e665..75fcf1bce3d 100644
--- a/providers/amazon/tests/unit/amazon/aws/operators/test_emr_serverless.py
+++ b/providers/amazon/tests/unit/amazon/aws/operators/test_emr_serverless.py
@@ -78,11 +78,6 @@ class TestEmrServerlessCreateApplicationOperator:
             "applicationId": application_id,
             "ResponseMetadata": {"HTTPStatusCode": 200},
         }
-        mock_conn.get_application.side_effect = [
-            {"application": {"state": "CREATED"}},
-            {"application": {"state": "STARTED"}},
-        ]
-
         operator = EmrServerlessCreateApplicationOperator(
             task_id=task_id,
             release_label=release_label,
@@ -111,7 +106,6 @@ class TestEmrServerlessCreateApplicationOperator:
 
         
mock_conn.start_application.assert_called_once_with(applicationId=application_id)
         assert id == application_id
-        mock_conn.get_application.call_count == 2
 
     @mock.patch.object(EmrServerlessHook, "get_waiter")
     @mock.patch.object(EmrServerlessHook, "conn")
@@ -234,7 +228,7 @@ class TestEmrServerlessCreateApplicationOperator:
             type=job_type,
             **config,
         )
-        mock_conn.create_application.call_count == 2
+        assert mock_conn.create_application.call_count == 2
 
     @mock.patch.object(EmrServerlessHook, "get_waiter")
     @mock.patch.object(EmrServerlessHook, "conn")
@@ -823,7 +817,7 @@ class TestEmrServerlessStartJobOperator:
         assert "Serverless Job failed:" in str(ex_message.value)
         default_name = operator.name
 
-        mock_conn.get_application.call_count == 2
+        assert mock_conn.get_application.call_count == 1
         mock_conn.start_job_run.assert_called_once_with(
             clientToken=client_request_token,
             applicationId=application_id,
diff --git 
a/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_processing.py 
b/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_processing.py
index df21010a8ee..a18058c745e 100644
--- 
a/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_processing.py
+++ 
b/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_processing.py
@@ -149,7 +149,7 @@ class TestSageMakerProcessingOperator:
                 (key3,) = key3_raw
                 assert sagemaker.config[key1][key2][key3] == 
int(sagemaker.config[key1][key2][key3])
             else:
-                sagemaker.config[key1][key2] == 
int(sagemaker.config[key1][key2])
+                assert sagemaker.config[key1][key2] == 
int(sagemaker.config[key1][key2])
 
     @mock.patch.object(SageMakerHook, "describe_processing_job")
     @mock.patch.object(SageMakerHook, "count_processing_jobs_by_name", 
return_value=0)
diff --git 
a/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_transform.py 
b/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_transform.py
index c91dbedb4d3..40c86115c48 100644
--- 
a/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_transform.py
+++ 
b/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_transform.py
@@ -103,7 +103,7 @@ class TestSageMakerTransformOperator:
                 (key3,) = key3_org
                 assert self.sagemaker.config[key1][key2][key3] == 
int(self.sagemaker.config[key1][key2][key3])
             else:
-                self.sagemaker.config[key1][key2] == 
int(self.sagemaker.config[key1][key2])
+                assert self.sagemaker.config[key1][key2] == 
int(self.sagemaker.config[key1][key2])
 
     @mock.patch.object(SageMakerHook, "describe_transform_job")
     @mock.patch.object(SageMakerHook, "create_model")
diff --git 
a/providers/amazon/tests/unit/amazon/aws/utils/test_waiter_with_logging.py 
b/providers/amazon/tests/unit/amazon/aws/utils/test_waiter_with_logging.py
index 6636f4cdb3a..716af7fbdd1 100644
--- a/providers/amazon/tests/unit/amazon/aws/utils/test_waiter_with_logging.py
+++ b/providers/amazon/tests/unit/amazon/aws/utils/test_waiter_with_logging.py
@@ -269,7 +269,7 @@ class TestWaiter:
                 "MaxAttempts": 1,
             },
         )
-        mock_waiter.wait.call_count == 3
+        assert mock_waiter.wait.call_count == 3
         mock_sleep.assert_called_with(123)
 
     @mock.patch("time.sleep")
diff --git 
a/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/executors/test_kubernetes_executor.py
 
b/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/executors/test_kubernetes_executor.py
index 354fdbf05c9..9269c4debd0 100644
--- 
a/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/executors/test_kubernetes_executor.py
+++ 
b/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/executors/test_kubernetes_executor.py
@@ -1639,7 +1639,7 @@ class TestKubernetesExecutor:
         assert not executor.has_task(task_instance=ti)
         executor.kube_scheduler.patch_pod_revoked.assert_called_once()
         executor.kube_scheduler.delete_pod.assert_called_once()
-        mock_kube_client.patch_namespaced_pod.calls[0] == []
+        mock_kube_client.patch_namespaced_pod.assert_not_called()
         assert executor.running == set()
 
     @pytest.mark.parametrize(
diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigquery.py 
b/providers/google/tests/unit/google/cloud/hooks/test_bigquery.py
index e750b42084c..ddacebbdbe1 100644
--- a/providers/google/tests/unit/google/cloud/hooks/test_bigquery.py
+++ b/providers/google/tests/unit/google/cloud/hooks/test_bigquery.py
@@ -1303,7 +1303,7 @@ class TestBigQueryCursor(_BigQueryBaseTestClass):
     def test_fetchone(self, mock_next, mock_get_client):
         bq_cursor = self.hook.get_cursor()
         result = bq_cursor.fetchone()
-        mock_next.call_count == 1
+        assert mock_next.call_count == 1
         assert mock_next.return_value == result
 
     
@mock.patch("airflow.providers.google.cloud.hooks.bigquery.BigQueryHook.get_client")
diff --git 
a/providers/google/tests/unit/google/cloud/transfers/test_sql_to_gcs.py 
b/providers/google/tests/unit/google/cloud/transfers/test_sql_to_gcs.py
index b252ae198d6..6c069b83335 100644
--- a/providers/google/tests/unit/google/cloud/transfers/test_sql_to_gcs.py
+++ b/providers/google/tests/unit/google/cloud/transfers/test_sql_to_gcs.py
@@ -49,13 +49,15 @@ INPUT_DATA = [
     ["102", "business", "2017-05-24"],
     ["103", "non-profit", "2018-10-01"],
 ]
-OUTPUT_DATA = json.dumps(
+EXPECTED_JSON_ROW = json.dumps(
     {
         "column_a": "convert_type_return_value",
         "column_b": "convert_type_return_value",
         "column_c": "convert_type_return_value",
-    }
-).encode("utf-8")
+    },
+    sort_keys=True,
+    ensure_ascii=False,
+)
 SCHEMA_FILE = "schema_file.json"
 APP_JSON = "application/json"
 
@@ -163,6 +165,7 @@ class TestBaseSQLToGCSOperator:
         mock_file.flush.reset_mock()
         mock_upload.reset_mock()
         mock_file.close.reset_mock()
+        mock_file.write.reset_mock()
         cursor_mock.reset_mock()
 
         cursor_mock.__iter__ = Mock(return_value=iter(INPUT_DATA))
@@ -183,14 +186,8 @@ class TestBaseSQLToGCSOperator:
         }
 
         mock_query.assert_called_once()
-        mock_file.write.call_args_list == [
-            mock.call(OUTPUT_DATA),
-            mock.call(b"\n"),
-            mock.call(OUTPUT_DATA),
-            mock.call(b"\n"),
-            mock.call(OUTPUT_DATA),
-            mock.call(b"\n"),
-        ]
+        written = "".join(c.args[0] for c in mock_file.write.call_args_list)
+        assert written == (EXPECTED_JSON_ROW + "\n") * 3
         mock_upload.assert_called_once_with(
             BUCKET, FILENAME.format(0), TMP_FILE_NAME, mime_type=APP_JSON, 
gzip=False, metadata=None
         )
@@ -227,14 +224,8 @@ class TestBaseSQLToGCSOperator:
         }
 
         mock_query.assert_called_once()
-        mock_file.write.call_args_list == [
-            mock.call(OUTPUT_DATA),
-            mock.call(b"\n"),
-            mock.call(OUTPUT_DATA),
-            mock.call(b"\n"),
-            mock.call(OUTPUT_DATA),
-            mock.call(b"\n"),
-        ]
+        written = "".join(c.args[0] for c in mock_file.write.call_args_list)
+        assert written == (EXPECTED_JSON_ROW + "\n") * 3
 
         mock_file.flush.assert_called_once()
         mock_upload.assert_called_once_with(
diff --git a/pyproject.toml b/pyproject.toml
index e7504f3e007..fda1174169e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -601,6 +601,7 @@ extend-select = [
     "G", # flake8-logging-format rules
     "LOG", # flake8-logging rules, most of them autofixable
     "PT", # flake8-pytest-style rules
+    "B015", # Useless comparison: bare `a == b` is a no-op; prepend `assert` 
or remove
     "TID25", # flake8-tidy-imports rules
     "E", # pycodestyle rules
     "W", # pycodestyle rules
diff --git 
a/shared/observability/tests/observability/metrics/test_otel_logger.py 
b/shared/observability/tests/observability/metrics/test_otel_logger.py
index f4c4cd369bf..21d27789def 100644
--- a/shared/observability/tests/observability/metrics/test_otel_logger.py
+++ b/shared/observability/tests/observability/metrics/test_otel_logger.py
@@ -190,7 +190,7 @@ class TestOtelMetrics:
         assert mock_random.call_count == 2
         # add() is called once in the initial stats.incr and once for the decr 
that passed the rate check.
         self.map[full_name(name)].add.assert_has_calls(expected_calls)
-        self.map[full_name(name)].add.call_count == 2
+        assert self.map[full_name(name)].add.call_count == 2
 
     def test_gauge_new_metric(self, name):
         self.stats.gauge(name, value=1)
@@ -205,7 +205,7 @@ class TestOtelMetrics:
         self.stats.gauge(name, value=1, tags=tags)
 
         
self.meter.get_meter().create_gauge.assert_called_once_with(name=full_name(name))
-        self.map[key].attributes == tags
+        assert self.map[key].attributes == tags
 
     def test_gauge_existing_metric(self, name):
         self.stats.gauge(name, value=1)
diff --git a/task-sdk/tests/task_sdk/definitions/test_taskgroup.py 
b/task-sdk/tests/task_sdk/definitions/test_taskgroup.py
index ed03e6c6773..18c7f65faf2 100644
--- a/task-sdk/tests/task_sdk/definitions/test_taskgroup.py
+++ b/task-sdk/tests/task_sdk/definitions/test_taskgroup.py
@@ -774,8 +774,8 @@ def test_mapped_task_group_id_prefix_task_id():
     assert t1.task_id == "t1"
     assert t2.task_id == "g.t2"
 
-    dag.get_task("t1") == t1
-    dag.get_task("g.t2") == t2
+    assert dag.get_task("t1") == t1
+    assert dag.get_task("g.t2") == t2
 
 
 def test_pass_taskgroup_output_to_task():

Reply via email to