Merge branch 'master' into feature/allow-multipart-without-files
This commit is contained in:
commit
4bb86a4e60
2
.github/workflows/test-suite.yml
vendored
2
.github/workflows/test-suite.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
|
||||
|
||||
steps:
|
||||
- uses: "actions/checkout@v4"
|
||||
|
||||
@ -4,13 +4,15 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## Dev
|
||||
## 0.28.1 (6th December, 2024)
|
||||
|
||||
* Fix SSL case where `verify=False` together with client side certificates.
|
||||
|
||||
## 0.28.0 (28th November, 2024)
|
||||
|
||||
The 0.28 release includes a limited set of deprecations.
|
||||
Be aware that the default *JSON request bodies now use a more compact representation*. This is generally considered a prefered style, tho may require updates to test suites.
|
||||
|
||||
The 0.28 release includes a limited set of deprecations...
|
||||
|
||||
**Deprecations**:
|
||||
|
||||
|
||||
@ -270,8 +270,9 @@ multipart file encoding is available by passing a dictionary with the
|
||||
name of the payloads as keys and either tuple of elements or a file-like object or a string as values.
|
||||
|
||||
```pycon
|
||||
>>> files = {'upload-file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel')}
|
||||
>>> r = httpx.post("https://httpbin.org/post", files=files)
|
||||
>>> with open('report.xls', 'rb') as report_file:
|
||||
... files = {'upload-file': ('report.xls', report_file, 'application/vnd.ms-excel')}
|
||||
... r = httpx.post("https://httpbin.org/post", files=files)
|
||||
>>> print(r.text)
|
||||
{
|
||||
...
|
||||
@ -318,7 +319,10 @@ To do that, pass a list of `(field, <file>)` items instead of a dictionary, allo
|
||||
For instance this request sends 2 files, `foo.png` and `bar.png` in one request on the `images` form field:
|
||||
|
||||
```pycon
|
||||
>>> files = [('images', ('foo.png', open('foo.png', 'rb'), 'image/png')),
|
||||
('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))]
|
||||
>>> r = httpx.post("https://httpbin.org/post", files=files)
|
||||
>>> with open('foo.png', 'rb') as foo_file, open('bar.png', 'rb') as bar_file:
|
||||
... files = [
|
||||
... ('images', ('foo.png', foo_file, 'image/png')),
|
||||
... ('images', ('bar.png', bar_file, 'image/png')),
|
||||
... ]
|
||||
... r = httpx.post("https://httpbin.org/post", files=files)
|
||||
```
|
||||
|
||||
15
docs/api.md
15
docs/api.md
@ -159,3 +159,18 @@ what gets sent over the wire.*
|
||||
* `def delete(name, [domain], [path])`
|
||||
* `def clear([domain], [path])`
|
||||
* *Standard mutable mapping interface*
|
||||
|
||||
## `Proxy`
|
||||
|
||||
*A configuration of the proxy server.*
|
||||
|
||||
```pycon
|
||||
>>> proxy = Proxy("http://proxy.example.com:8030")
|
||||
>>> client = Client(proxy=proxy)
|
||||
```
|
||||
|
||||
* `def __init__(url, [ssl_context], [auth], [headers])`
|
||||
* `.url` - **URL**
|
||||
* `.auth` - **tuple[str, str]**
|
||||
* `.headers` - **Headers**
|
||||
* `.ssl_context` - **SSLContext**
|
||||
|
||||
@ -174,8 +174,9 @@ Form encoded data can also include multiple values from a given key.
|
||||
You can also upload files, using HTTP multipart encoding:
|
||||
|
||||
```pycon
|
||||
>>> files = {'upload-file': open('report.xls', 'rb')}
|
||||
>>> r = httpx.post("https://httpbin.org/post", files=files)
|
||||
>>> with open('report.xls', 'rb') as report_file:
|
||||
... files = {'upload-file': report_file}
|
||||
... r = httpx.post("https://httpbin.org/post", files=files)
|
||||
>>> print(r.text)
|
||||
{
|
||||
...
|
||||
@ -190,8 +191,9 @@ You can also explicitly set the filename and content type, by using a tuple
|
||||
of items for the file value:
|
||||
|
||||
```pycon
|
||||
>>> files = {'upload-file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel')}
|
||||
>>> r = httpx.post("https://httpbin.org/post", files=files)
|
||||
>>> with open('report.xls', 'rb') report_file:
|
||||
... files = {'upload-file': ('report.xls', report_file, 'application/vnd.ms-excel')}
|
||||
... r = httpx.post("https://httpbin.org/post", files=files)
|
||||
>>> print(r.text)
|
||||
{
|
||||
...
|
||||
@ -206,8 +208,9 @@ If you need to include non-file data fields in the multipart form, use the `data
|
||||
|
||||
```pycon
|
||||
>>> data = {'message': 'Hello, world!'}
|
||||
>>> files = {'file': open('report.xls', 'rb')}
|
||||
>>> r = httpx.post("https://httpbin.org/post", data=data, files=files)
|
||||
>>> with open('report.xls', 'rb') as report_file:
|
||||
... files = {'file': report_file}
|
||||
... r = httpx.post("https://httpbin.org/post", data=data, files=files)
|
||||
>>> print(r.text)
|
||||
{
|
||||
...
|
||||
|
||||
@ -2,67 +2,21 @@
|
||||
|
||||
As HTTPX usage grows, there is an expanding community of developers building tools and libraries that integrate with HTTPX, or depend on HTTPX. Here are some of them.
|
||||
|
||||
<!-- NOTE: Entries are alphabetised. -->
|
||||
|
||||
## Plugins
|
||||
|
||||
### httpx-ws
|
||||
|
||||
[GitHub](https://github.com/frankie567/httpx-ws) - [Documentation](https://frankie567.github.io/httpx-ws/)
|
||||
|
||||
WebSocket support for HTTPX.
|
||||
|
||||
### httpx-socks
|
||||
|
||||
[GitHub](https://github.com/romis2012/httpx-socks)
|
||||
|
||||
Proxy (HTTP, SOCKS) transports for httpx.
|
||||
|
||||
### Hishel
|
||||
|
||||
[GitHub](https://github.com/karpetrosyan/hishel) - [Documentation](https://hishel.com/)
|
||||
|
||||
An elegant HTTP Cache implementation for HTTPX and HTTP Core.
|
||||
|
||||
### Authlib
|
||||
|
||||
[GitHub](https://github.com/lepture/authlib) - [Documentation](https://docs.authlib.org/en/latest/)
|
||||
|
||||
The ultimate Python library in building OAuth and OpenID Connect clients and servers. Includes an [OAuth HTTPX client](https://docs.authlib.org/en/latest/client/httpx.html).
|
||||
|
||||
### Gidgethub
|
||||
|
||||
[GitHub](https://github.com/brettcannon/gidgethub) - [Documentation](https://gidgethub.readthedocs.io/en/latest/index.html)
|
||||
|
||||
An asynchronous GitHub API library. Includes [HTTPX support](https://gidgethub.readthedocs.io/en/latest/httpx.html).
|
||||
|
||||
### HTTPX-Auth
|
||||
|
||||
[GitHub](https://github.com/Colin-b/httpx_auth) - [Documentation](https://colin-b.github.io/httpx_auth/)
|
||||
|
||||
Provides authentication classes to be used with HTTPX [authentication parameter](advanced/authentication.md#customizing-authentication).
|
||||
|
||||
### pytest-HTTPX
|
||||
|
||||
[GitHub](https://github.com/Colin-b/pytest_httpx) - [Documentation](https://colin-b.github.io/pytest_httpx/)
|
||||
|
||||
Provides `httpx_mock` [pytest](https://docs.pytest.org/en/latest/) fixture to mock HTTPX within test cases.
|
||||
|
||||
### RESPX
|
||||
|
||||
[GitHub](https://github.com/lundberg/respx) - [Documentation](https://lundberg.github.io/respx/)
|
||||
|
||||
A utility for mocking out the Python HTTPX library.
|
||||
|
||||
### rpc.py
|
||||
|
||||
[Github](https://github.com/abersheeran/rpc.py) - [Documentation](https://github.com/abersheeran/rpc.py#rpcpy)
|
||||
|
||||
An fast and powerful RPC framework based on ASGI/WSGI. Use HTTPX as the client of the RPC service.
|
||||
|
||||
### VCR.py
|
||||
|
||||
[GitHub](https://github.com/kevin1024/vcrpy) - [Documentation](https://vcrpy.readthedocs.io/)
|
||||
|
||||
A utility for record and repeat an http request.
|
||||
Provides authentication classes to be used with HTTPX's [authentication parameter](advanced/authentication.md#customizing-authentication).
|
||||
|
||||
### httpx-caching
|
||||
|
||||
@ -70,22 +24,76 @@ A utility for record and repeat an http request.
|
||||
|
||||
This package adds caching functionality to HTTPX
|
||||
|
||||
### httpx-socks
|
||||
|
||||
[GitHub](https://github.com/romis2012/httpx-socks)
|
||||
|
||||
Proxy (HTTP, SOCKS) transports for httpx.
|
||||
|
||||
### httpx-sse
|
||||
|
||||
[GitHub](https://github.com/florimondmanca/httpx-sse)
|
||||
|
||||
Allows consuming Server-Sent Events (SSE) with HTTPX.
|
||||
|
||||
### robox
|
||||
### httpx-retries
|
||||
|
||||
[Github](https://github.com/danclaudiupop/robox)
|
||||
[GitHub](https://github.com/will-ockmore/httpx-retries) - [Documentation](https://will-ockmore.github.io/httpx-retries/)
|
||||
|
||||
A library for scraping the web built on top of HTTPX.
|
||||
A retry layer for HTTPX.
|
||||
|
||||
### httpx-ws
|
||||
|
||||
[GitHub](https://github.com/frankie567/httpx-ws) - [Documentation](https://frankie567.github.io/httpx-ws/)
|
||||
|
||||
WebSocket support for HTTPX.
|
||||
|
||||
### pytest-HTTPX
|
||||
|
||||
[GitHub](https://github.com/Colin-b/pytest_httpx) - [Documentation](https://colin-b.github.io/pytest_httpx/)
|
||||
|
||||
Provides a [pytest](https://docs.pytest.org/en/latest/) fixture to mock HTTPX within test cases.
|
||||
|
||||
### RESPX
|
||||
|
||||
[GitHub](https://github.com/lundberg/respx) - [Documentation](https://lundberg.github.io/respx/)
|
||||
|
||||
A utility for mocking out HTTPX.
|
||||
|
||||
### rpc.py
|
||||
|
||||
[Github](https://github.com/abersheeran/rpc.py) - [Documentation](https://github.com/abersheeran/rpc.py#rpcpy)
|
||||
|
||||
A fast and powerful RPC framework based on ASGI/WSGI. Use HTTPX as the client of the RPC service.
|
||||
|
||||
## Libraries with HTTPX support
|
||||
|
||||
### Authlib
|
||||
|
||||
[GitHub](https://github.com/lepture/authlib) - [Documentation](https://docs.authlib.org/en/latest/)
|
||||
|
||||
A python library for building OAuth and OpenID Connect clients and servers. Includes an [OAuth HTTPX client](https://docs.authlib.org/en/latest/client/httpx.html).
|
||||
|
||||
### Gidgethub
|
||||
|
||||
[GitHub](https://github.com/brettcannon/gidgethub) - [Documentation](https://gidgethub.readthedocs.io/en/latest/index.html)
|
||||
|
||||
An asynchronous GitHub API library. Includes [HTTPX support](https://gidgethub.readthedocs.io/en/latest/httpx.html).
|
||||
|
||||
### httpdbg
|
||||
|
||||
[GitHub](https://github.com/cle-b/httpdbg) - [Documentation](https://httpdbg.readthedocs.io/)
|
||||
|
||||
A tool for python developers to easily debug the HTTP(S) client requests in a python program.
|
||||
|
||||
### VCR.py
|
||||
|
||||
[GitHub](https://github.com/kevin1024/vcrpy) - [Documentation](https://vcrpy.readthedocs.io/)
|
||||
|
||||
Record and repeat requests.
|
||||
|
||||
## Gists
|
||||
|
||||
<!-- NOTE: this list is in alphabetical order. -->
|
||||
|
||||
### urllib3-transport
|
||||
|
||||
[GitHub](https://gist.github.com/florimondmanca/d56764d78d748eb9f73165da388e546e)
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
__title__ = "httpx"
|
||||
__description__ = "A next generation HTTP client, for Python 3."
|
||||
__version__ = "0.28.0"
|
||||
__version__ = "0.28.1"
|
||||
|
||||
@ -1723,7 +1723,7 @@ class AsyncClient(BaseClient):
|
||||
|
||||
if not isinstance(request.stream, AsyncByteStream):
|
||||
raise RuntimeError(
|
||||
"Attempted to send an sync request with an AsyncClient instance."
|
||||
"Attempted to send a sync request with an AsyncClient instance."
|
||||
)
|
||||
|
||||
with request_context(request=request):
|
||||
|
||||
@ -964,7 +964,7 @@ class Response:
|
||||
Automatically called if the response body is read to completion.
|
||||
"""
|
||||
if not isinstance(self.stream, SyncByteStream):
|
||||
raise RuntimeError("Attempted to call an sync close on an async stream.")
|
||||
raise RuntimeError("Attempted to call a sync close on an async stream.")
|
||||
|
||||
if not self.is_closed:
|
||||
self.is_closed = True
|
||||
@ -1045,7 +1045,7 @@ class Response:
|
||||
if self.is_closed:
|
||||
raise StreamClosed()
|
||||
if not isinstance(self.stream, AsyncByteStream):
|
||||
raise RuntimeError("Attempted to call an async iterator on an sync stream.")
|
||||
raise RuntimeError("Attempted to call an async iterator on a sync stream.")
|
||||
|
||||
self.is_stream_consumed = True
|
||||
self._num_bytes_downloaded = 0
|
||||
@ -1068,7 +1068,7 @@ class Response:
|
||||
Automatically called if the response body is read to completion.
|
||||
"""
|
||||
if not isinstance(self.stream, AsyncByteStream):
|
||||
raise RuntimeError("Attempted to call an async close on an sync stream.")
|
||||
raise RuntimeError("Attempted to call an async close on a sync stream.")
|
||||
|
||||
if not self.is_closed:
|
||||
self.is_closed = True
|
||||
|
||||
@ -355,7 +355,7 @@ class AsyncHTTPTransport(AsyncBaseTransport):
|
||||
else: # pragma: no cover
|
||||
raise ValueError(
|
||||
"Proxy protocol must be either 'http', 'https', 'socks5', or 'socks5h',"
|
||||
" but got {proxy.url.scheme!r}."
|
||||
f" but got {proxy.url.scheme!r}."
|
||||
)
|
||||
|
||||
async def __aenter__(self: A) -> A: # Use generics for subclass support.
|
||||
|
||||
@ -25,6 +25,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
]
|
||||
dependencies = [
|
||||
|
||||
@ -19,7 +19,7 @@ twine==6.0.1
|
||||
|
||||
# Tests & Linting
|
||||
coverage[toml]==7.6.1
|
||||
cryptography==44.0.0
|
||||
cryptography==44.0.1
|
||||
mypy==1.13.0
|
||||
pytest==8.3.4
|
||||
ruff==0.8.1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user