tests: switch to mock.patch.object Python style reviewers often point people to use mock.patch.object since it can be statically checked better. Migrate code, and update the SKILL file to cover this too. Change-Id: If7aa8e3ddcdb3d739187b12e3034de1de990a7df Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/656246 Reviewed-by: Brian Gan <brgan@google.com> Tested-by: Mike Frysinger <vapier@google.com> Commit-Queue: Mike Frysinger <vapier@google.com>
diff --git a/agents/skills/core_internals/SKILL.md b/agents/skills/core_internals/SKILL.md index a764ad3..2835ba4 100644 --- a/agents/skills/core_internals/SKILL.md +++ b/agents/skills/core_internals/SKILL.md
@@ -3471,6 +3471,12 @@ : : : : asserted directly : : : : : in the test : : : : : docstring. : +| **T5-29** | Object-Referenced Mocking via | High | Passing a dotted | +: : `mock.patch.object` : : string target to : +: : : : `mock.patch` : +: : : : instead of using : +: : : : `mock.patch.object` : +: : : : on the object. : -------------------------------------------------------------------------------- @@ -3903,13 +3909,13 @@ **Don't:** ```python -@mock.patch("main.time.sleep") +@mock.patch.object(main.time, "sleep") ``` **Do:** ```python -@mock.patch("time.sleep") +@mock.patch.object(time, "sleep") ``` -------------------------------------------------------------------------------- @@ -3939,7 +3945,7 @@ ```python class SshTests(unittest.TestCase): def test_version(self): - with mock.patch("ssh._run_ssh_version", return_value="OpenSSH_1.2\n"): + with mock.patch.object(ssh, "_run_ssh_version", return_value="OpenSSH_1.2\n"): self.assertEqual(ssh.version(), (1, 2)) ``` @@ -3951,7 +3957,7 @@ ssh.version.cache_clear() def test_version(self): - with mock.patch("ssh._run_ssh_version", return_value="OpenSSH_1.2\n"): + with mock.patch.object(ssh, "_run_ssh_version", return_value="OpenSSH_1.2\n"): self.assertEqual(ssh.version(), (1, 2)) ``` @@ -4015,15 +4021,15 @@ **Don't:** ```python -with mock.patch("sys.stderr") as mock_stderr: - with mock.patch("socket.socket") as ms: +with mock.patch.object(time, "sleep") as mock_sleep: + with mock.patch.object(socket, "socket") as ms: run_test() ``` **Do:** ```python -with mock.patch("sys.stderr") as mock_stderr, mock.patch("socket.socket") as ms: +with mock.patch.object(time, "sleep") as mock_sleep, mock.patch.object(socket, "socket") as ms: run_test() ``` @@ -4075,7 +4081,7 @@ **Do:** ```python -mock.patch("socket.socket", side_effect=OSError) +mock.patch.object(socket, "socket", side_effect=OSError) ``` **Exceptions:** Tests explicitly verifying exact formatting serialization (e.g., @@ -4613,6 +4619,43 @@ -------------------------------------------------------------------------------- +#### T5-29: Object-Referenced Mocking via `mock.patch.object` + +> **Rule:** Never use `mock.patch`; always use `mock.patch.object`. +> +> **What:** All attribute and function patching in unit tests must use +> `mock.patch.object(target, "attribute", ...)` against an explicitly imported +> module or class object rather than passing dotted string paths to +> `mock.patch("module.attribute", ...)`. +> +> **Applies To:** All unit tests utilizing `unittest.mock`. +> +> **Why:** String-based `mock.patch` paths bypass static analysis and module +> import validation, making tests brittle during refactoring and prone to silent +> resolution errors or import ordering bugs. Referencing the imported object +> directly via `mock.patch.object` ensures the target module is explicitly +> imported and validated at load time. Failing to adhere to this typically +> results in **Brittle Patch Routing / Unvalidated String Targets**. + +**Trap 1: Passing a dotted string target to `mock.patch` instead of using +`mock.patch.object` on the object.** + +**Don't:** + +```python +with mock.patch("ssh._run_ssh_version", return_value="OpenSSH_1.2\n"): + ... +``` + +**Do:** + +```python +with mock.patch.object(ssh, "_run_ssh_version", return_value="OpenSSH_1.2\n"): + ... +``` + +-------------------------------------------------------------------------------- + ### Cross-Domain Dependencies * **Upstream:** T2 | Filesystem Atomicity & Worktree Layout - *Managing safe
diff --git a/tests/test_color.py b/tests/test_color.py index 72d7499..57a9a13 100644 --- a/tests/test_color.py +++ b/tests/test_color.py
@@ -14,6 +14,7 @@ """Unittests for the color.py module.""" +import os from unittest import mock import pytest @@ -21,6 +22,7 @@ import color import git_config +import pager @pytest.fixture @@ -147,8 +149,8 @@ pager_active: bool, expected: bool, ) -> None: - with mock.patch("os.isatty", return_value=isatty), mock.patch( - "pager.active", pager_active - ): + with mock.patch.object( + os, "isatty", return_value=isatty + ), mock.patch.object(pager, "active", pager_active): c = _make_coloring(state) assert c.is_on is expected
diff --git a/tests/test_git_command.py b/tests/test_git_command.py index dccc831..903322f 100644 --- a/tests/test_git_command.py +++ b/tests/test_git_command.py
@@ -18,6 +18,7 @@ import os import re import subprocess +import sys import unittest from unittest import mock @@ -76,7 +77,7 @@ self.mock_popen = mock.MagicMock() self.mock_popen.return_value = self.mock_process - mock.patch("subprocess.Popen", self.mock_popen).start() + mock.patch.object(subprocess, "Popen", self.mock_popen).start() def tearDown(self): mock.patch.stopall() @@ -145,7 +146,7 @@ self.mock_process.communicate.assert_called_once_with(input=None) self.mock_process.stderr.read1.assert_not_called() - @mock.patch("sys.stderr") + @mock.patch.object(sys, "stderr") def test_streams_stderr_when_no_stream_is_set(self, mock_stderr): mock_stderr.isatty.return_value = False logs = "\n".join( @@ -175,7 +176,7 @@ mock_stderr.write.assert_called_once_with(logs) self.assertEqual(cmd.stderr, logs) - @mock.patch("sys.stderr") + @mock.patch.object(sys, "stderr") def test_push_injects_progress_only_when_tty_and_not_suppressed( self, mock_stderr: mock.MagicMock ) -> None: @@ -186,7 +187,7 @@ cmd = self.mock_popen.call_args[0][0] self.assertEqual(cmd, ["git", "push", "--progress"]) - @mock.patch("sys.stderr") + @mock.patch.object(sys, "stderr") def test_push_does_not_inject_progress_when_no_progress_set( self, mock_stderr: mock.MagicMock ) -> None: @@ -209,7 +210,7 @@ self.mock_popen = mock.MagicMock() self.mock_popen.return_value = self.mock_process - mock.patch("subprocess.Popen", self.mock_popen).start() + mock.patch.object(subprocess, "Popen", self.mock_popen).start() def tearDown(self) -> None: mock.patch.stopall()
diff --git a/tests/test_git_superproject.py b/tests/test_git_superproject.py index e7f208d..ba68a91 100644 --- a/tests/test_git_superproject.py +++ b/tests/test_git_superproject.py
@@ -24,6 +24,7 @@ import pytest import test_manifest_xml +import git_command import git_superproject import git_trace2_event_log import manifest_xml @@ -464,8 +465,8 @@ def test_Init_success(self): """Test _Init succeeds and creates the work git dir.""" self.assertFalse(os.path.exists(self._superproject._work_git)) - with mock.patch( - "git_command.GitCommand", autospec=True + with mock.patch.object( + git_command, "GitCommand", autospec=True ) as mock_git_command: instance = mock_git_command.return_value instance.Wait.return_value = 0 @@ -491,16 +492,16 @@ """Test _Init returns early if the work git dir already exists.""" os.mkdir(self._superproject._superproject_path) os.mkdir(self._superproject._work_git) - with mock.patch( - "git_command.GitCommand", autospec=True + with mock.patch.object( + git_command, "GitCommand", autospec=True ) as mock_git_command: self.assertTrue(self._superproject._Init()) mock_git_command.assert_not_called() def test_Init_failure_cleans_up(self): """Test _Init cleans up the temporary directory if 'git init' fails.""" - with mock.patch( - "git_command.GitCommand", autospec=True + with mock.patch.object( + git_command, "GitCommand", autospec=True ) as mock_git_command: instance = mock_git_command.return_value instance.Wait.return_value = 1 @@ -539,8 +540,8 @@ os.mkdir(self._superproject._superproject_path) os.mkdir(self._superproject._work_git) with mock.patch.object(self._superproject, "_Init", return_value=True): - with mock.patch( - "git_command.GitCommand", autospec=True + with mock.patch.object( + git_command, "GitCommand", autospec=True ) as mock_git_command: with mock.patch.object( self._superproject, "_GetRef" @@ -599,12 +600,12 @@ def test_GetRef_resolves_only_the_requested_ref(self) -> None: command = mock.MagicMock(stdout="1234\n") command.Wait.return_value = 0 - with mock.patch( - "git_command.GitCommand", return_value=command - ) as git_command: + with mock.patch.object( + git_command, "GitCommand", return_value=command + ) as mock_git_command: self.assertEqual("1234", self._superproject._GetRef("HEAD")) - git_command.assert_called_once_with( + mock_git_command.assert_called_once_with( None, ["rev-parse", "--verify", "--quiet", "HEAD"], gitdir=self._superproject._work_git,
diff --git a/tests/test_git_trace2_event_log.py b/tests/test_git_trace2_event_log.py index 195dbaf..7b8b155 100644 --- a/tests/test_git_trace2_event_log.py +++ b/tests/test_git_trace2_event_log.py
@@ -437,7 +437,9 @@ event_log.verbose = False with contextlib.redirect_stderr( io.StringIO() - ) as mock_stderr, mock.patch("socket.socket", side_effect=OSError): + ) as mock_stderr, mock.patch.object( + socket, "socket", side_effect=OSError + ): event_log.Write(path="af_unix:stream:/tmp/test_sock") assert mock_stderr.getvalue() == "" @@ -447,8 +449,8 @@ event_log.verbose = True with contextlib.redirect_stderr( io.StringIO() - ) as mock_stderr, mock.patch( - "socket.socket", side_effect=OSError("Mock error") + ) as mock_stderr, mock.patch.object( + socket, "socket", side_effect=OSError("Mock error") ): event_log.Write(path="af_unix:stream:/tmp/test_sock") assert ( @@ -462,8 +464,8 @@ event_log.verbose = False with contextlib.redirect_stderr( io.StringIO() - ) as mock_stderr, mock.patch( - "tempfile.NamedTemporaryFile", side_effect=FileExistsError + ) as mock_stderr, mock.patch.object( + tempfile, "NamedTemporaryFile", side_effect=FileExistsError ): event_log.Write(path="/tmp") assert mock_stderr.getvalue() == "" @@ -474,8 +476,9 @@ event_log.verbose = True with contextlib.redirect_stderr( io.StringIO() - ) as mock_stderr, mock.patch( - "tempfile.NamedTemporaryFile", + ) as mock_stderr, mock.patch.object( + tempfile, + "NamedTemporaryFile", side_effect=FileExistsError("Mock error"), ): event_log.Write(path="/tmp")
diff --git a/tests/test_main.py b/tests/test_main.py index 74c6d9a..2545caa 100644 --- a/tests/test_main.py +++ b/tests/test_main.py
@@ -14,13 +14,16 @@ """Tests for the main repo script and subcommand routing.""" +import builtins from pathlib import Path +import time from unittest import mock import pytest import event_log import main +import manifest_xml @pytest.fixture(name="repo") @@ -38,7 +41,7 @@ return mock.MagicMock() -@mock.patch("time.sleep") +@mock.patch.object(time, "sleep") def test_autocorrect_delay(mock_sleep, repo, mock_config): """Test autocorrect with positive delay.""" mock_config.GetString.return_value = "10" @@ -50,7 +53,7 @@ assert res == "start" -@mock.patch("time.sleep") +@mock.patch.object(time, "sleep") def test_autocorrect_delay_one(mock_sleep, repo, mock_config): """Test autocorrect with '1' (0.1s delay, not immediate).""" mock_config.GetString.return_value = "1" @@ -61,7 +64,7 @@ assert res == "start" -@mock.patch("time.sleep", side_effect=KeyboardInterrupt()) +@mock.patch.object(time, "sleep", side_effect=KeyboardInterrupt()) def test_autocorrect_delay_interrupt(mock_sleep, repo, mock_config): """Test autocorrect handles KeyboardInterrupt during delay.""" mock_config.GetString.return_value = "10" @@ -72,7 +75,7 @@ assert res is None -@mock.patch("time.sleep") +@mock.patch.object(time, "sleep") def test_autocorrect_immediate(mock_sleep, repo, mock_config): """Test autocorrect with immediate/negative delay.""" # Test numeric negative. @@ -125,7 +128,7 @@ assert res is None -@mock.patch("builtins.input", return_value="y") +@mock.patch.object(builtins, "input", return_value="y") def test_autocorrect_prompt_yes(mock_input, repo, mock_config): """Test autocorrect with prompt and user answers yes.""" mock_config.GetString.return_value = "prompt" @@ -135,7 +138,7 @@ assert res == "start" -@mock.patch("builtins.input", return_value="n") +@mock.patch.object(builtins, "input", return_value="n") def test_autocorrect_prompt_no(mock_input, repo, mock_config): """Test autocorrect with prompt and user answers no.""" mock_config.GetString.return_value = "prompt" @@ -145,7 +148,7 @@ assert res is None -@mock.patch("builtins.input", return_value="y") +@mock.patch.object(builtins, "input", return_value="y") def test_autocorrect_multiple_candidates(mock_input, repo, mock_config): """Test autocorrect with multiple matches forces a prompt.""" mock_config.GetString.return_value = "10" # Normally just delay @@ -158,7 +161,7 @@ assert res == "start" -@mock.patch("builtins.input", side_effect=KeyboardInterrupt()) +@mock.patch.object(builtins, "input", side_effect=KeyboardInterrupt()) def test_autocorrect_prompt_interrupt(mock_input, repo, mock_config): """Test autocorrect with prompt and user interrupts.""" mock_config.GetString.return_value = "prompt" @@ -181,7 +184,7 @@ project.GetCommitRevisionId.assert_not_called() -@mock.patch("manifest_xml.RepoClient") +@mock.patch.object(manifest_xml, "RepoClient") def test_run_long_gates_event_log_on_flag( mock_client_cls: mock.MagicMock, tmp_path: Path ) -> None:
diff --git a/tests/test_project.py b/tests/test_project.py index 9b952e4..89fa1a5 100644 --- a/tests/test_project.py +++ b/tests/test_project.py
@@ -37,6 +37,7 @@ import manifest_xml import platform_utils import project +import repo_trace class FakeProject: @@ -274,8 +275,10 @@ """Check UploadForReview emits repo.uploadstate trace2 data events.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( - "project.ReviewableBranch" + with mock.patch.object( + git_command, "GitCommand" + ) as mock_git_cmd, mock.patch.object( + project, "ReviewableBranch" ) as mock_rb_cls: mock_cmd = mock.MagicMock() mock_cmd.Wait.return_value = 0 @@ -314,8 +317,10 @@ """Check event emission when stderr contains no review URLs.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( - "project.ReviewableBranch" + with mock.patch.object( + git_command, "GitCommand" + ) as mock_git_cmd, mock.patch.object( + project, "ReviewableBranch" ) as mock_rb_cls: mock_cmd = mock.MagicMock() mock_cmd.Wait.return_value = 0 @@ -348,8 +353,10 @@ """Check UploadForReview succeeds when git_event_log is None.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( - "project.ReviewableBranch" + with mock.patch.object( + git_command, "GitCommand" + ) as mock_git_cmd, mock.patch.object( + project, "ReviewableBranch" ) as mock_rb_cls: mock_cmd = mock.MagicMock() mock_cmd.Wait.return_value = 0 @@ -371,9 +378,13 @@ """Check exceptions during tracing are caught and do not fail upload.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( - "project.ReviewableBranch" - ) as mock_rb_cls, mock.patch("project.logger") as mock_logger: + with mock.patch.object( + git_command, "GitCommand" + ) as mock_git_cmd, mock.patch.object( + project, "ReviewableBranch" + ) as mock_rb_cls, mock.patch.object( + project, "logger" + ) as mock_logger: mock_cmd = mock.MagicMock() mock_cmd.Wait.return_value = 0 mock_cmd.stderr = "remote: https://example.com/c/test/+/1\n" @@ -396,8 +407,10 @@ """Check integration with real git_trace2_event_log.EventLog.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( - "project.ReviewableBranch" + with mock.patch.object( + git_command, "GitCommand" + ) as mock_git_cmd, mock.patch.object( + project, "ReviewableBranch" ) as mock_rb_cls: mock_cmd = mock.MagicMock() mock_cmd.Wait.return_value = 0 @@ -439,9 +452,11 @@ for quiet in (False, True): with self.subTest(quiet=quiet): proj, _ = self._create_project_for_upload_test() - with mock.patch( - "git_command.GitCommand" - ) as mock_git_cmd, mock.patch("project.ReviewableBranch"): + with mock.patch.object( + git_command, "GitCommand" + ) as mock_git_cmd, mock.patch.object( + project, "ReviewableBranch" + ): mock_cmd = mock.MagicMock() mock_cmd.Wait.return_value = 0 mock_cmd.stderr = "" @@ -1195,7 +1210,7 @@ with open(head_file, "w", encoding="utf-8", newline="") as fp: fp.write("ref:\t refs/heads/fallback-branch\r\n") - with mock.patch("platform_utils.islink", return_value=True): + with mock.patch.object(platform_utils, "islink", return_value=True): with mock.patch.object( fakeproj.work_git, "symbolic_ref", @@ -1215,7 +1230,7 @@ with open(head_file, "w", encoding="utf-8", newline="") as fp: fp.write(f"{sha_upper}\r\n") - with mock.patch("platform_utils.islink", return_value=True): + with mock.patch.object(platform_utils, "islink", return_value=True): with mock.patch.object( fakeproj.work_git, "symbolic_ref", @@ -1233,7 +1248,7 @@ with open(head_file, "w", encoding="utf-8", newline="") as fp: fp.write("ref: refs/heads/.invalid\r\n") - with mock.patch("platform_utils.islink", return_value=True): + with mock.patch.object(platform_utils, "islink", return_value=True): with mock.patch.object( fakeproj.work_git, "symbolic_ref", @@ -1476,7 +1491,7 @@ hex41 = "a" * 41 proj.SetRevision(hex41) - with mock.patch("git_command.GitCommand") as mock_git: + with mock.patch.object(git_command, "GitCommand") as mock_git: mock_cmd = mock.MagicMock() mock_cmd.Wait.return_value = 0 mock_git.return_value = mock_cmd @@ -2490,7 +2505,7 @@ proj.work_git = mock.MagicMock() syncbuf = project.SyncBuffer(proj.config) - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -2839,7 +2854,7 @@ if os.path.exists(shallow_path): os.unlink(shallow_path) - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -2862,7 +2877,7 @@ with open(os.path.join(proj.gitdir, "shallow"), "w") as f: f.write("") - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: res = proj._RemoteFetch( current_branch_only=True, depth=1, @@ -2885,7 +2900,7 @@ with open(os.path.join(other.gitdir, "shallow"), "w") as f: f.write("") - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -2914,7 +2929,7 @@ with open(os.path.join(other.gitdir, "shallow"), "w") as f: f.write("") - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: res = proj._RemoteFetch( current_branch_only=True, depth=1, @@ -3108,7 +3123,7 @@ mock_remote.PreConnectFetch.return_value = True proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -3147,7 +3162,7 @@ mock_remote.PreConnectFetch.return_value = True proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -3189,7 +3204,7 @@ mock_remote.PreConnectFetch.return_value = True proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -3237,7 +3252,7 @@ mock_remote.PreConnectFetch.return_value = True proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -3338,8 +3353,8 @@ inst.stdout = "" return inst - with mock.patch( - "git_command.GitCommand", side_effect=_fake_git_command + with mock.patch.object( + git_command, "GitCommand", side_effect=_fake_git_command ): res = proj._RemoteFetch(current_branch_only=True) @@ -3490,7 +3505,7 @@ mock_remote.ToLocal.return_value = "refs/remotes/origin/main" proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") res = proj._CustomFetch() @@ -3523,7 +3538,7 @@ mock_remote.ToLocal.return_value = "refs/remotes/origin/main" proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") res = proj._CustomFetch() @@ -3543,7 +3558,7 @@ proj.bare_git.ResolveRef.return_value = sha proj.GetRemote = mock.MagicMock() - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") res = proj._CustomFetch() @@ -3571,7 +3586,7 @@ mock_remote.ToLocal.return_value = "refs/remotes/origin/main" proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") self.assertFalse(proj._CustomFetch()) @@ -3588,7 +3603,7 @@ mock_remote.ToLocal.return_value = "refs/remotes/origin/main" proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") self.assertFalse(proj._CustomFetch()) @@ -3603,7 +3618,7 @@ mock_remote.ToLocal.return_value = "refs/remotes/origin/main" proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") self.assertFalse(proj._CustomFetch()) @@ -3618,7 +3633,7 @@ proj.revisionExpr = sha proj.bare_git.ResolveRef.side_effect = error.GitError("missing") - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") self.assertFalse(proj._CustomFetch()) @@ -3639,7 +3654,7 @@ mock_remote.ToLocal.return_value = "refs/tags/v1.0" proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") self.assertTrue(proj._CustomFetch()) @@ -3667,7 +3682,7 @@ mock_remote.ToLocal.return_value = "refs/tags/v1.0" proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") self.assertFalse(proj._CustomFetch()) @@ -3707,7 +3722,7 @@ ) return mock.MagicMock(returncode=0, stderr="") - with mock.patch("subprocess.run", side_effect=_edit_config): + with mock.patch.object(subprocess, "run", side_effect=_edit_config): self.assertTrue(proj._CustomFetch()) self.assertTrue(proj.config.GetBoolean("custom.initialized")) @@ -3730,7 +3745,9 @@ fp.write("[custom]\n\tfailedrun = true\n") return mock.MagicMock(returncode=2, stderr="boom") - with mock.patch("subprocess.run", side_effect=_fail_after_edit): + with mock.patch.object( + subprocess, "run", side_effect=_fail_after_edit + ): self.assertFalse(proj._CustomFetch()) self.assertTrue(proj.config.GetBoolean("custom.failedrun")) @@ -3790,9 +3807,9 @@ mock_remote.ToLocal.return_value = "refs/remotes/origin/main" proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("repo_trace.Trace") as mock_trace, mock.patch( - "subprocess.run" - ) as mock_run: + with mock.patch.object( + repo_trace, "Trace" + ) as mock_trace, mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") self.assertTrue(proj._CustomFetch()) @@ -3805,9 +3822,9 @@ ) proj.revisionId = sha - with mock.patch("repo_trace.Trace") as mock_trace, mock.patch( - "subprocess.run" - ) as mock_run: + with mock.patch.object( + repo_trace, "Trace" + ) as mock_trace, mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stderr="") self.assertTrue(proj._CustomFetch()) @@ -3819,9 +3836,9 @@ sha, ) - with mock.patch( - "repo_trace.Trace", side_effect=OSError("trace disk full") - ), mock.patch("subprocess.run") as mock_run: + with mock.patch.object( + repo_trace, "Trace", side_effect=OSError("trace disk full") + ), mock.patch.object(subprocess, "run") as mock_run: with self.assertRaises(OSError): proj._CustomFetch() mock_run.assert_not_called() @@ -4039,9 +4056,9 @@ self, proj: project.Project, **outputs: Any ) -> mock.MagicMock: """Run _Reproject against mocked Git; return the subprocess mock.""" - with mock.patch( - "git_command.GitCommand", side_effect=self._git_command(**outputs) - ), mock.patch("subprocess.run") as mock_run: + with mock.patch.object( + git_command, "GitCommand", side_effect=self._git_command(**outputs) + ), mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") proj._Reproject(self.REVID) return mock_run @@ -4050,9 +4067,9 @@ """Test the command runs from the client root with REPO_TREV set.""" with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) - with mock.patch( - "git_command.GitCommand", side_effect=self._git_command() - ), mock.patch("subprocess.run") as mock_run: + with mock.patch.object( + git_command, "GitCommand", side_effect=self._git_command() + ), mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") proj._Reproject(self.REVID) @@ -4110,7 +4127,7 @@ with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) proj.IsRebaseInProgress.return_value = True - with mock.patch("subprocess.run") as mock_run: + with mock.patch.object(subprocess, "run") as mock_run: with self.assertRaises(project.LocalSyncFail) as e: proj._Reproject(self.REVID) self.assertIn("rebase in progress", str(e.exception)) @@ -4120,9 +4137,9 @@ """Test a non-zero exit fails the sync with the command's output.""" with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) - with mock.patch( - "git_command.GitCommand", side_effect=self._git_command() - ), mock.patch("subprocess.run") as mock_run: + with mock.patch.object( + git_command, "GitCommand", side_effect=self._git_command() + ), mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock( returncode=3, stdout="disk on fire\n" ) @@ -4136,9 +4153,9 @@ with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) proj.work_git.GetHead.side_effect = [self.HEAD_ID, self.REVID] - with mock.patch( - "git_command.GitCommand", side_effect=self._git_command() - ), mock.patch("subprocess.run") as mock_run: + with mock.patch.object( + git_command, "GitCommand", side_effect=self._git_command() + ), mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") with self.assertRaises(project.LocalSyncFail) as e: proj._Reproject(self.REVID) @@ -4154,9 +4171,9 @@ self.HEAD_ID, # HEAD before command self.REVID, # HEAD after command ] - with mock.patch( - "git_command.GitCommand", side_effect=self._git_command() - ), mock.patch("subprocess.run") as mock_run: + with mock.patch.object( + git_command, "GitCommand", side_effect=self._git_command() + ), mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") with self.assertRaises(project.LocalSyncFail) as e: proj._Reproject(self.REVID) @@ -4166,10 +4183,11 @@ """Test _Reproject does not diff the index against REPO_TREV^{tree}.""" with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) - with mock.patch( - "git_command.GitCommand", + with mock.patch.object( + git_command, + "GitCommand", side_effect=self._git_command(), - ) as mock_git_cmd, mock.patch("subprocess.run") as mock_run: + ) as mock_git_cmd, mock.patch.object(subprocess, "run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") proj._Reproject(self.REVID) @@ -4517,7 +4535,7 @@ """Test _Reproject traces execution and propagates trace OSError.""" with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) - with mock.patch("repo_trace.Trace") as mock_trace: + with mock.patch.object(repo_trace, "Trace") as mock_trace: self._reproject(proj) mock_trace.assert_called_once_with( @@ -4528,12 +4546,12 @@ self.REVID, ) - with mock.patch( - "git_command.GitCommand", side_effect=self._git_command() - ), mock.patch( - "repo_trace.Trace", side_effect=OSError("trace disk full") - ), mock.patch( - "subprocess.run" + with mock.patch.object( + git_command, "GitCommand", side_effect=self._git_command() + ), mock.patch.object( + repo_trace, "Trace", side_effect=OSError("trace disk full") + ), mock.patch.object( + subprocess, "run" ) as mock_run: with self.assertRaises(OSError): proj._Reproject(self.REVID) @@ -4553,9 +4571,11 @@ fp.write("[custom]\n\treprojected = true\n") return mock.MagicMock(returncode=1, stdout="failed\n") - with mock.patch( - "git_command.GitCommand", side_effect=self._git_command() - ), mock.patch("subprocess.run", side_effect=_fail_after_edit): + with mock.patch.object( + git_command, "GitCommand", side_effect=self._git_command() + ), mock.patch.object( + subprocess, "run", side_effect=_fail_after_edit + ): with self.assertRaises(project.LocalSyncFail): proj._Reproject(self.REVID) @@ -5034,10 +5054,10 @@ def test_download_patch_set_with_no_filter_and_no_tags(self) -> None: """Test DownloadPatchSet includes --no-filter and --no-tags.""" - with mock.patch( - "git_command.git_require", return_value=True + with mock.patch.object( + git_command, "git_require", return_value=True ) as mock_git_require: - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -5063,8 +5083,8 @@ def test_download_patch_set_legacy_git_omits_no_filter(self) -> None: """Test DownloadPatchSet omits --no-filter on git < 2.17.""" - with mock.patch("git_command.git_require", return_value=False): - with mock.patch("git_command.GitCommand") as mock_git_cmd: + with mock.patch.object(git_command, "git_require", return_value=False): + with mock.patch.object(git_command, "GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance
diff --git a/tests/test_ssh.py b/tests/test_ssh.py index 6bb2c2f..26bd985 100644 --- a/tests/test_ssh.py +++ b/tests/test_ssh.py
@@ -53,7 +53,9 @@ def test_version() -> None: """Check version() handling.""" - with mock.patch("ssh._run_ssh_version", return_value="OpenSSH_1.2\n"): + with mock.patch.object( + ssh, "_run_ssh_version", return_value="OpenSSH_1.2\n" + ): assert ssh.version() == (1, 2) @@ -67,7 +69,7 @@ def test_context_manager_child_cleanup() -> None: """Verify orphaned clients & masters get cleaned up.""" with multiprocessing.Manager() as manager: - with mock.patch("ssh.version", return_value=(1, 2)): + with mock.patch.object(ssh, "version", return_value=(1, 2)): with ssh.ProxyManager(manager) as ssh_proxy: client = subprocess.Popen(["sleep", "964853320"]) ssh_proxy.add_client(client) @@ -87,13 +89,13 @@ ) # Old ssh version uses port. - with mock.patch("ssh.version", return_value=(6, 6)): + with mock.patch.object(ssh, "version", return_value=(6, 6)): with proxy as ssh_proxy: assert ssh_proxy.sock().endswith("%p") proxy._sock_path = None # New ssh version uses hash. - with mock.patch("ssh.version", return_value=(6, 7)): + with mock.patch.object(ssh, "version", return_value=(6, 7)): with proxy as ssh_proxy: assert ssh_proxy.sock().endswith("%C") proxy._sock_path = None
diff --git a/tests/test_subcmds_sync.py b/tests/test_subcmds_sync.py index 7483f37..01310e7 100644 --- a/tests/test_subcmds_sync.py +++ b/tests/test_subcmds_sync.py
@@ -13,6 +13,7 @@ # limitations under the License. """Unittests for the subcmds/sync.py module.""" +import builtins import contextlib import json import optparse @@ -35,6 +36,7 @@ import error import git_command import git_config +import git_superproject import manifest_xml import progress from project import SyncNetworkHalfResult @@ -101,8 +103,8 @@ cmd = sync.Sync() opts, _ = cmd.OptionParser.parse_args(cli_args) - with mock.patch( - "git_superproject.UseSuperproject", return_value=use_superproject + with mock.patch.object( + git_superproject, "UseSuperproject", return_value=use_superproject ): assert cmd._GetCurrentBranchOnly(opts, cmd.manifest) == result @@ -726,8 +728,8 @@ """Common teardown.""" shutil.rmtree(self.topdir) - def _new_state(self, time=_TIME): - with mock.patch("time.time", return_value=time): + def _new_state(self, now: int = _TIME) -> sync.LocalSyncState: + with mock.patch.object(time, "time", return_value=now): return sync.LocalSyncState(self.manifest) def test_set(self): @@ -885,7 +887,7 @@ self.state = self._new_state() self.assertEqual(self.state.GetFetchTime(projA), 5) self.assertEqual(self.state.GetFetchTime(projB), 7) - with mock.patch("os.path.exists", side_effect=mock_exists): + with mock.patch.object(os.path, "exists", side_effect=mock_exists): self.state.PruneRemovedProjects() self.assertIsNone(self.state.GetFetchTime(projA)) @@ -917,7 +919,7 @@ outer_client=self.manifest, ) - with mock.patch("time.time", return_value=self._TIME): + with mock.patch.object(time, "time", return_value=self._TIME): state = sync.LocalSyncState(child_manifest) state.SetFetchTime(project) @@ -954,8 +956,8 @@ self.state = self._new_state() self.assertEqual(self.state.GetFetchTime(projA), 5) self.assertEqual(self.state.GetFetchTime(projB), 7) - with mock.patch("os.path.exists", side_effect=mock_exists): - with mock.patch("os.path.islink", side_effect=mock_islink): + with mock.patch.object(os.path, "exists", side_effect=mock_exists): + with mock.patch.object(os.path, "islink", side_effect=mock_islink): self.state.PruneRemovedProjects() self.assertIsNone(self.state.GetFetchTime(projB)) @@ -1394,7 +1396,7 @@ "ssh_proxy": None, } - @mock.patch("subcmds.sync.Sync.is_multiprocessing_active") + @mock.patch.object(sync.Sync, "is_multiprocessing_active") def test_fetch_one_keyboard_interrupt_main_process(self, mock_is_active): """Test that _FetchOne re-raises KeyboardInterrupt if not worker.""" mock_is_active.return_value = False @@ -1408,7 +1410,7 @@ with self.assertRaises(KeyboardInterrupt): sync.Sync._FetchOne(self.opt, 0) - @mock.patch("subcmds.sync.Sync.is_multiprocessing_active") + @mock.patch.object(sync.Sync, "is_multiprocessing_active") def test_fetch_one_keyboard_interrupt_worker_process(self, mock_is_active): """Test that _FetchOne suppresses KeyboardInterrupt in workers.""" mock_is_active.return_value = True @@ -1641,7 +1643,7 @@ """Test parallel GC (jobs >= 2).""" self.opt.jobs = 2 with mock.patch.object(sync.Sync, "_SetPreciousObjectsState"): - with mock.patch("subcmds.sync._threading.Thread") as mock_thread: + with mock.patch.object(threading, "Thread") as mock_thread: mock_t = mock.MagicMock() mock_thread.return_value = mock_t err_event = mock.Mock() @@ -2271,8 +2273,8 @@ mock.patch.object(sync, "_PostRepoFetch").start() # Mock parallel context for worker tests. - self.parallel_context_patcher = mock.patch( - "subcmds.sync.Sync.get_parallel_context" + self.parallel_context_patcher = mock.patch.object( + sync.Sync, "get_parallel_context" ) self.mock_get_parallel_context = self.parallel_context_patcher.start() self.sync_dict = {} @@ -2470,8 +2472,8 @@ self.cmd, "GetProjects", return_value=reloaded_projects ), mock.patch.object(self.cmd, "event_log"), mock.patch.object( self.cmd, "ExecuteInParallel", side_effect=execute_side_effect - ), mock.patch( - "subcmds.sync.SyncBuffer" + ), mock.patch.object( + sync, "SyncBuffer" ) as mock_sync_buffer: mock_sync_buffer.return_value.Finish.return_value = True mock_sync_buffer.return_value.errors = [] @@ -2712,7 +2714,7 @@ project.manifest.manifestProject.config = mock.MagicMock() self.mock_context["projects"] = [project] - with mock.patch("subcmds.sync.SyncBuffer") as mock_sync_buffer: + with mock.patch.object(sync, "SyncBuffer") as mock_sync_buffer: mock_sync_buf_instance = mock.MagicMock() mock_sync_buf_instance.Finish.return_value = True mock_sync_buf_instance.errors = [] @@ -2739,7 +2741,7 @@ with self.subTest(this_manifest_only=this_manifest_only): opt = self._get_opts() opt.this_manifest_only = this_manifest_only - with mock.patch("subcmds.sync.SyncBuffer") as mock_sync_buffer: + with mock.patch.object(sync, "SyncBuffer") as mock_sync_buffer: mock_sync_buffer.return_value.Finish.return_value = True mock_sync_buffer.return_value.errors = [] result_obj = self.cmd._SyncProjectList(opt, [0]) @@ -2818,7 +2820,7 @@ project.manifest.manifestProject.config = mock.MagicMock() self.mock_context["projects"] = [project] - with mock.patch("subcmds.sync.SyncBuffer"): + with mock.patch.object(sync, "SyncBuffer"): result_obj = self.cmd._SyncProjectList(opt, [0]) result = result_obj.results[0] @@ -2838,7 +2840,7 @@ project.manifest.manifestProject.config = mock.MagicMock() self.mock_context["projects"] = [project] - with mock.patch("subcmds.sync.SyncBuffer") as mock_sync_buffer: + with mock.patch.object(sync, "SyncBuffer") as mock_sync_buffer: mock_sync_buf_instance = mock.MagicMock() mock_sync_buf_instance.Finish.return_value = True mock_sync_buf_instance.errors = [] @@ -3422,10 +3424,10 @@ self.manifest.manifestProject.GetMergeBranch.return_value = "main" self.smart_sync_manifest_path = "/fake/path/to/manifest.xml" - @mock.patch("shutil.which") - @mock.patch("subprocess.Popen") - @mock.patch("xmlrpc.client.Server") - @mock.patch("subcmds.sync.PersistentTransport") + @mock.patch.object(shutil, "which") + @mock.patch.object(subprocess, "Popen") + @mock.patch.object(xmlrpc.client, "Server") + @mock.patch.object(sync, "PersistentTransport") def test_smart_sync_setup_with_helper( self, mock_transport_class, mock_server_class, mock_popen, mock_which ): @@ -3457,7 +3459,7 @@ self.cmd._ReloadManifest = mock.MagicMock() # Mock open to avoid writing to disk - with mock.patch("builtins.open", mock.mock_open()): + with mock.patch.object(builtins, "open", mock.mock_open()): manifest_name = self.cmd._SmartSyncSetup( self.opt, self.smart_sync_manifest_path, self.manifest ) @@ -3486,7 +3488,7 @@ self.assertEqual(manifest_name, "manifest.xml") - @mock.patch("xmlrpc.client.Server") + @mock.patch.object(xmlrpc.client, "Server") def test_smart_sync_setup_unparsable_manifest( self, mock_server_class: mock.MagicMock ) -> None: @@ -3511,14 +3513,14 @@ side_effect=error.ManifestParseError("mismatched tag") ) - with mock.patch("builtins.open", mock.mock_open()): + with mock.patch.object(builtins, "open", mock.mock_open()): with self.assertRaises(error.ManifestParseError): self.cmd._SmartSyncSetup( self.opt, self.smart_sync_manifest_path, self.manifest ) - @mock.patch("shutil.which") - @mock.patch("subprocess.Popen") + @mock.patch.object(shutil, "which") + @mock.patch.object(subprocess, "Popen") def test_smart_sync_setup_helper_error(self, mock_popen, mock_which): """Test _SmartSyncSetup when helper returns an error status.""" self.manifest.manifest_server = ( @@ -3546,7 +3548,7 @@ str(context.exception), ) - @mock.patch("shutil.which") + @mock.patch.object(shutil, "which") def test_smart_sync_setup_missing_declared_helper(self, mock_which): """Test _SmartSyncSetup when helper declared in manifest is missing.""" self.manifest.manifest_server = ( @@ -3566,8 +3568,8 @@ str(context.exception), ) - @mock.patch("shutil.which") - @mock.patch("subprocess.Popen") + @mock.patch.object(shutil, "which") + @mock.patch.object(subprocess, "Popen") def test_smart_sync_setup_helper_exit_code_error( self, mock_popen, mock_which ): @@ -3598,8 +3600,8 @@ str(context.exception), ) - @mock.patch("shutil.which") - @mock.patch("subprocess.Popen") + @mock.patch.object(shutil, "which") + @mock.patch.object(subprocess, "Popen") def test_smart_sync_setup_helper_json_decode_error_with_stderr( self, mock_popen, mock_which ): @@ -3632,8 +3634,8 @@ str(context.exception), ) - @mock.patch("shutil.which") - @mock.patch("subprocess.Popen") + @mock.patch.object(shutil, "which") + @mock.patch.object(subprocess, "Popen") def test_smart_sync_setup_helper_error_with_stderr( self, mock_popen, mock_which ): @@ -3694,9 +3696,9 @@ ) def _RunSetup(self, env: Dict[str, str]) -> str: - with mock.patch.dict(os.environ, env, clear=True), mock.patch( - "xmlrpc.client.Server", return_value=self.mock_server - ), mock.patch("builtins.open", mock.mock_open()): + with mock.patch.dict(os.environ, env, clear=True), mock.patch.object( + xmlrpc.client, "Server", return_value=self.mock_server + ), mock.patch.object(builtins, "open", mock.mock_open()): return self.cmd._SmartSyncSetup( self.opt, self.smart_sync_manifest_path, self.manifest )
diff --git a/tests/test_subcmds_upload.py b/tests/test_subcmds_upload.py index 53cc651..8968042 100644 --- a/tests/test_subcmds_upload.py +++ b/tests/test_subcmds_upload.py
@@ -19,7 +19,9 @@ import pytest +import editor import error +import git_superproject from subcmds import upload @@ -183,8 +185,10 @@ branch2 = _create_mock_branch("b2", project_relpath="p2") pending = [(branch1.project, [branch1]), (branch2.project, [branch2])] - with mock.patch.object(cmd, "_UploadAndReport") as mock_upload, mock.patch( - "editor.Editor.EditString" + with mock.patch.object( + cmd, "_UploadAndReport" + ) as mock_upload, mock.patch.object( + editor.Editor, "EditString" ) as mock_edit: cmd._MultipleBranches(opt, pending, _STUB_PEOPLE) mock_edit.assert_not_called() @@ -202,8 +206,10 @@ branch2 = _create_mock_branch("b2", project_relpath="p2") pending = [(branch1.project, [branch1]), (branch2.project, [branch2])] - with mock.patch.object(cmd, "_UploadAndReport") as mock_upload, mock.patch( - "editor.Editor.EditString" + with mock.patch.object( + cmd, "_UploadAndReport" + ) as mock_upload, mock.patch.object( + editor.Editor, "EditString" ) as mock_edit: cmd._MultipleBranches(opt, pending, _STUB_PEOPLE) mock_edit.assert_not_called() @@ -221,8 +227,10 @@ branch2 = _create_mock_branch("feature", project_relpath="p2") pending = [(branch1.project, [branch1]), (branch2.project, [branch2])] - with mock.patch.object(cmd, "_UploadAndReport") as mock_upload, mock.patch( - "editor.Editor.EditString" + with mock.patch.object( + cmd, "_UploadAndReport" + ) as mock_upload, mock.patch.object( + editor.Editor, "EditString" ) as mock_edit: cmd._MultipleBranches(opt, pending, _STUB_PEOPLE) mock_edit.assert_not_called() @@ -265,8 +273,10 @@ " branch b1 ( 1 commit, 2026-08-26) to remote branch " "refs/heads/main:\n" ) - with mock.patch.object(cmd, "_UploadAndReport") as mock_upload, mock.patch( - "editor.Editor.EditString", return_value=edited_script + with mock.patch.object( + cmd, "_UploadAndReport" + ) as mock_upload, mock.patch.object( + editor.Editor, "EditString", return_value=edited_script ) as mock_edit: cmd._MultipleBranches(opt, pending, _STUB_PEOPLE) mock_edit.assert_called_once() @@ -324,7 +334,9 @@ cmd.CommonValidateOptions(opt, []) branch = mock.MagicMock() branch.project.dest_branch = None - with mock.patch("git_superproject.UseSuperproject", return_value=False): + with mock.patch.object( + git_superproject, "UseSuperproject", return_value=False + ): cmd._UploadBranch(opt, branch, _STUB_PEOPLE) branch.UploadForReview.assert_called_once()
diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index d27b170..82b5425 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py
@@ -83,9 +83,11 @@ def test_version(self, repo_wrapper: wrapper.Wrapper) -> None: """Make sure _Version works.""" with pytest.raises(SystemExit) as e: - with mock.patch("sys.stdout", new_callable=io.StringIO) as stdout: - with mock.patch( - "sys.stderr", new_callable=io.StringIO + with mock.patch.object( + sys, "stdout", new_callable=io.StringIO + ) as stdout: + with mock.patch.object( + sys, "stderr", new_callable=io.StringIO ) as stderr: repo_wrapper._Version() assert e.value.code == 0