Skip to content

Commit 6a35261

Browse files
committed
Test that USE_SHELL is unittest.mock.patch patchable
1 parent 40ed842 commit 6a35261

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

test/deprecation/test_cmd_git.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import contextlib
5757
import sys
5858
from typing import Generator
59+
import unittest.mock
5960
import warnings
6061

6162
if sys.version_info >= (3, 11):
@@ -250,6 +251,41 @@ def test_use_shell_cannot_set_on_instance(
250251
instance.USE_SHELL = value
251252

252253

254+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
255+
@pytest.mark.parametrize("original_value", [False, True])
256+
def test_use_shell_is_mock_patchable_on_class_as_object_attribute(
257+
original_value: bool,
258+
restore_use_shell_state: None,
259+
) -> None:
260+
"""Asymmetric patching looking up USE_SHELL in ``__dict__`` doesn't corrupt state.
261+
262+
Code using GitPython may temporarily set Git.USE_SHELL to a different value. Ideally
263+
it does not use unittest.mock.patch to do so, because that makes subtle assumptions
264+
about the relationship between attributes and dictionaries. If the attribute can be
265+
retrieved from the ``__dict__`` rather than directly, that value is assumed the
266+
correct one to restore, even by a normal setattr.
267+
268+
The effect is that some ways of simulating a class attribute with added behavior can
269+
cause a descriptor, such as a property, to be set to its own backing attribute
270+
during unpatching; then subsequent reads raise RecursionError. This happens if both
271+
(a) setting it on the class is customized in a metaclass and (b) getting it on
272+
instances is customized with a descriptor (such as a property) in the class itself.
273+
274+
Although ideally code outside GitPython would not rely on being able to patch
275+
Git.USE_SHELL with unittest.mock.patch, the technique is widespread. Thus, USE_SHELL
276+
should be implemented in some way compatible with it. This test checks for that.
277+
"""
278+
Git.USE_SHELL = original_value
279+
if Git.USE_SHELL is not original_value:
280+
raise RuntimeError(f"Can't set up the test")
281+
new_value = not original_value
282+
283+
with unittest.mock.patch.object(Git, "USE_SHELL", new_value):
284+
assert Git.USE_SHELL is new_value
285+
286+
assert Git.USE_SHELL is original_value
287+
288+
253289
_EXPECTED_DIR_SUBSET = {
254290
"cat_file_all",
255291
"cat_file_header",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy