-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
bpo-31368: Expose preadv (preadv2) and pwritev (pwritev2) in the os module #5239
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
Changes from 13 commits
ea21128
4570976
21a3004
8a2a2a3
c0c53dc
4ddbca9
cac62ac
c7b7285
58910d0
f7cdf22
47f65b5
87c6970
cb74d38
5563b8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1101,6 +1101,49 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo | |
.. versionadded:: 3.3 | ||
|
||
|
||
.. function:: pwritev(fd, buffers, offset, flags=0) | ||
|
||
Combines the functionality of :func:`os.writev` and :func:`os.pwrite`. It | ||
writes the contents of *buffers* to file descriptor *fd* at offset *offset*. | ||
*buffers* must be a sequence of :term:`bytes-like objects <bytes-like object>`. | ||
Buffers are processed in array order. Entire contents of first buffer is written | ||
before proceeding to second, and so on. The operating system may set a limit | ||
(sysconf() value SC_IOV_MAX) on the number of buffers that can be used. | ||
:func:`~os.pwritev` writes the contents of each object to the file descriptor | ||
and returns the total number of bytes written. | ||
|
||
|
||
The *flags* argument contains a bitwise OR of zero or more of the following | ||
flags: | ||
|
||
- RWF_DSYNC | ||
- RWF_SYNC | ||
|
||
:func:`~os.pwritev` will call *pwritev2* system call if available, which modifies | ||
the behavior on a per-call basis based on the value of the *flags* argument. The | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure that ", which modifies the behavior on a per-call basis based on the value of the flags argument." is needed. Nobody expects a flag passed to a function to have an effect on following calls. And the usage of pwrite2() doesn't mean that the caller must pass a non-zero flags. This sentence is confusing. |
||
:func:`~os.pwritev2` function is required to pass flags. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, there is no :func: I suggested "The C function :func: |
||
|
||
The :func:`~os.pwritev2` function is required to pass flags. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick: I would move this sentence before describing on which Linux platforms version it is available. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto, don't write ":func: Note the "c" prefix before "func". |
||
|
||
*pwritev2* and *flags* different than zero are available since Linux version | ||
4.7. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "The :func: I'm not sure that the Python has to mention pwritev2(). It's confusing and useless. I don't think that the documentation of other os function lists each internal called C functions. I suggest something simpler like: "Using non-zero flags requires Linux 4.7 or newer." |
||
|
||
Availability: Linux (version 2.6.30), FreeBSD 6.0 and newer, | ||
OpenBSD (version 2.7 and newer). | ||
|
||
.. versionadded:: 3.7 | ||
|
||
|
||
.. data:: RWF_DSYNC | ||
RWF_SYNC | ||
|
||
The above constants are available on Linux Kernel 4.7 (or newer). | ||
|
||
Availability: Linux. | ||
|
||
.. versionadded:: 3.7 | ||
|
||
|
||
.. function:: read(fd, n) | ||
|
||
Read at most *n* bytes from file descriptor *fd*. Return a bytestring containing the | ||
|
@@ -1195,6 +1238,47 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo | |
.. versionadded:: 3.3 | ||
|
||
|
||
.. function:: preadv(fd, buffers, offset, flags=0) | ||
|
||
Combines the functionality of :func:`os.readv` and :func:`os.pread`. It | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed you didn't duplicate the definition of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I has hessitant to duplicate because Corrected in c7b7285 |
||
reads from a file descriptor *fd* into a number of mutable :term:`bytes-like | ||
objects <bytes-like object>` *buffers*. As :func:`os.readv`, it will transfer | ||
data into each buffer until it is full and then move on to the next buffer in | ||
the sequence to hold the rest of the data. Its fourth argument, *offset*, | ||
specifies the file offset at which the input operation is to be performed. | ||
:func:`~os.preadv` return the total number of bytes read (which can be less than | ||
the total capacity of all the objects). | ||
|
||
The flags argument contains a bitwise OR of zero or more of the following | ||
flags: | ||
|
||
- RWF_HIPRI | ||
- RWF_NOWAIT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick: please align "-" on the previous paragraph (fix the indentation). |
||
|
||
:func:`~os.preadv` will call *preadv2* system call if available, which modifies | ||
the behavior on a per-call basis based on the value of the *flags* argument. The | ||
:c:func:`preadv2` function is required to pass flags. | ||
|
||
*preadv2* and flags different than zero are available since Linux version | ||
4.6 and newer. | ||
|
||
Availability: Linux (version 2.6.30), FreeBSD 6.0 and newer, | ||
OpenBSD (version 2.7 and newer). | ||
|
||
.. versionadded:: 3.7 | ||
|
||
|
||
.. data:: RWF_HIPRI | ||
RWF_NOWAIT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hum, I suggest to have one ".. data" entry per constant and copy the documentation from the manual page. Extract of Fedora 27 manual pages:
It would become simpler to describe the availability. |
||
|
||
The above constants are available on Linux Kernel 4.11 and 4.6 (or newer) | ||
respectively. | ||
|
||
Availability: Linux. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest to remove the previous sentence and just write: "Availability: Linux 4.11 and newer." As done for other functions documentation like getrandom(). |
||
|
||
.. versionadded:: 3.7 | ||
|
||
|
||
.. function:: tcgetpgrp(fd) | ||
|
||
Return the process group associated with the terminal given by *fd* (an open | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -272,6 +272,28 @@ def test_pread(self): | |
finally: | ||
os.close(fd) | ||
|
||
@unittest.skipUnless(hasattr(posix, 'preadv'), "test needs posix.preadv()") | ||
def test_preadv(self): | ||
fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) | ||
try: | ||
os.write(fd, b'test1tt2t3t5t6t6t8') | ||
buf = [bytearray(i) for i in [5, 3, 2]] | ||
self.assertEqual(posix.preadv(fd, buf, 3), 10) | ||
self.assertEqual([b't1tt2', b't3t', b'5t'], list(buf)) | ||
finally: | ||
os.close(fd) | ||
|
||
@unittest.skipUnless(hasattr(posix, 'RWF_HIPRI'), "test needs posix.RWF_HIPRI") | ||
def test_preadv_flags(self): | ||
fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) | ||
try: | ||
os.write(fd, b'test1tt2t3t5t6t6t8') | ||
buf = [bytearray(i) for i in [5, 3, 2]] | ||
self.assertEqual(posix.preadv(fd, buf, 3, os.RWF_HIPRI), 10) | ||
self.assertEqual([b't1tt2', b't3t', b'5t'], list(buf)) | ||
finally: | ||
os.close(fd) | ||
|
||
@unittest.skipUnless(hasattr(posix, 'pwrite'), "test needs posix.pwrite()") | ||
def test_pwrite(self): | ||
fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) | ||
|
@@ -283,6 +305,37 @@ def test_pwrite(self): | |
finally: | ||
os.close(fd) | ||
|
||
@unittest.skipUnless(hasattr(posix, 'pwritev'), "test needs posix.pwritev()") | ||
def test_pwritev(self): | ||
fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) | ||
try: | ||
os.write(fd,b"xx") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PEP 8: add a space after "," |
||
os.lseek(fd, 0, os.SEEK_SET) | ||
n = os.pwritev(fd, [b'test1', b'tt2', b't3'], 2) | ||
self.assertEqual(n, 10) | ||
|
||
os.lseek(fd, 0, os.SEEK_SET) | ||
self.assertEqual(b'xxtest1tt2', posix.read(fd, 10)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest posix.read(fd, 100) to make sure that no extra data is written. Same comment for the other test method below. |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick: IMHO this empty line is useless |
||
finally: | ||
os.close(fd) | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PEP 8: only one empty line between methods of class, please. (remove this empty line) |
||
@unittest.skipUnless(hasattr(posix, 'os.RWF_SYNC'), "test needs os.RWF_SYNC") | ||
def test_pwritev_flags(self): | ||
fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) | ||
try: | ||
os.write(fd,b"xx") | ||
os.lseek(fd, 0, os.SEEK_SET) | ||
n = os.pwritev(fd, [b'test1', b'tt2', b't3'], 2, os.RWF_SYNC) | ||
self.assertEqual(n, 10) | ||
|
||
os.lseek(fd, 0, os.SEEK_SET) | ||
self.assertEqual(b'xxtest1tt2', posix.read(fd, 10)) | ||
finally: | ||
os.close(fd) | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto: remove this empty line |
||
@unittest.skipUnless(hasattr(posix, 'posix_fallocate'), | ||
"test needs posix.posix_fallocate()") | ||
def test_posix_fallocate(self): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Expose preadv (preadv2) and pwritev (pwritev2) system calls in the os module. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest: Add os.preadv() and os.pwritev() functions. Again, I don't think that it's needed to mention the underlying C functions. |
||
Patch by Pablo Galindo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a single empty line is enough.