Skip to content

bpo-31904: disable os.popen and impacted test cases on VxWorks #21687

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Doc/library/os.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Notes on the availability of these functions:
objects, and result in an object of the same type, if a path or file name is
returned.

* On VxWorks, os.fork, os.execv and os.spawn*p* are not supported.
* On VxWorks, os.popen, os.fork, os.execv and os.spawn*p* are not supported.

.. note::

Expand Down
94 changes: 49 additions & 45 deletions Lib/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
"defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR",
"SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen",
"popen", "extsep"]
"extsep"]

def _exists(name):
return name in globals()
Expand Down Expand Up @@ -969,51 +969,55 @@ def spawnlpe(mode, file, *args):

__all__.extend(["spawnlp", "spawnlpe"])


# Supply os.popen()
def popen(cmd, mode="r", buffering=-1):
if not isinstance(cmd, str):
raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
if mode not in ("r", "w"):
raise ValueError("invalid mode %r" % mode)
if buffering == 0 or buffering is None:
raise ValueError("popen() does not support unbuffered streams")
import subprocess, io
if mode == "r":
proc = subprocess.Popen(cmd,
shell=True,
stdout=subprocess.PIPE,
bufsize=buffering)
return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
else:
proc = subprocess.Popen(cmd,
shell=True,
stdin=subprocess.PIPE,
bufsize=buffering)
return _wrap_close(io.TextIOWrapper(proc.stdin), proc)

# Helper for popen() -- a proxy for a file whose close waits for the process
class _wrap_close:
def __init__(self, stream, proc):
self._stream = stream
self._proc = proc
def close(self):
self._stream.close()
returncode = self._proc.wait()
if returncode == 0:
return None
if name == 'nt':
return returncode
# VxWorks has no user space shell provided. As a result, running
# command in a shell can't be supported.
if sys.platform != 'vxworks':
# Supply os.popen()
def popen(cmd, mode="r", buffering=-1):
if not isinstance(cmd, str):
raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
if mode not in ("r", "w"):
raise ValueError("invalid mode %r" % mode)
if buffering == 0 or buffering is None:
raise ValueError("popen() does not support unbuffered streams")
import subprocess, io
if mode == "r":
proc = subprocess.Popen(cmd,
shell=True,
stdout=subprocess.PIPE,
bufsize=buffering)
return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
else:
return returncode << 8 # Shift left to match old behavior
def __enter__(self):
return self
def __exit__(self, *args):
self.close()
def __getattr__(self, name):
return getattr(self._stream, name)
def __iter__(self):
return iter(self._stream)
proc = subprocess.Popen(cmd,
shell=True,
stdin=subprocess.PIPE,
bufsize=buffering)
return _wrap_close(io.TextIOWrapper(proc.stdin), proc)

# Helper for popen() -- a proxy for a file whose close waits for the process
class _wrap_close:
def __init__(self, stream, proc):
self._stream = stream
self._proc = proc
def close(self):
self._stream.close()
returncode = self._proc.wait()
if returncode == 0:
return None
if name == 'nt':
return returncode
else:
return returncode << 8 # Shift left to match old behavior
def __enter__(self):
return self
def __exit__(self, *args):
self.close()
def __getattr__(self, name):
return getattr(self._stream, name)
def __iter__(self):
return iter(self._stream)

__all__.append("popen")

# Supply os.fdopen()
def fdopen(fd, *args, **kwargs):
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,7 @@ def _empty_mapping(self):
# Bug 1110478
@unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
'requires a shell')
@unittest.skipUnless(hasattr(os, 'popen'), "needs os.popen()")
def test_update2(self):
os.environ.clear()
os.environ.update(HELLO="World")
Expand All @@ -996,6 +997,7 @@ def test_update2(self):

@unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
'requires a shell')
@unittest.skipUnless(hasattr(os, 'popen'), "needs os.popen()")
def test_os_popen_iter(self):
with os.popen("%s -c 'echo \"line1\nline2\nline3\"'"
% unix_shell) as popen:
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_popen.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from test import support
import os, sys

if not hasattr(os, 'popen'):
raise unittest.SkipTest("need os.popen()")

# Test that command-lines get down as we expect.
# To do this we execute:
# python -c "import sys;print(sys.argv)" {rest_of_commandline}
Expand Down
3 changes: 2 additions & 1 deletion Lib/test/test_posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,7 @@ def test_getgrouplist(self):


@unittest.skipUnless(hasattr(os, 'getegid'), "test needs os.getegid()")
@unittest.skipUnless(hasattr(os, 'popen'), "test needs os.popen()")
def test_getgroups(self):
with os.popen('id -G 2>/dev/null') as idg:
groups = idg.read().strip()
Expand Down Expand Up @@ -1929,7 +1930,7 @@ def test_posix_spawnp(self):
class TestPosixWeaklinking(unittest.TestCase):
# These test cases verify that weak linking support on macOS works
# as expected. These cases only test new behaviour introduced by weak linking,
# regular behaviour is tested by the normal test cases.
# regular behaviour is tested by the normal test cases.
#
# See the section on Weak Linking in Mac/README.txt for more information.
def setUp(self):
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def test_returned_list_identity(self):
self.assertIsNot(r, x)
self.assertIsNot(w, x)

@unittest.skipUnless(hasattr(os, 'popen'), "need os.popen()")
def test_select(self):
cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done'
with os.popen(cmd) as p:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Disable os.popen and impacted tests on VxWorks