Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite725c82

Browse files
committed
Make the restore_use_shell_state fixture more robust
1 parent6a35261 commite725c82

File tree

1 file changed

+39
-13
lines changed

1 file changed

+39
-13
lines changed

‎test/deprecation/test_cmd_git.py

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"""
5555

5656
importcontextlib
57+
importlogging
5758
importsys
5859
fromtypingimportGenerator
5960
importunittest.mock
@@ -75,6 +76,8 @@
7576
_USE_SHELL_DANGEROUS_FRAGMENT="Setting Git.USE_SHELL to True is unsafe and insecure"
7677
"""Beginning text of USE_SHELL deprecation warnings when USE_SHELL is set True."""
7778

79+
_logger=logging.getLogger(__name__)
80+
7881

7982
@contextlib.contextmanager
8083
def_suppress_deprecation_warning()->Generator[None,None,None]:
@@ -85,37 +88,60 @@ def _suppress_deprecation_warning() -> Generator[None, None, None]:
8588

8689
@pytest.fixture
8790
defrestore_use_shell_state()->Generator[None,None,None]:
88-
"""Fixture to attempt to restore state associated with the``USE_SHELL`` attribute.
91+
"""Fixture to attempt to restore state associated with the USE_SHELL attribute.
8992
9093
This is used to decrease the likelihood of state changes leaking out and affecting
91-
other tests. But the goal is not to assert that ``_USE_SHELL`` is used, nor anything
92-
about how or when it is used, which is an implementation detail subject to change.
94+
other tests. But the goal is not to assert implementation details of USE_SHELL.
95+
96+
This covers two of the common implementation strategies, for convenience in testing
97+
both. USE_SHELL could be implemented in the metaclass:
9398
94-
This is possible but inelegant to do with pytest's monkeypatch fixture, which only
95-
restores attributes that it has previously been used to change, create, or remove.
99+
* With a separate _USE_SHELL backing attribute. If using a property or other
100+
descriptor, this is the natural way to do it, but custom __getattribute__ and
101+
__setattr__ logic, if it does more than adding warnings, may also use that.
102+
* Like a simple attribute, using USE_SHELL itself, stored as usual in the class
103+
dictionary, with custom __getattribute__/__setattr__ logic only to warn.
104+
105+
This tries to save private state, tries to save the public attribute value, yields
106+
to the test case, tries to restore the public attribute value, then tries to restore
107+
private state. The idea is that if the getting or setting logic is wrong in the code
108+
under test, the state will still most likely be reset successfully.
96109
"""
97110
no_value=object()
98111

112+
# Try to save the original private state.
99113
try:
100-
old_backing_value=Git._USE_SHELL
114+
old_private_value=Git._USE_SHELL
101115
exceptAttributeError:
102-
old_backing_value=no_value
116+
separate_backing_attribute=False
117+
try:
118+
old_private_value=type.__getattribute__(Git,"USE_SHELL")
119+
exceptAttributeError:
120+
old_private_value=no_value
121+
_logger.error("Cannot retrieve old private _USE_SHELL or USE_SHELL value")
122+
else:
123+
separate_backing_attribute=True
124+
103125
try:
126+
# Try to save the original public value. Rather than attempt to restore a state
127+
# where the attribute is not set, if we cannot do this we allow AttributeError
128+
# to propagate out of the fixture, erroring the test case before its code runs.
104129
with_suppress_deprecation_warning():
105130
old_public_value=Git.USE_SHELL
106131

107132
# This doesn't have its own try-finally because pytest catches exceptions raised
108133
# during the yield. (The outer try-finally catches exceptions in this fixture.)
109134
yield
110135

136+
# Try to restore the original public value.
111137
with_suppress_deprecation_warning():
112138
Git.USE_SHELL=old_public_value
113139
finally:
114-
ifold_backing_valueisno_value:
115-
withcontextlib.suppress(AttributeError):
116-
delGit._USE_SHELL
117-
else:
118-
Git._USE_SHELL=old_backing_value
140+
# Try to restore the original private state.
141+
ifseparate_backing_attribute:
142+
Git._USE_SHELL=old_private_value
143+
elifold_private_valueisnotno_value:
144+
type.__setattr__(Git,"USE_SHELL",old_private_value)
119145

120146

121147
deftest_cannot_access_undefined_on_git_class()->None:
@@ -277,7 +303,7 @@ def test_use_shell_is_mock_patchable_on_class_as_object_attribute(
277303
"""
278304
Git.USE_SHELL=original_value
279305
ifGit.USE_SHELLisnotoriginal_value:
280-
raiseRuntimeError(f"Can't set up the test")
306+
raiseRuntimeError("Can't set up the test")
281307
new_value=notoriginal_value
282308

283309
withunittest.mock.patch.object(Git,"USE_SHELL",new_value):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp