Compare commits

...

15 Commits

Author SHA1 Message Date
Tom Christie
7c10773193
Merge branch 'master' into async-dependencies-optional 2024-09-27 17:07:44 +01:00
Tom Christie
85886d7d43
Update README.md 2024-09-27 17:05:51 +01:00
Tom Christie
6a4ea7a1fe
Update README.md 2024-09-27 17:04:54 +01:00
Tom Christie
4e58ae69e9
Merge branch 'master' into async-dependencies-optional 2024-09-27 13:00:30 +01:00
Tom Christie
3ebb3a5b9b
Update docs/http2.md
Co-authored-by: T-256 <132141463+T-256@users.noreply.github.com>
2024-09-27 09:48:50 +01:00
Tom Christie
88d9324081
Update docs/async.md
Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-01-15 16:57:22 +00:00
Tom Christie
0e34e2ce25
Merge branch 'master' into async-dependencies-optional 2024-01-11 13:02:27 +00:00
Tom Christie
aa9ca07104
Merge branch 'master' into async-dependencies-optional 2024-01-08 14:12:29 +00:00
Tom Christie
9b36a208b3
Update httpx/_transports/default.py 2023-12-28 20:35:16 +00:00
Tom Christie
3741513647
Merge branch 'master' into async-dependencies-optional 2023-12-28 14:21:57 +00:00
Kar Petrosyan
e4e8fb2d71
Merge branch 'master' into async-dependencies-optional 2023-10-25 06:31:19 -04:00
Tom Christie
56b2fb0533
Update README.md
Co-authored-by: T-256 <132141463+T-256@users.noreply.github.com>
2023-10-12 10:42:02 +01:00
Tom Christie
40aa60c2c6
Merge branch 'master' into async-dependencies-optional 2023-10-10 13:43:40 +01:00
Tom Christie
f4dd500f0e Fix dependency formatting 2023-09-20 10:10:12 +01:00
Tom Christie
0dd72fce4a Make async dependencies optional. 2023-09-20 09:46:39 +01:00
8 changed files with 54 additions and 34 deletions

View File

@ -97,10 +97,12 @@ Install with pip:
$ pip install httpx $ pip install httpx
``` ```
Or, to include the optional HTTP/2 support, use: There are also a number of optional dependancies.
For example to include asyncio and HTTP/2 support, use:
```shell ```shell
$ pip install httpx[http2] $ pip install 'httpx[asyncio,http2]'
``` ```
HTTPX requires Python 3.8+. HTTPX requires Python 3.8+.
@ -129,15 +131,17 @@ The HTTPX project relies on these excellent libraries:
* `h11` - HTTP/1.1 support. * `h11` - HTTP/1.1 support.
* `certifi` - SSL certificates. * `certifi` - SSL certificates.
* `idna` - Internationalized domain name support. * `idna` - Internationalized domain name support.
* `sniffio` - Async library autodetection.
As well as these optional installs: As well as these optional installs:
* `h2` - HTTP/2 support. *(Optional, with `httpx[http2]`)* * `anyio` - Async support for `asyncio`. *(Optional, with `httpx['asyncio']`)*
* `socksio` - SOCKS proxy support. *(Optional, with `httpx[socks]`)* * `trio` - Async support for `trio`. *(Optional, with `httpx['trio']`)*
* `rich` - Rich terminal support. *(Optional, with `httpx[cli]`)* * `h2` - HTTP/2 support. *(Optional, with `httpx['http2']`)*
* `click` - Command line client support. *(Optional, with `httpx[cli]`)* * `socksio` - SOCKS proxy support. *(Optional, with `httpx['socks']`)*
* `brotli` or `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional, with `httpx[brotli]`)* * `click` - Command line client support. *(Optional, with `httpx['cli']`)*
* `rich` - Command line client support. *(Optional, with `httpx['cli']`)*
* `pygments` - Command line client support. *(Optional, with `httpx['cli']`)*
* `brotli` or `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional, with `httpx['brotli']`)*
* `zstandard` - Decoding for "zstd" compressed responses. *(Optional, with `httpx[zstd]`)* * `zstandard` - Decoding for "zstd" compressed responses. *(Optional, with `httpx[zstd]`)*
A huge amount of credit is due to `requests` for the API layout that A huge amount of credit is due to `requests` for the API layout that

View File

@ -10,6 +10,24 @@ long-lived network connections such as WebSockets.
If you're working with an async web framework then you'll also want to use an If you're working with an async web framework then you'll also want to use an
async client for sending outgoing HTTP requests. async client for sending outgoing HTTP requests.
## Enabling Async support
To enable async support you'll need to install some additional dependencies:
If you're using Python's [standard `asyncio` support](https://docs.python.org/3/library/asyncio.html) then:
```shell
$ pip install "httpx[asyncio]"
```
Or, if you're working with the [`trio` third party package](https://trio.readthedocs.io/en/stable/):
```shell
$ pip install httpx['trio']
```
We highly recommend `trio` for async support. The `trio` project [pioneered the principles of structured concurrency](https://en.wikipedia.org/wiki/Structured_concurrency), and has a more carefully constrained API against which to work from.
## Making Async requests ## Making Async requests
To make asynchronous requests, you'll need an `AsyncClient`. To make asynchronous requests, you'll need an `AsyncClient`.

View File

@ -28,7 +28,7 @@ trying out our HTTP/2 support. You can do so by first making sure to install
the optional HTTP/2 dependencies... the optional HTTP/2 dependencies...
```shell ```shell
$ pip install httpx[http2] $ pip install 'httpx[http2]'
``` ```
And then instantiating a client with HTTP/2 support enabled: And then instantiating a client with HTTP/2 support enabled:

View File

@ -2,8 +2,6 @@ from __future__ import annotations
import typing import typing
import sniffio
from .._models import Request, Response from .._models import Request, Response
from .._types import AsyncByteStream from .._types import AsyncByteStream
from .base import AsyncBaseTransport from .base import AsyncBaseTransport
@ -28,7 +26,9 @@ _ASGIApp = typing.Callable[
__all__ = ["ASGITransport"] __all__ = ["ASGITransport"]
def create_event() -> Event: def create_event() -> "Event":
import sniffio
if sniffio.current_async_library() == "trio": if sniffio.current_async_library() == "trio":
import trio import trio

View File

@ -277,6 +277,14 @@ class AsyncHTTPTransport(AsyncBaseTransport):
retries: int = 0, retries: int = 0,
socket_options: typing.Iterable[SOCKET_OPTION] | None = None, socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
) -> None: ) -> None:
try:
import sniffio # noqa: F401
except ImportError: # pragma: nocover
raise RuntimeError(
"Using httpx in async mode, but neither "
"httpx['asyncio'] or asyncio['trio'] is installed."
)
ssl_context = create_ssl_context(verify=verify, cert=cert, trust_env=trust_env) ssl_context = create_ssl_context(verify=verify, cert=cert, trust_env=trust_env)
proxy = Proxy(url=proxy) if isinstance(proxy, (str, URL)) else proxy proxy = Proxy(url=proxy) if isinstance(proxy, (str, URL)) else proxy

View File

@ -11,8 +11,6 @@ import typing
from pathlib import Path from pathlib import Path
from urllib.request import getproxies from urllib.request import getproxies
import sniffio
from ._types import PrimitiveData from ._types import PrimitiveData
if typing.TYPE_CHECKING: # pragma: no cover if typing.TYPE_CHECKING: # pragma: no cover
@ -291,29 +289,18 @@ def peek_filelike_length(stream: typing.Any) -> int | None:
class Timer: class Timer:
async def _get_time(self) -> float:
library = sniffio.current_async_library()
if library == "trio":
import trio
return trio.current_time()
else:
import asyncio
return asyncio.get_event_loop().time()
def sync_start(self) -> None: def sync_start(self) -> None:
self.started = time.perf_counter() self.started = time.perf_counter()
async def async_start(self) -> None: async def async_start(self) -> None:
self.started = await self._get_time() self.started = time.perf_counter()
def sync_elapsed(self) -> float: def sync_elapsed(self) -> float:
now = time.perf_counter() now = time.perf_counter()
return now - self.started return now - self.started
async def async_elapsed(self) -> float: async def async_elapsed(self) -> float:
now = await self._get_time() now = time.perf_counter()
return now - self.started return now - self.started

View File

@ -29,10 +29,8 @@ classifiers = [
] ]
dependencies = [ dependencies = [
"certifi", "certifi",
"httpcore==1.*", "httpcore>=1.0.0,<2.0.0",
"anyio",
"idna", "idna",
"sniffio",
] ]
dynamic = ["readme", "version"] dynamic = ["readme", "version"]
@ -47,10 +45,16 @@ cli = [
"rich>=10,<14", "rich>=10,<14",
] ]
http2 = [ http2 = [
"h2>=3,<5", "httpcore[http2]",
] ]
socks = [ socks = [
"socksio==1.*", "httpcore[socks]",
]
asyncio = [
"httpcore[asyncio]"
]
trio = [
"httpcore[trio]"
] ]
zstd = [ zstd = [
"zstandard>=0.18.0", "zstandard>=0.18.0",

View File

@ -2,7 +2,7 @@
# On the other hand, we're not pinning package dependencies, because our tests # On the other hand, we're not pinning package dependencies, because our tests
# needs to pass with the latest version of the packages. # needs to pass with the latest version of the packages.
# Reference: https://github.com/encode/httpx/pull/1721#discussion_r661241588 # Reference: https://github.com/encode/httpx/pull/1721#discussion_r661241588
-e .[brotli,cli,http2,socks,zstd] -e .[asyncio,trio,brotli,cli,http2,socks,zstd]
# Optional charset auto-detection # Optional charset auto-detection
# Used in our test cases # Used in our test cases
@ -24,6 +24,5 @@ mypy==1.11.2
pytest==8.3.2 pytest==8.3.2
ruff==0.6.3 ruff==0.6.3
trio==0.26.2 trio==0.26.2
trio-typing==0.10.0
trustme==1.1.0 trustme==1.1.0
uvicorn==0.30.6 uvicorn==0.30.6