Skip to content

Commit 8aca8b6

Browse files
committed
gh-148402: add missing stacklevel to warnings.warn() in subprocess.Popen
Add stacklevel to two warnings.warn() calls in subprocess.Popen so that warnings point to the caller's code instead of subprocess.py internals: - POSIX path (__init__): stacklevel=2 - Windows path (_execute_child): stacklevel=3 (extra frame depth) Add regression tests that assert warning.filename == __file__.
1 parent ba1e1c1 commit 8aca8b6

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

Lib/subprocess.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ def __init__(self, args, bufsize=-1, executable=None,
912912
else:
913913
# POSIX
914914
if pass_fds and not close_fds:
915-
warnings.warn("pass_fds overriding close_fds.", RuntimeWarning)
915+
warnings.warn("pass_fds overriding close_fds.", RuntimeWarning, stacklevel=2)
916916
close_fds = True
917917
if startupinfo is not None:
918918
raise ValueError("startupinfo is only supported on Windows "
@@ -1567,7 +1567,8 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
15671567
if handle_list:
15681568
if not close_fds:
15691569
warnings.warn("startupinfo.lpAttributeList['handle_list'] "
1570-
"overriding close_fds", RuntimeWarning)
1570+
"overriding close_fds", RuntimeWarning,
1571+
stacklevel=3)
15711572

15721573
# When using the handle_list we always request to inherit
15731574
# handles but the only handles that will be inherited are

Lib/test/test_subprocess.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3177,6 +3177,18 @@ def test_pass_fds(self):
31773177
close_fds=False, pass_fds=(fd, )))
31783178
self.assertIn('overriding close_fds', str(context.warning))
31793179

3180+
def test_pass_fds_overriding_close_fds_warning_location(self):
3181+
# gh-148402: the warning should point to the caller, not subprocess.py
3182+
fd = os.dup(1)
3183+
self.addCleanup(os.close, fd)
3184+
os.set_inheritable(fd, True)
3185+
with self.assertWarns(RuntimeWarning) as context:
3186+
p = subprocess.Popen(ZERO_RETURN_CMD,
3187+
close_fds=False, pass_fds=(fd,))
3188+
p.wait()
3189+
self.assertIn('overriding close_fds', str(context.warning))
3190+
self.assertEqual(context.filename, __file__)
3191+
31803192
def test_pass_fds_inheritable(self):
31813193
script = support.findfile("fd_status.py", subdir="subprocessdata")
31823194

@@ -3762,8 +3774,7 @@ def test_close_fds_with_stdio(self):
37623774
self.assertIn(b"OSError", stderr)
37633775

37643776
# Check for a warning due to using handle_list and close_fds=False
3765-
with warnings_helper.check_warnings((".*overriding close_fds",
3766-
RuntimeWarning)):
3777+
with self.assertWarns(RuntimeWarning) as context:
37673778
startupinfo = subprocess.STARTUPINFO()
37683779
startupinfo.lpAttributeList = {"handle_list": handles[:]}
37693780
p = subprocess.Popen([sys.executable, "-c",
@@ -3772,6 +3783,9 @@ def test_close_fds_with_stdio(self):
37723783
startupinfo=startupinfo, close_fds=False)
37733784
stdout, stderr = p.communicate()
37743785
self.assertEqual(p.returncode, 0)
3786+
self.assertIn('overriding close_fds', str(context.warning))
3787+
# gh-148402: warning should point to the caller, not subprocess.py
3788+
self.assertEqual(context.filename, __file__)
37753789

37763790
def test_empty_attribute_list(self):
37773791
startupinfo = subprocess.STARTUPINFO()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add missing ``stacklevel`` to two :func:`warnings.warn` calls in
2+
:class:`subprocess.Popen` so that warnings correctly point to the caller's
3+
code instead of ``subprocess.py`` internals.

0 commit comments

Comments
 (0)