Switch to more concise Timeout parameters (#1111)
* Switch to more concise Timeout parameters * Update docs * Rename attributes Co-authored-by: Tom Christie <tom@tomchristie.com>
This commit is contained in:
parent
a9284214e2
commit
26cd4f54e8
@ -374,16 +374,16 @@ HTTPX also allows you to specify the timeout behavior in more fine grained detai
|
||||
There are four different types of timeouts that may occur. These are **connect**,
|
||||
**read**, **write**, and **pool** timeouts.
|
||||
|
||||
* The **connect timeout** specifies the maximum amount of time to wait until
|
||||
* The **connect** timeout specifies the maximum amount of time to wait until
|
||||
a connection to the requested host is established. If HTTPX is unable to connect
|
||||
within this time frame, a `ConnectTimeout` exception is raised.
|
||||
* The **read timeout** specifies the maximum duration to wait for a chunk of
|
||||
* The **read** timeout specifies the maximum duration to wait for a chunk of
|
||||
data to be received (for example, a chunk of the response body). If HTTPX is
|
||||
unable to receive data within this time frame, a `ReadTimeout` exception is raised.
|
||||
* The **write timeout** specifies the maximum duration to wait for a chunk of
|
||||
* The **write** timeout specifies the maximum duration to wait for a chunk of
|
||||
data to be sent (for example, a chunk of the request body). If HTTPX is unable
|
||||
to send data within this time frame, a `WriteTimeout` exception is raised.
|
||||
* The **pool timeout** specifies the maximum duration to wait for acquiring
|
||||
* The **pool** timeout specifies the maximum duration to wait for acquiring
|
||||
a connection from the connection pool. If HTTPX is unable to acquire a connection
|
||||
within this time frame, a `PoolTimeout` exception is raised. A related
|
||||
configuration here is the maximum number of allowable connections in the
|
||||
@ -393,7 +393,7 @@ You can configure the timeout behavior for any of these values...
|
||||
|
||||
```python
|
||||
# A client with a 60s timeout for connecting, and a 10s timeout elsewhere.
|
||||
timeout = httpx.Timeout(10.0, connect_timeout=60.0)
|
||||
timeout = httpx.Timeout(10.0, connect=60.0)
|
||||
client = httpx.Client(timeout=timeout)
|
||||
|
||||
response = client.get('http://example.com/')
|
||||
|
||||
144
httpx/_config.py
144
httpx/_config.py
@ -9,7 +9,7 @@ import certifi
|
||||
|
||||
from ._models import URL, Headers
|
||||
from ._types import CertTypes, HeaderTypes, TimeoutTypes, URLTypes, VerifyTypes
|
||||
from ._utils import get_ca_bundle_from_env, get_logger
|
||||
from ._utils import get_ca_bundle_from_env, get_logger, warn_deprecated
|
||||
|
||||
DEFAULT_CIPHERS = ":".join(
|
||||
[
|
||||
@ -196,51 +196,86 @@ class Timeout:
|
||||
|
||||
**Usage**:
|
||||
|
||||
Timeout(None) # No timeouts.
|
||||
Timeout(5.0) # 5s timeout on all operations.
|
||||
Timeout(None, connect_timeout=5.0) # 5s timeout on connect, no other timeouts.
|
||||
Timeout(5.0, connect_timeout=10.0) # 10s timeout on connect. 5s timeout elsewhere.
|
||||
Timeout(5.0, pool_timeout=None) # No timeout on acquiring connection from pool.
|
||||
# 5s timeout elsewhere.
|
||||
Timeout(None) # No timeouts.
|
||||
Timeout(5.0) # 5s timeout on all operations.
|
||||
Timeout(None, connect=5.0) # 5s timeout on connect, no other timeouts.
|
||||
Timeout(5.0, connect=10.0) # 10s timeout on connect. 5s timeout elsewhere.
|
||||
Timeout(5.0, pool=None) # No timeout on acquiring connection from pool.
|
||||
# 5s timeout elsewhere.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
timeout: typing.Union[TimeoutTypes, UnsetType] = UNSET,
|
||||
*,
|
||||
connect: typing.Union[None, float, UnsetType] = UNSET,
|
||||
read: typing.Union[None, float, UnsetType] = UNSET,
|
||||
write: typing.Union[None, float, UnsetType] = UNSET,
|
||||
pool: typing.Union[None, float, UnsetType] = UNSET,
|
||||
# Deprecated aliases.
|
||||
connect_timeout: typing.Union[None, float, UnsetType] = UNSET,
|
||||
read_timeout: typing.Union[None, float, UnsetType] = UNSET,
|
||||
write_timeout: typing.Union[None, float, UnsetType] = UNSET,
|
||||
pool_timeout: typing.Union[None, float, UnsetType] = UNSET,
|
||||
):
|
||||
if not isinstance(connect_timeout, UnsetType):
|
||||
warn_deprecated(
|
||||
"httpx.Timeout(..., connect_timeout=...) is deprecated and will "
|
||||
"raise errors in a future version. "
|
||||
"Use httpx.Timeout(..., connect=...) instead."
|
||||
)
|
||||
connect = connect_timeout
|
||||
|
||||
if not isinstance(read_timeout, UnsetType):
|
||||
warn_deprecated(
|
||||
"httpx.Timeout(..., read_timeout=...) is deprecated and will "
|
||||
"raise errors in a future version. "
|
||||
"Use httpx.Timeout(..., write=...) instead."
|
||||
)
|
||||
read = read_timeout
|
||||
|
||||
if not isinstance(write_timeout, UnsetType):
|
||||
warn_deprecated(
|
||||
"httpx.Timeout(..., write_timeout=...) is deprecated and will "
|
||||
"raise errors in a future version. "
|
||||
"Use httpx.Timeout(..., write=...) instead."
|
||||
)
|
||||
write = write_timeout
|
||||
|
||||
if not isinstance(pool_timeout, UnsetType):
|
||||
warn_deprecated(
|
||||
"httpx.Timeout(..., pool_timeout=...) is deprecated and will "
|
||||
"raise errors in a future version. "
|
||||
"Use httpx.Timeout(..., pool=...) instead."
|
||||
)
|
||||
pool = pool_timeout
|
||||
|
||||
if isinstance(timeout, Timeout):
|
||||
# Passed as a single explicit Timeout.
|
||||
assert connect_timeout is UNSET
|
||||
assert read_timeout is UNSET
|
||||
assert write_timeout is UNSET
|
||||
assert pool_timeout is UNSET
|
||||
self.connect_timeout = (
|
||||
timeout.connect_timeout
|
||||
) # type: typing.Optional[float]
|
||||
self.read_timeout = timeout.read_timeout # type: typing.Optional[float]
|
||||
self.write_timeout = timeout.write_timeout # type: typing.Optional[float]
|
||||
self.pool_timeout = timeout.pool_timeout # type: typing.Optional[float]
|
||||
assert connect is UNSET
|
||||
assert read is UNSET
|
||||
assert write is UNSET
|
||||
assert pool is UNSET
|
||||
self.connect = timeout.connect # type: typing.Optional[float]
|
||||
self.read = timeout.read # type: typing.Optional[float]
|
||||
self.write = timeout.write # type: typing.Optional[float]
|
||||
self.pool = timeout.pool # type: typing.Optional[float]
|
||||
elif isinstance(timeout, tuple):
|
||||
# Passed as a tuple.
|
||||
self.connect_timeout = timeout[0]
|
||||
self.read_timeout = timeout[1]
|
||||
self.write_timeout = None if len(timeout) < 3 else timeout[2]
|
||||
self.pool_timeout = None if len(timeout) < 4 else timeout[3]
|
||||
self.connect = timeout[0]
|
||||
self.read = timeout[1]
|
||||
self.write = None if len(timeout) < 3 else timeout[2]
|
||||
self.pool = None if len(timeout) < 4 else timeout[3]
|
||||
elif not (
|
||||
isinstance(connect_timeout, UnsetType)
|
||||
or isinstance(read_timeout, UnsetType)
|
||||
or isinstance(write_timeout, UnsetType)
|
||||
or isinstance(pool_timeout, UnsetType)
|
||||
isinstance(connect, UnsetType)
|
||||
or isinstance(read, UnsetType)
|
||||
or isinstance(write, UnsetType)
|
||||
or isinstance(pool, UnsetType)
|
||||
):
|
||||
self.connect_timeout = connect_timeout
|
||||
self.read_timeout = read_timeout
|
||||
self.write_timeout = write_timeout
|
||||
self.pool_timeout = pool_timeout
|
||||
self.connect = connect
|
||||
self.read = read
|
||||
self.write = write
|
||||
self.pool = pool
|
||||
else:
|
||||
if isinstance(timeout, UnsetType):
|
||||
warnings.warn(
|
||||
@ -250,54 +285,35 @@ class Timeout:
|
||||
DeprecationWarning,
|
||||
)
|
||||
timeout = None
|
||||
self.connect_timeout = (
|
||||
timeout if isinstance(connect_timeout, UnsetType) else connect_timeout
|
||||
)
|
||||
self.read_timeout = (
|
||||
timeout if isinstance(read_timeout, UnsetType) else read_timeout
|
||||
)
|
||||
self.write_timeout = (
|
||||
timeout if isinstance(write_timeout, UnsetType) else write_timeout
|
||||
)
|
||||
self.pool_timeout = (
|
||||
timeout if isinstance(pool_timeout, UnsetType) else pool_timeout
|
||||
)
|
||||
self.connect = timeout if isinstance(connect, UnsetType) else connect
|
||||
self.read = timeout if isinstance(read, UnsetType) else read
|
||||
self.write = timeout if isinstance(write, UnsetType) else write
|
||||
self.pool = timeout if isinstance(pool, UnsetType) else pool
|
||||
|
||||
def as_dict(self) -> typing.Dict[str, typing.Optional[float]]:
|
||||
return {
|
||||
"connect": self.connect_timeout,
|
||||
"read": self.read_timeout,
|
||||
"write": self.write_timeout,
|
||||
"pool": self.pool_timeout,
|
||||
"connect": self.connect,
|
||||
"read": self.read,
|
||||
"write": self.write,
|
||||
"pool": self.pool,
|
||||
}
|
||||
|
||||
def __eq__(self, other: typing.Any) -> bool:
|
||||
return (
|
||||
isinstance(other, self.__class__)
|
||||
and self.connect_timeout == other.connect_timeout
|
||||
and self.read_timeout == other.read_timeout
|
||||
and self.write_timeout == other.write_timeout
|
||||
and self.pool_timeout == other.pool_timeout
|
||||
and self.connect == other.connect
|
||||
and self.read == other.read
|
||||
and self.write == other.write
|
||||
and self.pool == other.pool
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
class_name = self.__class__.__name__
|
||||
if (
|
||||
len(
|
||||
{
|
||||
self.connect_timeout,
|
||||
self.read_timeout,
|
||||
self.write_timeout,
|
||||
self.pool_timeout,
|
||||
}
|
||||
)
|
||||
== 1
|
||||
):
|
||||
return f"{class_name}(timeout={self.connect_timeout})"
|
||||
if len({self.connect, self.read, self.write, self.pool}) == 1:
|
||||
return f"{class_name}(timeout={self.connect})"
|
||||
return (
|
||||
f"{class_name}(connect_timeout={self.connect_timeout}, "
|
||||
f"read_timeout={self.read_timeout}, write_timeout={self.write_timeout}, "
|
||||
f"pool_timeout={self.pool_timeout})"
|
||||
f"{class_name}(connect={self.connect}, "
|
||||
f"read={self.read}, write={self.write}, pool={self.pool})"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -116,18 +116,16 @@ def test_timeout_eq():
|
||||
|
||||
|
||||
def test_timeout_all_parameters_set():
|
||||
timeout = httpx.Timeout(
|
||||
connect_timeout=5.0, read_timeout=5.0, write_timeout=5.0, pool_timeout=5.0
|
||||
)
|
||||
timeout = httpx.Timeout(connect=5.0, read=5.0, write=5.0, pool=5.0)
|
||||
assert timeout == httpx.Timeout(timeout=5.0)
|
||||
|
||||
|
||||
def test_timeout_from_nothing():
|
||||
timeout = httpx.Timeout(None)
|
||||
assert timeout.connect_timeout is None
|
||||
assert timeout.read_timeout is None
|
||||
assert timeout.write_timeout is None
|
||||
assert timeout.pool_timeout is None
|
||||
assert timeout.connect is None
|
||||
assert timeout.read is None
|
||||
assert timeout.write is None
|
||||
assert timeout.pool is None
|
||||
|
||||
|
||||
def test_timeout_from_none():
|
||||
@ -136,23 +134,23 @@ def test_timeout_from_none():
|
||||
|
||||
|
||||
def test_timeout_from_one_none_value():
|
||||
timeout = httpx.Timeout(None, read_timeout=None)
|
||||
timeout = httpx.Timeout(None, read=None)
|
||||
assert timeout == httpx.Timeout(None)
|
||||
|
||||
|
||||
def test_timeout_from_one_value():
|
||||
timeout = httpx.Timeout(None, read_timeout=5.0)
|
||||
timeout = httpx.Timeout(None, read=5.0)
|
||||
assert timeout == httpx.Timeout(timeout=(None, 5.0, None, None))
|
||||
|
||||
|
||||
def test_timeout_from_one_value_and_default():
|
||||
timeout = httpx.Timeout(5.0, pool_timeout=60.0)
|
||||
timeout = httpx.Timeout(5.0, pool=60.0)
|
||||
assert timeout == httpx.Timeout(timeout=(5.0, 5.0, 5.0, 60.0))
|
||||
|
||||
|
||||
def test_timeout_missing_default():
|
||||
with pytest.warns(DeprecationWarning):
|
||||
timeout = httpx.Timeout(pool_timeout=60.0)
|
||||
timeout = httpx.Timeout(pool=60.0)
|
||||
assert timeout == httpx.Timeout(timeout=(None, None, None, 60.0))
|
||||
|
||||
|
||||
@ -170,11 +168,8 @@ def test_timeout_repr():
|
||||
timeout = httpx.Timeout(timeout=5.0)
|
||||
assert repr(timeout) == "Timeout(timeout=5.0)"
|
||||
|
||||
timeout = httpx.Timeout(None, read_timeout=5.0)
|
||||
assert repr(timeout) == (
|
||||
"Timeout(connect_timeout=None, read_timeout=5.0, "
|
||||
"write_timeout=None, pool_timeout=None)"
|
||||
)
|
||||
timeout = httpx.Timeout(None, read=5.0)
|
||||
assert repr(timeout) == "Timeout(connect=None, read=5.0, write=None, pool=None)"
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
|
||||
@ -5,7 +5,7 @@ import httpx
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_read_timeout(server):
|
||||
timeout = httpx.Timeout(None, read_timeout=1e-6)
|
||||
timeout = httpx.Timeout(None, read=1e-6)
|
||||
|
||||
async with httpx.AsyncClient(timeout=timeout) as client:
|
||||
with pytest.raises(httpx.ReadTimeout):
|
||||
@ -14,7 +14,7 @@ async def test_read_timeout(server):
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_write_timeout(server):
|
||||
timeout = httpx.Timeout(None, write_timeout=1e-6)
|
||||
timeout = httpx.Timeout(None, write=1e-6)
|
||||
|
||||
async with httpx.AsyncClient(timeout=timeout) as client:
|
||||
with pytest.raises(httpx.WriteTimeout):
|
||||
@ -24,7 +24,7 @@ async def test_write_timeout(server):
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_connect_timeout(server):
|
||||
timeout = httpx.Timeout(None, connect_timeout=1e-6)
|
||||
timeout = httpx.Timeout(None, connect=1e-6)
|
||||
|
||||
async with httpx.AsyncClient(timeout=timeout) as client:
|
||||
with pytest.raises(httpx.ConnectTimeout):
|
||||
@ -35,9 +35,23 @@ async def test_connect_timeout(server):
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_pool_timeout(server):
|
||||
pool_limits = httpx.PoolLimits(max_connections=1)
|
||||
timeout = httpx.Timeout(None, pool_timeout=1e-4)
|
||||
timeout = httpx.Timeout(None, pool=1e-4)
|
||||
|
||||
async with httpx.AsyncClient(pool_limits=pool_limits, timeout=timeout) as client:
|
||||
async with client.stream("GET", server.url):
|
||||
with pytest.raises(httpx.PoolTimeout):
|
||||
await client.get("http://localhost:8000/")
|
||||
|
||||
|
||||
def test_deprecated_verbose_timeout_params():
|
||||
with pytest.warns(DeprecationWarning):
|
||||
httpx.Timeout(None, read_timeout=1.0)
|
||||
|
||||
with pytest.warns(DeprecationWarning):
|
||||
httpx.Timeout(None, write_timeout=1.0)
|
||||
|
||||
with pytest.warns(DeprecationWarning):
|
||||
httpx.Timeout(None, connect_timeout=1.0)
|
||||
|
||||
with pytest.warns(DeprecationWarning):
|
||||
httpx.Timeout(None, pool_timeout=1.0)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user