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

sbp pushed a commit to branch sbp
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git


The following commit(s) were added to refs/heads/sbp by this push:
     new 5581675a Fix some code style problems
5581675a is described below

commit 5581675a3529afcf9f5db5179f16452b2687ebf2
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Feb 18 15:41:50 2026 +0000

    Fix some code style problems
---
 atr/tasks/checks/__init__.py             |  2 +-
 tests/unit/test_archive_root_variants.py | 54 +++++++++++------------
 tests/unit/test_cache.py                 | 10 ++---
 tests/unit/test_create_revision.py       | 28 ++++++------
 tests/unit/test_mail.py                  | 26 +++++------
 tests/unit/test_merge.py                 | 26 +++++------
 tests/unit/test_message.py               | 74 ++++++++++++++++----------------
 7 files changed, 111 insertions(+), 109 deletions(-)

diff --git a/atr/tasks/checks/__init__.py b/atr/tasks/checks/__init__.py
index 8b0d2830..db3616a9 100644
--- a/atr/tasks/checks/__init__.py
+++ b/atr/tasks/checks/__init__.py
@@ -374,7 +374,7 @@ async def resolve_cache_key(
     if file_hash:
         cache_key["file_hash"] = file_hash
 
-    if len(policy_keys) > 0 and policy is not None:
+    if (len(policy_keys) > 0) and (policy is not None):
         policy_dict = policy.model_dump(exclude_none=True)
         return {**cache_key, **args, **{k: policy_dict[k] for k in policy_keys 
if k in policy_dict}}
     else:
diff --git a/tests/unit/test_archive_root_variants.py 
b/tests/unit/test_archive_root_variants.py
index 23f4ba6d..c71ce3d7 100644
--- a/tests/unit/test_archive_root_variants.py
+++ b/tests/unit/test_archive_root_variants.py
@@ -98,11 +98,12 @@ async def 
test_targz_structure_accepts_src_suffix_variant(tmp_path: pathlib.Path
 
 
 @pytest.mark.asyncio
-async def 
test_targz_structure_rejects_package_root_without_package_json(tmp_path: 
pathlib.Path) -> None:
+async def test_targz_structure_rejects_npm_pack_filename_mismatch(tmp_path: 
pathlib.Path) -> None:
     archive_path = tmp_path / "example-1.2.3.tgz"
     _make_tar_gz_with_contents(
         archive_path,
         {
+            "package/package.json": json.dumps({"name": "different", 
"version": "1.2.3"}),
             "package/README.txt": "hello",
         },
     )
@@ -120,12 +121,18 @@ async def 
test_targz_structure_rejects_package_root_without_package_json(tmp_pat
     await targz.structure(args)
 
     assert any(status == sql.CheckResultStatus.FAILURE.value for status, _, _ 
in recorder.messages)
+    assert any("npm pack layout detected" in message for _, message, _ in 
recorder.messages)
 
 
 @pytest.mark.asyncio
-async def 
test_targz_structure_rejects_source_root_when_filename_has_no_suffix(tmp_path: 
pathlib.Path) -> None:
-    archive_path = tmp_path / "apache-example-1.2.3.tar.gz"
-    _make_tar_gz(archive_path, ["apache-example-1.2.3-source/README.txt"])
+async def 
test_targz_structure_rejects_package_root_without_package_json(tmp_path: 
pathlib.Path) -> None:
+    archive_path = tmp_path / "example-1.2.3.tgz"
+    _make_tar_gz_with_contents(
+        archive_path,
+        {
+            "package/README.txt": "hello",
+        },
+    )
     recorder = recorders.RecorderStub(archive_path, 
"tests.unit.test_archive_root_variants")
     args = checks.FunctionArguments(
         recorder=recorders.get_recorder(recorder),
@@ -143,8 +150,8 @@ async def 
test_targz_structure_rejects_source_root_when_filename_has_no_suffix(t
 
 
 @pytest.mark.asyncio
-async def 
test_targz_structure_rejects_source_root_when_filename_has_src_suffix(tmp_path: 
pathlib.Path) -> None:
-    archive_path = tmp_path / "apache-example-1.2.3-src.tar.gz"
+async def 
test_targz_structure_rejects_source_root_when_filename_has_no_suffix(tmp_path: 
pathlib.Path) -> None:
+    archive_path = tmp_path / "apache-example-1.2.3.tar.gz"
     _make_tar_gz(archive_path, ["apache-example-1.2.3-source/README.txt"])
     recorder = recorders.RecorderStub(archive_path, 
"tests.unit.test_archive_root_variants")
     args = checks.FunctionArguments(
@@ -163,9 +170,9 @@ async def 
test_targz_structure_rejects_source_root_when_filename_has_src_suffix(
 
 
 @pytest.mark.asyncio
-async def 
test_targz_structure_rejects_src_root_when_filename_has_no_suffix(tmp_path: 
pathlib.Path) -> None:
-    archive_path = tmp_path / "apache-example-1.2.3.tar.gz"
-    _make_tar_gz(archive_path, ["apache-example-1.2.3-src/README.txt"])
+async def 
test_targz_structure_rejects_source_root_when_filename_has_src_suffix(tmp_path: 
pathlib.Path) -> None:
+    archive_path = tmp_path / "apache-example-1.2.3-src.tar.gz"
+    _make_tar_gz(archive_path, ["apache-example-1.2.3-source/README.txt"])
     recorder = recorders.RecorderStub(archive_path, 
"tests.unit.test_archive_root_variants")
     args = checks.FunctionArguments(
         recorder=recorders.get_recorder(recorder),
@@ -183,8 +190,8 @@ async def 
test_targz_structure_rejects_src_root_when_filename_has_no_suffix(tmp_
 
 
 @pytest.mark.asyncio
-async def 
test_targz_structure_rejects_src_root_when_filename_has_source_suffix(tmp_path: 
pathlib.Path) -> None:
-    archive_path = tmp_path / "apache-example-1.2.3-source.tar.gz"
+async def 
test_targz_structure_rejects_src_root_when_filename_has_no_suffix(tmp_path: 
pathlib.Path) -> None:
+    archive_path = tmp_path / "apache-example-1.2.3.tar.gz"
     _make_tar_gz(archive_path, ["apache-example-1.2.3-src/README.txt"])
     recorder = recorders.RecorderStub(archive_path, 
"tests.unit.test_archive_root_variants")
     args = checks.FunctionArguments(
@@ -203,15 +210,9 @@ async def 
test_targz_structure_rejects_src_root_when_filename_has_source_suffix(
 
 
 @pytest.mark.asyncio
-async def test_targz_structure_rejects_npm_pack_filename_mismatch(tmp_path: 
pathlib.Path) -> None:
-    archive_path = tmp_path / "example-1.2.3.tgz"
-    _make_tar_gz_with_contents(
-        archive_path,
-        {
-            "package/package.json": json.dumps({"name": "different", 
"version": "1.2.3"}),
-            "package/README.txt": "hello",
-        },
-    )
+async def 
test_targz_structure_rejects_src_root_when_filename_has_source_suffix(tmp_path: 
pathlib.Path) -> None:
+    archive_path = tmp_path / "apache-example-1.2.3-source.tar.gz"
+    _make_tar_gz(archive_path, ["apache-example-1.2.3-src/README.txt"])
     recorder = recorders.RecorderStub(archive_path, 
"tests.unit.test_archive_root_variants")
     args = checks.FunctionArguments(
         recorder=recorders.get_recorder(recorder),
@@ -226,7 +227,6 @@ async def 
test_targz_structure_rejects_npm_pack_filename_mismatch(tmp_path: path
     await targz.structure(args)
 
     assert any(status == sql.CheckResultStatus.FAILURE.value for status, _, _ 
in recorder.messages)
-    assert any("npm pack layout detected" in message for _, message, _ in 
recorder.messages)
 
 
 def test_zipformat_structure_accepts_npm_pack_root(tmp_path: pathlib.Path) -> 
None:
@@ -267,11 +267,12 @@ def 
test_zipformat_structure_rejects_dated_src_suffix(tmp_path: pathlib.Path) ->
     assert "Root directory mismatch" in result["error"]
 
 
-def 
test_zipformat_structure_rejects_package_root_without_package_json(tmp_path: 
pathlib.Path) -> None:
+def test_zipformat_structure_rejects_npm_pack_filename_mismatch(tmp_path: 
pathlib.Path) -> None:
     archive_path = tmp_path / "example-1.2.3.zip"
     _make_zip_with_contents(
         archive_path,
         {
+            "package/package.json": json.dumps({"name": "different", 
"version": "1.2.3"}),
             "package/README.txt": "hello",
         },
     )
@@ -279,15 +280,15 @@ def 
test_zipformat_structure_rejects_package_root_without_package_json(tmp_path:
     result = zipformat._structure_check_core_logic(str(archive_path))
 
     assert result.get("error") is not None
-    assert "Root directory mismatch" in result["error"]
+    assert "npm pack layout detected" in result["error"]
+    assert result.get("root_dir") == "package"
 
 
-def test_zipformat_structure_rejects_npm_pack_filename_mismatch(tmp_path: 
pathlib.Path) -> None:
+def 
test_zipformat_structure_rejects_package_root_without_package_json(tmp_path: 
pathlib.Path) -> None:
     archive_path = tmp_path / "example-1.2.3.zip"
     _make_zip_with_contents(
         archive_path,
         {
-            "package/package.json": json.dumps({"name": "different", 
"version": "1.2.3"}),
             "package/README.txt": "hello",
         },
     )
@@ -295,8 +296,7 @@ def 
test_zipformat_structure_rejects_npm_pack_filename_mismatch(tmp_path: pathli
     result = zipformat._structure_check_core_logic(str(archive_path))
 
     assert result.get("error") is not None
-    assert "npm pack layout detected" in result["error"]
-    assert result.get("root_dir") == "package"
+    assert "Root directory mismatch" in result["error"]
 
 
 def _make_tar_gz(path: pathlib.Path, members: list[str]) -> None:
diff --git a/tests/unit/test_cache.py b/tests/unit/test_cache.py
index 12bf275b..a1657783 100644
--- a/tests/unit/test_cache.py
+++ b/tests/unit/test_cache.py
@@ -115,15 +115,15 @@ async def 
test_admins_get_async_uses_extensions_when_available(mock_app: MockApp
     assert result == frozenset({"async_alice"})
 
 
-def test_admins_get_returns_frozenset_from_extensions(mock_app: MockApp):
-    mock_app.extensions["admins"] = frozenset({"alice", "bob"})
+def test_admins_get_returns_empty_frozenset_when_not_set(mock_app: MockApp):
     result = cache.admins_get()
-    assert result == frozenset({"alice", "bob"})
+    assert result == frozenset()
 
 
-def test_admins_get_returns_empty_frozenset_when_not_set(mock_app: MockApp):
+def test_admins_get_returns_frozenset_from_extensions(mock_app: MockApp):
+    mock_app.extensions["admins"] = frozenset({"alice", "bob"})
     result = cache.admins_get()
-    assert result == frozenset()
+    assert result == frozenset({"alice", "bob"})
 
 
 @pytest.mark.asyncio
diff --git a/tests/unit/test_create_revision.py 
b/tests/unit/test_create_revision.py
index 62fe3150..d785a6d6 100644
--- a/tests/unit/test_create_revision.py
+++ b/tests/unit/test_create_revision.py
@@ -17,7 +17,7 @@
 
 import os
 import pathlib
-from unittest.mock import AsyncMock, MagicMock, patch
+import unittest.mock as mock
 
 import pytest
 
@@ -35,13 +35,13 @@ async def 
test_modify_failed_error_propagates_and_cleans_up(tmp_path: pathlib.Pa
         (path / "file.txt").write_text("Should be cleaned up.")
         raise types.FailedError("Intentional error")
 
-    mock_session = _mock_db_session(MagicMock())
+    mock_session = _mock_db_session(mock.MagicMock())
     participant = _make_participant()
 
     with (
-        patch.object(revision.db, "session", return_value=mock_session),
-        patch.object(revision.interaction, "latest_revision", 
new_callable=AsyncMock, return_value=None),
-        patch.object(revision.util, "get_tmp_dir", return_value=tmp_path),
+        mock.patch.object(revision.db, "session", return_value=mock_session),
+        mock.patch.object(revision.interaction, "latest_revision", 
new_callable=mock.AsyncMock, return_value=None),
+        mock.patch.object(revision.util, "get_tmp_dir", return_value=tmp_path),
     ):
         with pytest.raises(types.FailedError, match="Intentional error"):
             await participant.create_revision("proj", "1.0", "test", 
modify=modify)
@@ -52,16 +52,16 @@ async def 
test_modify_failed_error_propagates_and_cleans_up(tmp_path: pathlib.Pa
 
 
 def _make_participant() -> revision.CommitteeParticipant:
-    mock_write = MagicMock()
+    mock_write = mock.MagicMock()
     mock_write.authorisation.asf_uid = "test"
-    return revision.CommitteeParticipant(mock_write, MagicMock(), MagicMock(), 
"test")
+    return revision.CommitteeParticipant(mock_write, mock.MagicMock(), 
mock.MagicMock(), "test")
 
 
-def _mock_db_session(release: MagicMock) -> MagicMock:
-    mock_query = MagicMock()
-    mock_query.demand = AsyncMock(return_value=release)
-    mock_data = AsyncMock()
-    mock_data.release = MagicMock(return_value=mock_query)
-    mock_data.__aenter__ = AsyncMock(return_value=mock_data)
-    mock_data.__aexit__ = AsyncMock(return_value=False)
+def _mock_db_session(release: mock.MagicMock) -> mock.MagicMock:
+    mock_query = mock.MagicMock()
+    mock_query.demand = mock.AsyncMock(return_value=release)
+    mock_data = mock.AsyncMock()
+    mock_data.release = mock.MagicMock(return_value=mock_query)
+    mock_data.__aenter__ = mock.AsyncMock(return_value=mock_data)
+    mock_data.__aexit__ = mock.AsyncMock(return_value=False)
     return mock_data
diff --git a/tests/unit/test_mail.py b/tests/unit/test_mail.py
index 39a83398..e8586559 100644
--- a/tests/unit/test_mail.py
+++ b/tests/unit/test_mail.py
@@ -19,8 +19,8 @@
 
 import email.message as emailmessage
 import email.policy as policy
+import unittest.mock as mock
 from typing import TYPE_CHECKING
-from unittest.mock import AsyncMock
 
 import pytest
 
@@ -33,7 +33,7 @@ if TYPE_CHECKING:
 @pytest.mark.asyncio
 async def test_address_objects_used_for_from_to_headers(monkeypatch: 
"MonkeyPatch") -> None:
     """Test that Address objects are used for From/To headers."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     legitimate_message = mail.Message(
@@ -61,7 +61,7 @@ async def 
test_address_objects_used_for_from_to_headers(monkeypatch: "MonkeyPatc
 @pytest.mark.asyncio
 async def test_send_accepts_legitimate_message(monkeypatch: "MonkeyPatch") -> 
None:
     """Test that a legitimate message without CRLF is accepted."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a legitimate message without any CRLF injection attempts
@@ -94,7 +94,7 @@ async def test_send_accepts_legitimate_message(monkeypatch: 
"MonkeyPatch") -> No
 @pytest.mark.asyncio
 async def test_send_accepts_message_with_reply_to(monkeypatch: "MonkeyPatch") 
-> None:
     """Test that a legitimate message with in_reply_to is accepted."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a legitimate message with a valid in_reply_to
@@ -122,7 +122,7 @@ async def 
test_send_accepts_message_with_reply_to(monkeypatch: "MonkeyPatch") ->
 @pytest.mark.asyncio
 async def test_send_handles_non_ascii_headers(monkeypatch: "MonkeyPatch") -> 
None:
     """Test that non-ASCII characters in headers are handled correctly."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a message with non-ASCII characters in the subject
@@ -152,7 +152,7 @@ async def test_send_handles_non_ascii_headers(monkeypatch: 
"MonkeyPatch") -> Non
 @pytest.mark.asyncio
 async def test_send_rejects_bcc_header_injection(monkeypatch: "MonkeyPatch") 
-> None:
     """Test a realistic Bcc header injection attack scenario."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a malicious message attempting to inject a Bcc header
@@ -177,7 +177,7 @@ async def 
test_send_rejects_bcc_header_injection(monkeypatch: "MonkeyPatch") ->
 @pytest.mark.asyncio
 async def test_send_rejects_content_type_injection(monkeypatch: "MonkeyPatch") 
-> None:
     """Test injection attempting to override Content-Type header."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a malicious message attempting to inject Content-Type
@@ -202,7 +202,7 @@ async def 
test_send_rejects_content_type_injection(monkeypatch: "MonkeyPatch") -
 @pytest.mark.asyncio
 async def test_send_rejects_cr_only_injection(monkeypatch: "MonkeyPatch") -> 
None:
     """Test that injection with CR only (\\r) is also rejected."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a malicious message with just CR (no LF)
@@ -231,7 +231,7 @@ async def 
test_send_rejects_crlf_in_from_address(monkeypatch: "MonkeyPatch") ->
     Note: The from_addr validation happens before EmailMessage processing,
     so this test verifies the early validation layer also protects against 
injection.
     """
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a malicious message with CRLF in the from address
@@ -253,7 +253,7 @@ async def 
test_send_rejects_crlf_in_from_address(monkeypatch: "MonkeyPatch") ->
 @pytest.mark.asyncio
 async def test_send_rejects_crlf_in_reply_to(monkeypatch: "MonkeyPatch") -> 
None:
     """Test that CRLF injection in in_reply_to field is rejected."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a malicious message with CRLF in the in_reply_to field
@@ -280,7 +280,7 @@ async def test_send_rejects_crlf_in_reply_to(monkeypatch: 
"MonkeyPatch") -> None
 async def test_send_rejects_crlf_in_subject(monkeypatch: "MonkeyPatch") -> 
None:
     """Test that CRLF injection in subject field is rejected."""
     # Mock _send_many to ensure we never actually send emails
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a malicious message with CRLF in the subject
@@ -309,7 +309,7 @@ async def test_send_rejects_crlf_in_to_address(monkeypatch: 
"MonkeyPatch") -> No
     Note: The _validate_recipient check happens before EmailMessage processing,
     so this test verifies the early validation layer also protects against 
injection.
     """
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a malicious message with CRLF in the to address
@@ -331,7 +331,7 @@ async def test_send_rejects_crlf_in_to_address(monkeypatch: 
"MonkeyPatch") -> No
 @pytest.mark.asyncio
 async def test_send_rejects_lf_only_injection(monkeypatch: "MonkeyPatch") -> 
None:
     """Test that injection with LF only (\\n) is also rejected."""
-    mock_send_many = AsyncMock(return_value=[])
+    mock_send_many = mock.AsyncMock(return_value=[])
     monkeypatch.setattr("atr.mail._send_many", mock_send_many)
 
     # Create a malicious message with just LF (no CR)
diff --git a/tests/unit/test_merge.py b/tests/unit/test_merge.py
index 48c5d22e..46fd2a82 100644
--- a/tests/unit/test_merge.py
+++ b/tests/unit/test_merge.py
@@ -17,7 +17,7 @@
 
 import os
 import pathlib
-from unittest.mock import AsyncMock, patch
+import unittest.mock as mock
 
 import pytest
 
@@ -39,7 +39,7 @@ async def test_case_09_prior_adds_file(tmp_path: 
pathlib.Path):
 
     mock_prior_hashes = {"added.txt": "blake3:abc123"}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value=mock_prior_hashes):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value=mock_prior_hashes):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -74,7 +74,7 @@ async def 
test_case_09_prior_adds_file_in_subdirectory(tmp_path: pathlib.Path):
 
     mock_prior_hashes = {"apple/banana.txt": "blake3:xyz890"}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value=mock_prior_hashes):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value=mock_prior_hashes):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -108,7 +108,7 @@ async def test_case_10_prior_deletion_via_hash(tmp_path: 
pathlib.Path):
     n_hashes = {"removed.txt": "blake3:matching"}
     n_sizes = {"removed.txt": len("same content")}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value={}):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value={}):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -140,7 +140,7 @@ async def test_case_10_prior_deletion_via_inode(tmp_path: 
pathlib.Path):
     n_hashes = {"removed.txt": "blake3:aaa"}
     n_sizes = {"removed.txt": len("to be deleted")}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value={}):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value={}):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -181,7 +181,7 @@ async def test_case_11_prior_replacement_via_hash(tmp_path: 
pathlib.Path):
 
     mock_prior_hashes = {"shared.txt": "blake3:updated"}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value=mock_prior_hashes):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value=mock_prior_hashes):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -216,7 +216,7 @@ async def 
test_case_11_prior_replacement_via_inode(tmp_path: pathlib.Path):
 
     mock_prior_hashes = {"shared.txt": "blake3:updated"}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value=mock_prior_hashes):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value=mock_prior_hashes):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -248,7 +248,7 @@ async def 
test_case_13_new_wins_when_prior_deletes(tmp_path: pathlib.Path):
     n_hashes = {"modified.txt": "blake3:new"}
     n_sizes = {"modified.txt": len("new content")}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value={}):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value={}):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -282,7 +282,7 @@ async def test_noop_when_base_and_prior_agree(tmp_path: 
pathlib.Path):
     n_hashes = {"unchanged.txt": "blake3:modified"}
     n_sizes = {"unchanged.txt": len("modified by new")}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value={}) as mock_load:
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value={}) as mock_load:
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -315,7 +315,7 @@ async def 
test_type_conflict_prior_file_vs_new_directory(tmp_path: pathlib.Path)
     n_hashes = {"docs/guide.txt": "blake3:guide"}
     n_sizes = {"docs/guide.txt": len("a file under a directory in new")}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value={"docs": "blake3:docs"}):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value={"docs": "blake3:docs"}):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -348,7 +348,7 @@ async def 
test_type_conflict_prior_file_vs_new_empty_directory(tmp_path: pathlib
     n_hashes: dict[str, str] = {}
     n_sizes: dict[str, int] = {}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value={"empty": "blake3:empty"}):
+    with mock.patch("atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value={"empty": "blake3:empty"}):
         await merge.merge(
             base_inodes,
             base_hashes,
@@ -380,7 +380,9 @@ async def 
test_type_conflict_prior_subdir_vs_new_file(tmp_path: pathlib.Path):
     n_hashes = {"docs": "blake3:docs"}
     n_sizes = {"docs": len("a file in new")}
 
-    with patch("atr.attestable.load_paths", new_callable=AsyncMock, 
return_value={"docs/guide.txt": "blake3:guide"}):
+    with mock.patch(
+        "atr.attestable.load_paths", new_callable=mock.AsyncMock, 
return_value={"docs/guide.txt": "blake3:guide"}
+    ):
         await merge.merge(
             base_inodes,
             base_hashes,
diff --git a/tests/unit/test_message.py b/tests/unit/test_message.py
index b5e86281..1194061a 100644
--- a/tests/unit/test_message.py
+++ b/tests/unit/test_message.py
@@ -18,8 +18,8 @@
 """Tests for ASF ID validation in atr.tasks.message module."""
 
 import contextlib
+import unittest.mock as mock
 from typing import TYPE_CHECKING
-from unittest.mock import AsyncMock, MagicMock
 
 import pytest
 
@@ -29,52 +29,35 @@ if TYPE_CHECKING:
     from pytest import MonkeyPatch
 
 
-def _send_args(
-    email_sender: str = "[email protected]",
-    email_recipient: str = "[email protected]",
-    subject: str = "Test Subject",
-    body: str = "Test body",
-    in_reply_to: str | None = None,
-) -> dict[str, str | None]:
-    """Build an argument dict matching the Send schema."""
-    return {
-        "email_sender": email_sender,
-        "email_recipient": email_recipient,
-        "subject": subject,
-        "body": body,
-        "in_reply_to": in_reply_to,
-    }
-
-
 @pytest.mark.asyncio
-async def test_send_rejects_invalid_asf_id(monkeypatch: "MonkeyPatch") -> None:
-    """Test that an ASF UID not found in LDAP raises SendError."""
-    # ldap.account_lookup returns None for an unknown UID
-    monkeypatch.setattr("atr.tasks.message.ldap.account_lookup", 
AsyncMock(return_value=None))
+async def test_send_rejects_banned_asf_account(monkeypatch: "MonkeyPatch") -> 
None:
+    """Test that a banned ASF account raises SendError."""
+    monkeypatch.setattr(
+        "atr.tasks.message.ldap.account_lookup",
+        mock.AsyncMock(return_value={"uid": "banneduser", "cn": "Banned User", 
"asf-banned": "yes"}),
+    )
 
-    with pytest.raises(message.SendError, match=r"Invalid email account"):
-        await message.send(_send_args(email_sender="[email protected]"))
+    with pytest.raises(message.SendError, match=r"banned"):
+        await message.send(_send_args(email_sender="[email protected]"))
 
 
 @pytest.mark.asyncio
 async def test_send_rejects_bare_invalid_asf_id(monkeypatch: "MonkeyPatch") -> 
None:
     """Test that a bare ASF UID (no @) not found in LDAP raises SendError."""
-    monkeypatch.setattr("atr.tasks.message.ldap.account_lookup", 
AsyncMock(return_value=None))
+    monkeypatch.setattr("atr.tasks.message.ldap.account_lookup", 
mock.AsyncMock(return_value=None))
 
     with pytest.raises(message.SendError, match=r"Invalid email account"):
         await message.send(_send_args(email_sender="nosuchuser"))
 
 
 @pytest.mark.asyncio
-async def test_send_rejects_banned_asf_account(monkeypatch: "MonkeyPatch") -> 
None:
-    """Test that a banned ASF account raises SendError."""
-    monkeypatch.setattr(
-        "atr.tasks.message.ldap.account_lookup",
-        AsyncMock(return_value={"uid": "banneduser", "cn": "Banned User", 
"asf-banned": "yes"}),
-    )
+async def test_send_rejects_invalid_asf_id(monkeypatch: "MonkeyPatch") -> None:
+    """Test that an ASF UID not found in LDAP raises SendError."""
+    # ldap.account_lookup returns None for an unknown UID
+    monkeypatch.setattr("atr.tasks.message.ldap.account_lookup", 
mock.AsyncMock(return_value=None))
 
-    with pytest.raises(message.SendError, match=r"banned"):
-        await message.send(_send_args(email_sender="[email protected]"))
+    with pytest.raises(message.SendError, match=r"Invalid email account"):
+        await message.send(_send_args(email_sender="[email protected]"))
 
 
 @pytest.mark.asyncio
@@ -83,15 +66,15 @@ async def test_send_succeeds_with_valid_asf_id(monkeypatch: 
"MonkeyPatch") -> No
     # ldap.account_lookup returns a dict for a known UID
     monkeypatch.setattr(
         "atr.tasks.message.ldap.account_lookup",
-        AsyncMock(return_value={"uid": "validuser", "cn": "Valid User"}),
+        mock.AsyncMock(return_value={"uid": "validuser", "cn": "Valid User"}),
     )
 
     # Mock the storage.write async context manager chain:
     #   storage.write(uid) -> write -> write.as_foundation_committer() -> wafc 
-> wafc.mail.send() -> (mid, [])
-    mock_mail_send = AsyncMock(return_value=("[email protected]", []))
-    mock_wafc = MagicMock()
+    mock_mail_send = mock.AsyncMock(return_value=("[email protected]", []))
+    mock_wafc = mock.MagicMock()
     mock_wafc.mail.send = mock_mail_send
-    mock_write = MagicMock()
+    mock_write = mock.MagicMock()
     mock_write.as_foundation_committer.return_value = mock_wafc
 
     @contextlib.asynccontextmanager
@@ -109,3 +92,20 @@ async def test_send_succeeds_with_valid_asf_id(monkeypatch: 
"MonkeyPatch") -> No
 
     # Verify mail.send was called exactly once
     mock_mail_send.assert_called_once()
+
+
+def _send_args(
+    email_sender: str = "[email protected]",
+    email_recipient: str = "[email protected]",
+    subject: str = "Test Subject",
+    body: str = "Test body",
+    in_reply_to: str | None = None,
+) -> dict[str, str | None]:
+    """Build an argument dict matching the Send schema."""
+    return {
+        "email_sender": email_sender,
+        "email_recipient": email_recipient,
+        "subject": subject,
+        "body": body,
+        "in_reply_to": in_reply_to,
+    }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to