mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Remove native popen() and fdopen(), replacing them with subprocess calls.
Fix a path to an assert in fileio_read(). Some misc tweaks.
This commit is contained in:
parent
d8595fe304
commit
c2f93dc2e4
7 changed files with 59 additions and 1552 deletions
|
@ -120,6 +120,8 @@ def open(file, mode="r", buffering=None, *, encoding=None, newline=None):
|
||||||
(appending and "a" or "") +
|
(appending and "a" or "") +
|
||||||
(updating and "+" or ""))
|
(updating and "+" or ""))
|
||||||
if buffering is None:
|
if buffering is None:
|
||||||
|
buffering = -1
|
||||||
|
if buffering < 0:
|
||||||
buffering = DEFAULT_BUFFER_SIZE
|
buffering = DEFAULT_BUFFER_SIZE
|
||||||
# XXX Should default to line buffering if os.isatty(raw.fileno())
|
# XXX Should default to line buffering if os.isatty(raw.fileno())
|
||||||
try:
|
try:
|
||||||
|
@ -446,8 +448,8 @@ class BufferedIOBase(IOBase):
|
||||||
implementation, but wrap one.
|
implementation, but wrap one.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def read(self, n: int = -1) -> bytes:
|
def read(self, n: int = None) -> bytes:
|
||||||
"""read(n: int = -1) -> bytes. Read and return up to n bytes.
|
"""read(n: int = None) -> bytes. Read and return up to n bytes.
|
||||||
|
|
||||||
If the argument is omitted, None, or negative, reads and
|
If the argument is omitted, None, or negative, reads and
|
||||||
returns all data until EOF.
|
returns all data until EOF.
|
||||||
|
@ -717,6 +719,8 @@ class BufferedWriter(_BufferedIOMixin):
|
||||||
self._write_buf = b""
|
self._write_buf = b""
|
||||||
|
|
||||||
def write(self, b):
|
def write(self, b):
|
||||||
|
if not isinstance(b, bytes):
|
||||||
|
b = bytes(b)
|
||||||
# XXX we can implement some more tricks to try and avoid partial writes
|
# XXX we can implement some more tricks to try and avoid partial writes
|
||||||
if len(self._write_buf) > self.buffer_size:
|
if len(self._write_buf) > self.buffer_size:
|
||||||
# We're full, so let's pre-flush the buffer
|
# We're full, so let's pre-flush the buffer
|
||||||
|
|
38
Lib/os.py
38
Lib/os.py
|
@ -696,3 +696,41 @@ if not _exists("urandom"):
|
||||||
bs += read(_urandomfd, n - len(bs))
|
bs += read(_urandomfd, n - len(bs))
|
||||||
close(_urandomfd)
|
close(_urandomfd)
|
||||||
return bs
|
return bs
|
||||||
|
|
||||||
|
# Supply os.popen()
|
||||||
|
def popen(cmd, mode="r", buffering=None):
|
||||||
|
if not isinstance(cmd, basestring):
|
||||||
|
raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
|
||||||
|
if mode not in ("r", "w"):
|
||||||
|
raise ValueError("invalid mode %r" % mode)
|
||||||
|
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()
|
||||||
|
return self._proc.wait() << 8 # Shift left to match old behavior
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self._stream, name)
|
||||||
|
|
||||||
|
# Supply os.fdopen() (used by subprocess!)
|
||||||
|
def fdopen(fd, mode="r", buffering=-1):
|
||||||
|
if not isinstance(fd, int):
|
||||||
|
raise TypeError("invalid fd type (%s, expected integer)" % type(fd))
|
||||||
|
import io
|
||||||
|
return io.open(fd, mode, buffering)
|
||||||
|
|
|
@ -246,11 +246,11 @@ A more real-world example would look like this:
|
||||||
try:
|
try:
|
||||||
retcode = call("mycmd" + " myarg", shell=True)
|
retcode = call("mycmd" + " myarg", shell=True)
|
||||||
if retcode < 0:
|
if retcode < 0:
|
||||||
print >>sys.stderr, "Child was terminated by signal", -retcode
|
print("Child was terminated by signal", -retcode, file=sys.stderr)
|
||||||
else:
|
else:
|
||||||
print >>sys.stderr, "Child returned", retcode
|
print("Child returned", retcode, file=sys.stderr)
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
print >>sys.stderr, "Execution failed:", e
|
print("Execution failed:", e, file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
Replacing os.spawn*
|
Replacing os.spawn*
|
||||||
|
@ -539,6 +539,8 @@ class Popen(object):
|
||||||
os.close(errread)
|
os.close(errread)
|
||||||
errread = None
|
errread = None
|
||||||
|
|
||||||
|
if bufsize == 0:
|
||||||
|
bufsize = 1 # Nearly unbuffered (XXX for now)
|
||||||
if p2cwrite is not None:
|
if p2cwrite is not None:
|
||||||
self.stdin = os.fdopen(p2cwrite, 'wb', bufsize)
|
self.stdin = os.fdopen(p2cwrite, 'wb', bufsize)
|
||||||
if c2pread is not None:
|
if c2pread is not None:
|
||||||
|
@ -1007,6 +1009,7 @@ class Popen(object):
|
||||||
if data:
|
if data:
|
||||||
os.waitpid(self.pid, 0)
|
os.waitpid(self.pid, 0)
|
||||||
child_exception = pickle.loads(data)
|
child_exception = pickle.loads(data)
|
||||||
|
print("exc:", child_exception)
|
||||||
raise child_exception
|
raise child_exception
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -478,7 +478,7 @@ class TextIOWrapperTest(unittest.TestCase):
|
||||||
[ '\r\n', input_lines ],
|
[ '\r\n', input_lines ],
|
||||||
]
|
]
|
||||||
|
|
||||||
encodings = ('utf-8', 'bz2')
|
encodings = ('utf-8', 'latin-1')
|
||||||
|
|
||||||
# Try a range of pad sizes to test the case where \r is the last
|
# Try a range of pad sizes to test the case where \r is the last
|
||||||
# character in TextIOWrapper._pending_line.
|
# character in TextIOWrapper._pending_line.
|
||||||
|
|
|
@ -730,7 +730,7 @@ class test_SpooledTemporaryFile(TC):
|
||||||
write("a" * 35)
|
write("a" * 35)
|
||||||
write("b" * 35)
|
write("b" * 35)
|
||||||
seek(0, 0)
|
seek(0, 0)
|
||||||
self.failUnless(read(70) == 'a'*35 + 'b'*35)
|
self.assertEqual(read(70), 'a'*35 + 'b'*35)
|
||||||
|
|
||||||
test_classes.append(test_SpooledTemporaryFile)
|
test_classes.append(test_SpooledTemporaryFile)
|
||||||
|
|
||||||
|
|
|
@ -375,6 +375,12 @@ fileio_read(PyFileIOObject *self, PyObject *args)
|
||||||
if (!PyArg_ParseTuple(args, "i", &size))
|
if (!PyArg_ParseTuple(args, "i", &size))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (size < 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"negative read count");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bytes = PyBytes_FromStringAndSize(NULL, size);
|
bytes = PyBytes_FromStringAndSize(NULL, size);
|
||||||
if (bytes == NULL)
|
if (bytes == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue