Compare commits
15 Commits
master
...
async-depe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c10773193 | ||
|
|
85886d7d43 | ||
|
|
6a4ea7a1fe | ||
|
|
4e58ae69e9 | ||
|
|
3ebb3a5b9b | ||
|
|
88d9324081 | ||
|
|
0e34e2ce25 | ||
|
|
aa9ca07104 | ||
|
|
9b36a208b3 | ||
|
|
3741513647 | ||
|
|
e4e8fb2d71 | ||
|
|
56b2fb0533 | ||
|
|
40aa60c2c6 | ||
|
|
f4dd500f0e | ||
|
|
0dd72fce4a |
20
README.md
20
README.md
@ -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
|
||||||
|
|||||||
@ -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`.
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user