bpo-32373: Add socket.getblocking() method.#4926
Conversation
vstinner
left a comment
There was a problem hiding this comment.
Please add self.assertFalse(self.serv.getblocking()) in testInitNonBlocking(), or write a new test to ensure that socket created with SOCK_NONBLOCK is non-blocking: getblocking() is false.
There was a problem hiding this comment.
"This reflects the last call to :meth:setblocking or :meth:settimeout."
What abou the following case?
>>> import socket; socket.socket(type=socket.SOCK_STREAM | socket.SOCK_NONBLOCK).getblocking()
False
I suggest to remove the second sentence.
There're extensive tests for that, see the updated |
vstinner
left a comment
There was a problem hiding this comment.
LGTM. You may document the new change in Doc/whatsnew/3.7.rst.
There was a problem hiding this comment.
Very minor thing: moving if it to next line increases docstrict readability imho.
There was a problem hiding this comment.
Hum, wait, what is this change? Timeouts > 0 now set the socket is blocking mode?
Would you mind to document this subtle behaviour change in settimeout() documentation?
There was a problem hiding this comment.
Yes. I'm still working on it. Turns out sendfile currently tests test sendfile on non-blocking sockets, but at the same time the documentation says that it's not supported for non-blocking sockets at all. It's a mess.
3b8074e to
5f1cf87
Compare
There was a problem hiding this comment.
I don't think there's any point in explaining this inside test_socket.
There was a problem hiding this comment.
In this test it makes sense, because I use fcntl to check the blocking mode of the underlying FD. Usually comments don't hurt in tests.
There was a problem hiding this comment.
Hmm, I'm sure that comment can be made much shorter :-)
There was a problem hiding this comment.
Can you write your version?
There was a problem hiding this comment.
Sure:
/* When a socket socket has a non-infinite timeout,
* its underlying fd is internally set to non-blocking.
* This table summarizes [etc.]
*/
There was a problem hiding this comment.
Hm, that's too short :) But I'll trim down my version.
There was a problem hiding this comment.
I'm wary of documenting internals here. It could be quite confusing to the reader, and doesn't seem to provide any useful information.
There was a problem hiding this comment.
Yeah, but my confusion with this thing came from me trying to check if the FD is blocking/nonblocking with fcntl.fcntl(sock, fcntl.F_GETFL, os.O_NONBLOCK) & os.O_NONBLOCK, and from there it's was quite a painful experience to discover how socket objects really work in Python (probably because I was debugging a failing sendfile test after some changes, but whatever).
I agree that all this information might overwhelm an average Python user who just wants to read the documentation. On the other hand, socket module is usually used by more or less advanced Python users.
That said, I'd be OK to keep this detailed documentation piece in socketmodule.c if everyone thinks it's too much to have it here.
There was a problem hiding this comment.
I think it would be best located in socketmodule.c indeed. Not sure where.
There was a problem hiding this comment.
Let's keep it in sock_settimeout(), as it's the central place that triggers blocking/non-blocking modes.
I remove my vote since Yury rewrote his PR after I approved it
vstinner
left a comment
There was a problem hiding this comment.
I don't think that getblocking() doc is the right place to explain in depth the behaviour of all timeouts and blocking/non-blocking modes.
getblocking() should be a simple as: return True if the timeout is equal to zero, False otherwise.
Maybe the long description of blocking/non-blocking should even be a separated PR?
|
When you're done making the requested changes, leave the comment: |
There was a problem hiding this comment.
It seems like you modified settimeout() behaviour. It must be documented here and in settimeout() doc.
There was a problem hiding this comment.
I'm wrong, settimeout() is (no longer) modified by this PR.
My comment was for a previous version of the PR. The PR evolved too quickly, I was lost, sorry.
The PR is in the exact same shape as it was the moment you approved it + few comments. I've pushed a few commits experimenting with different approaches, and later removed those experimental commits.
That's exactly what is in the PR. |
There was a problem hiding this comment.
I'm wrong, settimeout() is (no longer) modified by this PR.
My comment was for a previous version of the PR. The PR evolved too quickly, I was lost, sorry.
There was a problem hiding this comment.
Victor: "getblocking() should be a simple as: return True if the timeout is equal to zero, False otherwise."
Yury: "That's exactly what is in the PR."
Hum, this doc doesn't mention the timeout but refers to a "blocking mode" which is not well defined for timeout > 0.
The socket module mentions 3 modes: blocking, non-blocking and "timeout mode":
https://docs.python.org/dev/library/socket.html#notes-on-socket-timeouts
Replace "if socket is in blocking mode" with "if the timeout is equal to zero", or replace "is in blocking mode" with "is in blocking or timeout mode"?
By the way, there is already a note: "At the operating system level, sockets in timeout mode are internally set in non-blocking mode."
There was a problem hiding this comment.
I think the docstring here should say "This is equivalent to gettimeout() == 0", just like the docstring for setblocking explains that it's equivalent to a certain settimeout call.
There was a problem hiding this comment.
You may write an helper function which makes sure that timeout, blocking and SOCK_NONBLOCK flag are consistent.
Something like:
def check_timeout(sock, timeout):
assert sock.gettimeout() == timeout
assert sock.getblocking() == (timeout == 0.0)
assert _is_fd_in_blocking_mode(sock) == (timeout != 0.0)
(I'm not sure of these assertions :-))
There was a problem hiding this comment.
Since this is internal C docs, it might be helpful to add a column to the table for s->sock_timeout values – IIUC the rows would be < 0, 0.0, and > 0 respectively, but it took some grovelling through the source to figure that out.
|
@vstinner Do you have any objections here? I'd like to merge this to 3.7 and I don't see any open questions regarding this PR. Reorganizing tests to make them prettier is fine, but we can surely do it later. |
vstinner
left a comment
There was a problem hiding this comment.
LGTM.
If I recall correctly, I voted -1 on a previous because setblocking() was modified. It's not more the case. Moreover, the new doc is also better now.
| "getblocking()\n\ | ||
| \n\ | ||
| Returns True if socket is in blocking mode, or False if it\n\ | ||
| is in non-blocking mode."); |
There was a problem hiding this comment.
You may add "This is equivalent to checking socket.gettimeout() == 0." here as well.
|
@1st1: Please replace |
|
Thanks, Victor! |
https://bugs.python.org/issue32373