Skip to content

Commit 4bb86a4

Browse files
authored
Merge branch 'master' into feature/allow-multipart-without-files
2 parents d543147 + 336204f commit 4bb86a4

12 files changed

Lines changed: 89 additions & 56 deletions

File tree

.github/workflows/test-suite.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414

1515
strategy:
1616
matrix:
17-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
17+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
1818

1919
steps:
2020
- uses: "actions/checkout@v4"

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

7-
## Dev
7+
## 0.28.1 (6th December, 2024)
88

99
* Fix SSL case where `verify=False` together with client side certificates.
1010

1111
## 0.28.0 (28th November, 2024)
1212

13-
The 0.28 release includes a limited set of deprecations.
13+
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.
14+
15+
The 0.28 release includes a limited set of deprecations...
1416

1517
**Deprecations**:
1618

docs/advanced/clients.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,9 @@ multipart file encoding is available by passing a dictionary with the
270270
name of the payloads as keys and either tuple of elements or a file-like object or a string as values.
271271

272272
```pycon
273-
>>> files = {'upload-file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel')}
274-
>>> r = httpx.post("https://httpbin.org/post", files=files)
273+
>>> with open('report.xls', 'rb') as report_file:
274+
... files = {'upload-file': ('report.xls', report_file, 'application/vnd.ms-excel')}
275+
... r = httpx.post("https://httpbin.org/post", files=files)
275276
>>> print(r.text)
276277
{
277278
...
@@ -318,7 +319,10 @@ To do that, pass a list of `(field, <file>)` items instead of a dictionary, allo
318319
For instance this request sends 2 files, `foo.png` and `bar.png` in one request on the `images` form field:
319320

320321
```pycon
321-
>>> files = [('images', ('foo.png', open('foo.png', 'rb'), 'image/png')),
322-
('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))]
323-
>>> r = httpx.post("https://httpbin.org/post", files=files)
322+
>>> with open('foo.png', 'rb') as foo_file, open('bar.png', 'rb') as bar_file:
323+
... files = [
324+
... ('images', ('foo.png', foo_file, 'image/png')),
325+
... ('images', ('bar.png', bar_file, 'image/png')),
326+
... ]
327+
... r = httpx.post("https://httpbin.org/post", files=files)
324328
```

docs/api.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,18 @@ what gets sent over the wire.*
159159
* `def delete(name, [domain], [path])`
160160
* `def clear([domain], [path])`
161161
* *Standard mutable mapping interface*
162+
163+
## `Proxy`
164+
165+
*A configuration of the proxy server.*
166+
167+
```pycon
168+
>>> proxy = Proxy("http://proxy.example.com:8030")
169+
>>> client = Client(proxy=proxy)
170+
```
171+
172+
* `def __init__(url, [ssl_context], [auth], [headers])`
173+
* `.url` - **URL**
174+
* `.auth` - **tuple[str, str]**
175+
* `.headers` - **Headers**
176+
* `.ssl_context` - **SSLContext**

docs/quickstart.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,9 @@ Form encoded data can also include multiple values from a given key.
174174
You can also upload files, using HTTP multipart encoding:
175175

176176
```pycon
177-
>>> files = {'upload-file': open('report.xls', 'rb')}
178-
>>> r = httpx.post("https://httpbin.org/post", files=files)
177+
>>> with open('report.xls', 'rb') as report_file:
178+
... files = {'upload-file': report_file}
179+
... r = httpx.post("https://httpbin.org/post", files=files)
179180
>>> print(r.text)
180181
{
181182
...
@@ -190,8 +191,9 @@ You can also explicitly set the filename and content type, by using a tuple
190191
of items for the file value:
191192

192193
```pycon
193-
>>> files = {'upload-file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel')}
194-
>>> r = httpx.post("https://httpbin.org/post", files=files)
194+
>>> with open('report.xls', 'rb') report_file:
195+
... files = {'upload-file': ('report.xls', report_file, 'application/vnd.ms-excel')}
196+
... r = httpx.post("https://httpbin.org/post", files=files)
195197
>>> print(r.text)
196198
{
197199
...
@@ -206,8 +208,9 @@ If you need to include non-file data fields in the multipart form, use the `data
206208

207209
```pycon
208210
>>> data = {'message': 'Hello, world!'}
209-
>>> files = {'file': open('report.xls', 'rb')}
210-
>>> r = httpx.post("https://httpbin.org/post", data=data, files=files)
211+
>>> with open('report.xls', 'rb') as report_file:
212+
... files = {'file': report_file}
213+
... r = httpx.post("https://httpbin.org/post", data=data, files=files)
211214
>>> print(r.text)
212215
{
213216
...

docs/third_party_packages.md

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,90 +2,98 @@
22

33
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.
44

5+
<!-- NOTE: Entries are alphabetised. -->
6+
57
## Plugins
68

7-
### httpx-ws
9+
### Hishel
810

9-
[GitHub](https://github.com/frankie567/httpx-ws) - [Documentation](https://frankie567.github.io/httpx-ws/)
11+
[GitHub](https://github.com/karpetrosyan/hishel) - [Documentation](https://hishel.com/)
1012

11-
WebSocket support for HTTPX.
13+
An elegant HTTP Cache implementation for HTTPX and HTTP Core.
1214

13-
### httpx-socks
15+
### HTTPX-Auth
1416

15-
[GitHub](https://github.com/romis2012/httpx-socks)
17+
[GitHub](https://github.com/Colin-b/httpx_auth) - [Documentation](https://colin-b.github.io/httpx_auth/)
1618

17-
Proxy (HTTP, SOCKS) transports for httpx.
19+
Provides authentication classes to be used with HTTPX's [authentication parameter](advanced/authentication.md#customizing-authentication).
1820

19-
### Hishel
21+
### httpx-caching
2022

21-
[GitHub](https://github.com/karpetrosyan/hishel) - [Documentation](https://hishel.com/)
23+
[Github](https://github.com/johtso/httpx-caching)
2224

23-
An elegant HTTP Cache implementation for HTTPX and HTTP Core.
25+
This package adds caching functionality to HTTPX
2426

25-
### Authlib
27+
### httpx-socks
2628

27-
[GitHub](https://github.com/lepture/authlib) - [Documentation](https://docs.authlib.org/en/latest/)
29+
[GitHub](https://github.com/romis2012/httpx-socks)
2830

29-
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).
31+
Proxy (HTTP, SOCKS) transports for httpx.
3032

31-
### Gidgethub
33+
### httpx-sse
3234

33-
[GitHub](https://github.com/brettcannon/gidgethub) - [Documentation](https://gidgethub.readthedocs.io/en/latest/index.html)
35+
[GitHub](https://github.com/florimondmanca/httpx-sse)
3436

35-
An asynchronous GitHub API library. Includes [HTTPX support](https://gidgethub.readthedocs.io/en/latest/httpx.html).
37+
Allows consuming Server-Sent Events (SSE) with HTTPX.
3638

37-
### HTTPX-Auth
39+
### httpx-retries
3840

39-
[GitHub](https://github.com/Colin-b/httpx_auth) - [Documentation](https://colin-b.github.io/httpx_auth/)
41+
[GitHub](https://github.com/will-ockmore/httpx-retries) - [Documentation](https://will-ockmore.github.io/httpx-retries/)
42+
43+
A retry layer for HTTPX.
44+
45+
### httpx-ws
4046

41-
Provides authentication classes to be used with HTTPX [authentication parameter](advanced/authentication.md#customizing-authentication).
47+
[GitHub](https://github.com/frankie567/httpx-ws) - [Documentation](https://frankie567.github.io/httpx-ws/)
48+
49+
WebSocket support for HTTPX.
4250

4351
### pytest-HTTPX
4452

4553
[GitHub](https://github.com/Colin-b/pytest_httpx) - [Documentation](https://colin-b.github.io/pytest_httpx/)
4654

47-
Provides `httpx_mock` [pytest](https://docs.pytest.org/en/latest/) fixture to mock HTTPX within test cases.
55+
Provides a [pytest](https://docs.pytest.org/en/latest/) fixture to mock HTTPX within test cases.
4856

4957
### RESPX
5058

5159
[GitHub](https://github.com/lundberg/respx) - [Documentation](https://lundberg.github.io/respx/)
5260

53-
A utility for mocking out the Python HTTPX library.
61+
A utility for mocking out HTTPX.
5462

5563
### rpc.py
5664

5765
[Github](https://github.com/abersheeran/rpc.py) - [Documentation](https://github.com/abersheeran/rpc.py#rpcpy)
5866

59-
An fast and powerful RPC framework based on ASGI/WSGI. Use HTTPX as the client of the RPC service.
67+
A fast and powerful RPC framework based on ASGI/WSGI. Use HTTPX as the client of the RPC service.
6068

61-
### VCR.py
69+
## Libraries with HTTPX support
6270

63-
[GitHub](https://github.com/kevin1024/vcrpy) - [Documentation](https://vcrpy.readthedocs.io/)
71+
### Authlib
6472

65-
A utility for record and repeat an http request.
73+
[GitHub](https://github.com/lepture/authlib) - [Documentation](https://docs.authlib.org/en/latest/)
6674

67-
### httpx-caching
75+
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).
6876

69-
[Github](https://github.com/johtso/httpx-caching)
77+
### Gidgethub
7078

71-
This package adds caching functionality to HTTPX
79+
[GitHub](https://github.com/brettcannon/gidgethub) - [Documentation](https://gidgethub.readthedocs.io/en/latest/index.html)
7280

73-
### httpx-sse
81+
An asynchronous GitHub API library. Includes [HTTPX support](https://gidgethub.readthedocs.io/en/latest/httpx.html).
7482

75-
[GitHub](https://github.com/florimondmanca/httpx-sse)
83+
### httpdbg
7684

77-
Allows consuming Server-Sent Events (SSE) with HTTPX.
85+
[GitHub](https://github.com/cle-b/httpdbg) - [Documentation](https://httpdbg.readthedocs.io/)
86+
87+
A tool for python developers to easily debug the HTTP(S) client requests in a python program.
7888

79-
### robox
89+
### VCR.py
8090

81-
[Github](https://github.com/danclaudiupop/robox)
91+
[GitHub](https://github.com/kevin1024/vcrpy) - [Documentation](https://vcrpy.readthedocs.io/)
8292

83-
A library for scraping the web built on top of HTTPX.
93+
Record and repeat requests.
8494

8595
## Gists
8696

87-
<!-- NOTE: this list is in alphabetical order. -->
88-
8997
### urllib3-transport
9098

9199
[GitHub](https://gist.github.com/florimondmanca/d56764d78d748eb9f73165da388e546e)

httpx/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
__title__ = "httpx"
22
__description__ = "A next generation HTTP client, for Python 3."
3-
__version__ = "0.28.0"
3+
__version__ = "0.28.1"

httpx/_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1723,7 +1723,7 @@ async def _send_single_request(self, request: Request) -> Response:
17231723

17241724
if not isinstance(request.stream, AsyncByteStream):
17251725
raise RuntimeError(
1726-
"Attempted to send an sync request with an AsyncClient instance."
1726+
"Attempted to send a sync request with an AsyncClient instance."
17271727
)
17281728

17291729
with request_context(request=request):

httpx/_models.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,7 @@ def close(self) -> None:
964964
Automatically called if the response body is read to completion.
965965
"""
966966
if not isinstance(self.stream, SyncByteStream):
967-
raise RuntimeError("Attempted to call an sync close on an async stream.")
967+
raise RuntimeError("Attempted to call a sync close on an async stream.")
968968

969969
if not self.is_closed:
970970
self.is_closed = True
@@ -1045,7 +1045,7 @@ async def aiter_raw(
10451045
if self.is_closed:
10461046
raise StreamClosed()
10471047
if not isinstance(self.stream, AsyncByteStream):
1048-
raise RuntimeError("Attempted to call an async iterator on an sync stream.")
1048+
raise RuntimeError("Attempted to call an async iterator on a sync stream.")
10491049

10501050
self.is_stream_consumed = True
10511051
self._num_bytes_downloaded = 0
@@ -1068,7 +1068,7 @@ async def aclose(self) -> None:
10681068
Automatically called if the response body is read to completion.
10691069
"""
10701070
if not isinstance(self.stream, AsyncByteStream):
1071-
raise RuntimeError("Attempted to call an async close on an sync stream.")
1071+
raise RuntimeError("Attempted to call an async close on a sync stream.")
10721072

10731073
if not self.is_closed:
10741074
self.is_closed = True

httpx/_transports/default.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ def __init__(
355355
else: # pragma: no cover
356356
raise ValueError(
357357
"Proxy protocol must be either 'http', 'https', 'socks5', or 'socks5h',"
358-
" but got {proxy.url.scheme!r}."
358+
f" but got {proxy.url.scheme!r}."
359359
)
360360

361361
async def __aenter__(self: A) -> A: # Use generics for subclass support.

0 commit comments

Comments
 (0)