]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/wait.py
4 from functools
import partial
7 from time
import monotonic
9 from time
import time
as monotonic
11 __all__
= ["NoWayToWaitForSocketError", "wait_for_read", "wait_for_write"]
14 class NoWayToWaitForSocketError(Exception):
18 # How should we wait on sockets?
20 # There are two types of APIs you can use for waiting on sockets: the fancy
21 # modern stateful APIs like epoll/kqueue, and the older stateless APIs like
22 # select/poll. The stateful APIs are more efficient when you have a lots of
23 # sockets to keep track of, because you can set them up once and then use them
24 # lots of times. But we only ever want to wait on a single socket at a time
25 # and don't want to keep track of state, so the stateless APIs are actually
26 # more efficient. So we want to use select() or poll().
28 # Now, how do we choose between select() and poll()? On traditional Unixes,
29 # select() has a strange calling convention that makes it slow, or fail
30 # altogether, for high-numbered file descriptors. The point of poll() is to fix
31 # that, so on Unixes, we prefer poll().
33 # On Windows, there is no poll() (or at least Python doesn't provide a wrapper
34 # for it), but that's OK, because on Windows, select() doesn't have this
35 # strange calling convention; plain select() works fine.
37 # So: on Windows we use select(), and everywhere else we use poll(). We also
38 # fall back to select() in case poll() is somehow broken or missing.
40 if sys
.version_info
>= (3, 5):
41 # Modern Python, that retries syscalls by default
42 def _retry_on_intr(fn
, timeout
):
46 # Old and broken Pythons.
47 def _retry_on_intr(fn
, timeout
):
49 deadline
= float("inf")
51 deadline
= monotonic() + timeout
56 # OSError for 3 <= pyver < 3.5, select.error for pyver <= 2.7
57 except (OSError, select
.error
) as e
:
58 # 'e.args[0]' incantation works for both OSError and select.error
59 if e
.args
[0] != errno
.EINTR
:
62 timeout
= deadline
- monotonic()
65 if timeout
== float("inf"):
70 def select_wait_for_socket(sock
, read
=False, write
=False, timeout
=None):
71 if not read
and not write
:
72 raise RuntimeError("must specify at least one of read=True, write=True")
79 # When doing a non-blocking connect, most systems signal success by
80 # marking the socket writable. Windows, though, signals success by marked
81 # it as "exceptional". We paper over the difference by checking the write
82 # sockets for both conditions. (The stdlib selectors module does the same
84 fn
= partial(select
.select
, rcheck
, wcheck
, wcheck
)
85 rready
, wready
, xready
= _retry_on_intr(fn
, timeout
)
86 return bool(rready
or wready
or xready
)
89 def poll_wait_for_socket(sock
, read
=False, write
=False, timeout
=None):
90 if not read
and not write
:
91 raise RuntimeError("must specify at least one of read=True, write=True")
96 mask |
= select
.POLLOUT
97 poll_obj
= select
.poll()
98 poll_obj
.register(sock
, mask
)
100 # For some reason, poll() takes timeout in milliseconds
104 return poll_obj
.poll(t
)
106 return bool(_retry_on_intr(do_poll
, timeout
))
109 def null_wait_for_socket(*args
, **kwargs
):
110 raise NoWayToWaitForSocketError("no select-equivalent available")
113 def _have_working_poll():
114 # Apparently some systems have a select.poll that fails as soon as you try
115 # to use it, either due to strange configuration or broken monkeypatching
116 # from libraries like eventlet/greenlet.
118 poll_obj
= select
.poll()
119 _retry_on_intr(poll_obj
.poll
, 0)
120 except (AttributeError, OSError):
126 def wait_for_socket(*args
, **kwargs
):
127 # We delay choosing which implementation to use until the first time we're
128 # called. We could do it at import time, but then we might make the wrong
129 # decision if someone goes wild with monkeypatching select.poll after
131 global wait_for_socket
132 if _have_working_poll():
133 wait_for_socket
= poll_wait_for_socket
134 elif hasattr(select
, "select"):
135 wait_for_socket
= select_wait_for_socket
136 else: # Platform-specific: Appengine.
137 wait_for_socket
= null_wait_for_socket
138 return wait_for_socket(*args
, **kwargs
)
141 def wait_for_read(sock
, timeout
=None):
142 """Waits for reading to be available on a given socket.
143 Returns True if the socket is readable, or False if the timeout expired.
145 return wait_for_socket(sock
, read
=True, timeout
=timeout
)
148 def wait_for_write(sock
, timeout
=None):
149 """Waits for writing to be available on a given socket.
150 Returns True if the socket is readable, or False if the timeout expired.
152 return wait_for_socket(sock
, write
=True, timeout
=timeout
)