Compare commits

..

3 Commits

Author SHA1 Message Date
Tom Christie
c0b46ebf4c
Update CHANGELOG.md 2025-03-04 11:28:56 +00:00
Tom Christie
fc3a4aa9bf
Update CHANGELOG.md 2025-03-04 11:27:33 +00:00
Tom Christie
e30c099c6f
Update version to 0.28.2
Update Python package with up to date classifiers.
2025-03-04 11:26:04 +00:00
27 changed files with 117 additions and 162 deletions

View File

@ -15,9 +15,9 @@ jobs:
steps: steps:
- uses: "actions/checkout@v4" - uses: "actions/checkout@v4"
- uses: "actions/setup-python@v6" - uses: "actions/setup-python@v5"
with: with:
python-version: 3.9 python-version: 3.8
- name: "Install dependencies" - name: "Install dependencies"
run: "scripts/install" run: "scripts/install"
- name: "Build package & docs" - name: "Build package & docs"

View File

@ -14,11 +14,11 @@ jobs:
strategy: strategy:
matrix: matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
steps: steps:
- uses: "actions/checkout@v4" - uses: "actions/checkout@v4"
- uses: "actions/setup-python@v6" - uses: "actions/setup-python@v5"
with: with:
python-version: "${{ matrix.python-version }}" python-version: "${{ matrix.python-version }}"
allow-prereleases: true allow-prereleases: true

View File

@ -4,16 +4,10 @@ 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/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [UNRELEASED] ## 0.28.2 (...)
### Removed
* Drop support for Python 3.8
### Added
* Expose `FunctionAuth` from the public API. (#3699)
* Update package classifiers. (#3460)
## 0.28.1 (6th December, 2024) ## 0.28.1 (6th December, 2024)
* Fix SSL case where `verify=False` together with client side certificates. * Fix SSL case where `verify=False` together with client side certificates.

View File

@ -101,7 +101,7 @@ Or, to include the optional HTTP/2 support, use:
$ pip install httpx[http2] $ pip install httpx[http2]
``` ```
HTTPX requires Python 3.9+. HTTPX requires Python 3.8+.
## Documentation ## Documentation

View File

@ -29,7 +29,7 @@ import certifi
import httpx import httpx
import ssl import ssl
# This SSL context is equivalent to the default `verify=True`. # This SSL context is equivelent to the default `verify=True`.
ctx = ssl.create_default_context(cafile=certifi.where()) ctx = ssl.create_default_context(cafile=certifi.where())
client = httpx.Client(verify=ctx) client = httpx.Client(verify=ctx)
``` ```
@ -71,7 +71,19 @@ client = httpx.Client(verify=ctx)
### Working with `SSL_CERT_FILE` and `SSL_CERT_DIR` ### Working with `SSL_CERT_FILE` and `SSL_CERT_DIR`
`httpx` does respect the `SSL_CERT_FILE` and `SSL_CERT_DIR` environment variables by default. For details, refer to [the section on the environment variables page](../environment_variables.md#ssl_cert_file). Unlike `requests`, the `httpx` package does not automatically pull in [the environment variables `SSL_CERT_FILE` or `SSL_CERT_DIR`](https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_default_verify_paths.html). If you want to use these they need to be enabled explicitly.
For example...
```python
# Use `SSL_CERT_FILE` or `SSL_CERT_DIR` if configured.
# Otherwise default to certifi.
ctx = ssl.create_default_context(
cafile=os.environ.get("SSL_CERT_FILE", certifi.where()),
capath=os.environ.get("SSL_CERT_DIR"),
)
client = httpx.Client(verify=ctx)
```
### Making HTTPS requests to a local server ### Making HTTPS requests to a local server

View File

@ -159,18 +159,3 @@ what gets sent over the wire.*
* `def delete(name, [domain], [path])` * `def delete(name, [domain], [path])`
* `def clear([domain], [path])` * `def clear([domain], [path])`
* *Standard mutable mapping interface* * *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**

View File

@ -23,7 +23,7 @@ To make asynchronous requests, you'll need an `AsyncClient`.
``` ```
!!! tip !!! tip
Use [IPython](https://ipython.readthedocs.io/en/stable/) or Python 3.9+ with `python -m asyncio` to try this code interactively, as they support executing `async`/`await` expressions in the console. Use [IPython](https://ipython.readthedocs.io/en/stable/) or Python 3.8+ with `python -m asyncio` to try this code interactively, as they support executing `async`/`await` expressions in the console.
## API Differences ## API Differences

View File

@ -226,7 +226,3 @@ For both query params (`params=`) and form data (`data=`), `requests` supports s
In HTTPX, event hooks may access properties of requests and responses, but event hook callbacks cannot mutate the original request/response. In HTTPX, event hooks may access properties of requests and responses, but event hook callbacks cannot mutate the original request/response.
If you are looking for more control, consider checking out [Custom Transports](advanced/transports.md#custom-transports). If you are looking for more control, consider checking out [Custom Transports](advanced/transports.md#custom-transports).
## Exceptions and Errors
`requests` exception hierarchy is slightly different to the `httpx` exception hierarchy. `requests` exposes a top level `RequestException`, where as `httpx` exposes a top level `HTTPError`. see the exceptions exposes in requests [here](https://requests.readthedocs.io/en/latest/_modules/requests/exceptions/). See the `httpx` error hierarchy [here](https://www.python-httpx.org/exceptions/).

View File

@ -51,29 +51,3 @@ python -c "import httpx; httpx.get('http://example.com')"
python -c "import httpx; httpx.get('http://127.0.0.1:5000/my-api')" python -c "import httpx; httpx.get('http://127.0.0.1:5000/my-api')"
python -c "import httpx; httpx.get('https://www.python-httpx.org')" python -c "import httpx; httpx.get('https://www.python-httpx.org')"
``` ```
## `SSL_CERT_FILE`
Valid values: a filename
If this environment variable is set then HTTPX will load
CA certificate from the specified file instead of the default
location.
Example:
```console
SSL_CERT_FILE=/path/to/ca-certs/ca-bundle.crt python -c "import httpx; httpx.get('https://example.com')"
```
## `SSL_CERT_DIR`
Valid values: a directory following an [OpenSSL specific layout](https://www.openssl.org/docs/manmaster/man3/SSL_CTX_load_verify_locations.html).
If this environment variable is set and the directory follows an [OpenSSL specific layout](https://www.openssl.org/docs/manmaster/man3/SSL_CTX_load_verify_locations.html) (ie. you ran `c_rehash`) then HTTPX will load CA certificates from this directory instead of the default location.
Example:
```console
SSL_CERT_DIR=/path/to/ca-certs/ python -c "import httpx; httpx.get('https://example.com')"
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@ -145,6 +145,6 @@ To include the optional brotli and zstandard decoders support, use:
$ pip install httpx[brotli,zstd] $ pip install httpx[brotli,zstd]
``` ```
HTTPX requires Python 3.9+ HTTPX requires Python 3.8+
[sync-support]: https://github.com/encode/httpx/issues/572 [sync-support]: https://github.com/encode/httpx/issues/572

View File

@ -20,6 +20,8 @@ httpx.get("https://www.example.com")
Will send debug level output to the console, or wherever `stdout` is directed too... Will send debug level output to the console, or wherever `stdout` is directed too...
``` ```
DEBUG [2024-09-28 17:27:40] httpx - load_ssl_context verify=True cert=None
DEBUG [2024-09-28 17:27:40] httpx - load_verify_locations cafile='/Users/karenpetrosyan/oss/karhttpx/.venv/lib/python3.9/site-packages/certifi/cacert.pem'
DEBUG [2024-09-28 17:27:40] httpcore.connection - connect_tcp.started host='www.example.com' port=443 local_address=None timeout=5.0 socket_options=None DEBUG [2024-09-28 17:27:40] httpcore.connection - connect_tcp.started host='www.example.com' port=443 local_address=None timeout=5.0 socket_options=None
DEBUG [2024-09-28 17:27:41] httpcore.connection - connect_tcp.complete return_value=<httpcore._backends.sync.SyncStream object at 0x101f1e8e0> DEBUG [2024-09-28 17:27:41] httpcore.connection - connect_tcp.complete return_value=<httpcore._backends.sync.SyncStream object at 0x101f1e8e0>
DEBUG [2024-09-28 17:27:41] httpcore.connection - start_tls.started ssl_context=SSLContext(verify=True) server_hostname='www.example.com' timeout=5.0 DEBUG [2024-09-28 17:27:41] httpcore.connection - start_tls.started ssl_context=SSLContext(verify=True) server_hostname='www.example.com' timeout=5.0
@ -78,4 +80,4 @@ logging.config.dictConfig(LOGGING_CONFIG)
httpx.get('https://www.example.com') httpx.get('https://www.example.com')
``` ```
The exact formatting of the debug logging may be subject to change across different versions of `httpx` and `httpcore`. If you need to rely on a particular format it is recommended that you pin installation of these packages to fixed versions. The exact formatting of the debug logging may be subject to change across different versions of `httpx` and `httpcore`. If you need to rely on a particular format it is recommended that you pin installation of these packages to fixed versions.

View File

@ -191,7 +191,7 @@ You can also explicitly set the filename and content type, by using a tuple
of items for the file value: of items for the file value:
```pycon ```pycon
>>> with open('report.xls', 'rb') as report_file: >>> with open('report.xls', 'rb') report_file:
... files = {'upload-file': ('report.xls', report_file, 'application/vnd.ms-excel')} ... files = {'upload-file': ('report.xls', report_file, 'application/vnd.ms-excel')}
... r = httpx.post("https://httpbin.org/post", files=files) ... r = httpx.post("https://httpbin.org/post", files=files)
>>> print(r.text) >>> print(r.text)

View File

@ -2,83 +2,37 @@
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. 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 ## Plugins
### Hishel
[GitHub](https://github.com/karpetrosyan/hishel) - [Documentation](https://hishel.com/)
An elegant HTTP Cache implementation for HTTPX and HTTP Core.
### 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's [authentication parameter](advanced/authentication.md#customizing-authentication).
### httpx-caching
[Github](https://github.com/johtso/httpx-caching)
This package adds caching functionality to HTTPX
### httpx-secure
[GitHub](https://github.com/Zaczero/httpx-secure)
Drop-in SSRF protection for httpx with DNS caching and custom validation support.
### 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.
### httpx-retries
[GitHub](https://github.com/will-ockmore/httpx-retries) - [Documentation](https://will-ockmore.github.io/httpx-retries/)
A retry layer for HTTPX.
### httpx-ws ### httpx-ws
[GitHub](https://github.com/frankie567/httpx-ws) - [Documentation](https://frankie567.github.io/httpx-ws/) [GitHub](https://github.com/frankie567/httpx-ws) - [Documentation](https://frankie567.github.io/httpx-ws/)
WebSocket support for HTTPX. WebSocket support for HTTPX.
### pytest-HTTPX ### httpx-socks
[GitHub](https://github.com/Colin-b/pytest_httpx) - [Documentation](https://colin-b.github.io/pytest_httpx/) [GitHub](https://github.com/romis2012/httpx-socks)
Provides a [pytest](https://docs.pytest.org/en/latest/) fixture to mock HTTPX within test cases. Proxy (HTTP, SOCKS) transports for httpx.
### RESPX ### httpdbg
[GitHub](https://github.com/lundberg/respx) - [Documentation](https://lundberg.github.io/respx/) [GitHub](https://github.com/cle-b/httpdbg) - [Documentation](https://httpdbg.readthedocs.io/)
A utility for mocking out HTTPX. A tool for Python developers to easily debug the HTTP(S) client requests in a Python program.
### rpc.py ### Hishel
[Github](https://github.com/abersheeran/rpc.py) - [Documentation](https://github.com/abersheeran/rpc.py#rpcpy) [GitHub](https://github.com/karpetrosyan/hishel) - [Documentation](https://hishel.com/)
A fast and powerful RPC framework based on ASGI/WSGI. Use HTTPX as the client of the RPC service. An elegant HTTP Cache implementation for HTTPX and HTTP Core.
## Libraries with HTTPX support
### Authlib ### Authlib
[GitHub](https://github.com/lepture/authlib) - [Documentation](https://docs.authlib.org/en/latest/) [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). 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 ### Gidgethub
@ -86,20 +40,58 @@ A python library for building OAuth and OpenID Connect clients and servers. Incl
An asynchronous GitHub API library. Includes [HTTPX support](https://gidgethub.readthedocs.io/en/latest/httpx.html). An asynchronous GitHub API library. Includes [HTTPX support](https://gidgethub.readthedocs.io/en/latest/httpx.html).
### httpdbg ### HTTPX-Auth
[GitHub](https://github.com/cle-b/httpdbg) - [Documentation](https://httpdbg.readthedocs.io/) [GitHub](https://github.com/Colin-b/httpx_auth) - [Documentation](https://colin-b.github.io/httpx_auth/)
A tool for python developers to easily debug the HTTP(S) client requests in a python program. 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 ### VCR.py
[GitHub](https://github.com/kevin1024/vcrpy) - [Documentation](https://vcrpy.readthedocs.io/) [GitHub](https://github.com/kevin1024/vcrpy) - [Documentation](https://vcrpy.readthedocs.io/)
Record and repeat requests. A utility for record and repeat an http request.
### httpx-caching
[Github](https://github.com/johtso/httpx-caching)
This package adds caching functionality to HTTPX
### httpx-sse
[GitHub](https://github.com/florimondmanca/httpx-sse)
Allows consuming Server-Sent Events (SSE) with HTTPX.
### robox
[Github](https://github.com/danclaudiupop/robox)
A library for scraping the web built on top of HTTPX.
## Gists ## Gists
<!-- NOTE: this list is in alphabetical order. -->
### urllib3-transport ### urllib3-transport
[GitHub](https://gist.github.com/florimondmanca/d56764d78d748eb9f73165da388e546e) [GitHub](https://gist.github.com/florimondmanca/d56764d78d748eb9f73165da388e546e)

View File

@ -50,7 +50,6 @@ __all__ = [
"DecodingError", "DecodingError",
"delete", "delete",
"DigestAuth", "DigestAuth",
"FunctionAuth",
"get", "get",
"head", "head",
"Headers", "Headers",

View File

@ -1,3 +1,3 @@
__title__ = "httpx" __title__ = "httpx"
__description__ = "A next generation HTTP client, for Python 3." __description__ = "A next generation HTTP client, for Python 3."
__version__ = "0.28.1" __version__ = "0.28.2"

View File

@ -16,7 +16,7 @@ if typing.TYPE_CHECKING: # pragma: no cover
from hashlib import _Hash from hashlib import _Hash
__all__ = ["Auth", "BasicAuth", "DigestAuth", "FunctionAuth", "NetRCAuth"] __all__ = ["Auth", "BasicAuth", "DigestAuth", "NetRCAuth"]
class Auth: class Auth:

View File

@ -331,7 +331,9 @@ class StreamClosed(StreamError):
""" """
def __init__(self) -> None: def __init__(self) -> None:
message = "Attempted to read or stream content, but the stream has been closed." message = (
"Attempted to read or stream content, but the stream has " "been closed."
)
super().__init__(message) super().__init__(message)

View File

@ -355,7 +355,7 @@ class AsyncHTTPTransport(AsyncBaseTransport):
else: # pragma: no cover else: # pragma: no cover
raise ValueError( raise ValueError(
"Proxy protocol must be either 'http', 'https', 'socks5', or 'socks5h'," "Proxy protocol must be either 'http', 'https', 'socks5', or 'socks5h',"
f" but got {proxy.url.scheme!r}." " but got {proxy.url.scheme!r}."
) )
async def __aenter__(self: A) -> A: # Use generics for subclass support. async def __aenter__(self: A) -> A: # Use generics for subclass support.

View File

@ -379,7 +379,7 @@ class URL:
if ":" in userinfo: if ":" in userinfo:
# Mask any password component. # Mask any password component.
userinfo = f"{userinfo.split(':')[0]}:[secure]" userinfo = f'{userinfo.split(":")[0]}:[secure]'
authority = "".join( authority = "".join(
[ [

View File

@ -6,7 +6,7 @@ build-backend = "hatchling.build"
name = "httpx" name = "httpx"
description = "The next generation HTTP client." description = "The next generation HTTP client."
license = "BSD-3-Clause" license = "BSD-3-Clause"
requires-python = ">=3.9" requires-python = ">=3.8"
authors = [ authors = [
{ name = "Tom Christie", email = "tom@tomchristie.com" }, { name = "Tom Christie", email = "tom@tomchristie.com" },
] ]
@ -20,6 +20,7 @@ classifiers = [
"Operating System :: OS Independent", "Operating System :: OS Independent",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
@ -43,7 +44,7 @@ brotli = [
cli = [ cli = [
"click==8.*", "click==8.*",
"pygments==2.*", "pygments==2.*",
"rich>=10,<15", "rich>=10,<14",
] ]
http2 = [ http2 = [
"h2>=3,<5", "h2>=3,<5",

View File

@ -11,19 +11,20 @@ chardet==5.2.0
# Documentation # Documentation
mkdocs==1.6.1 mkdocs==1.6.1
mkautodoc==0.2.0 mkautodoc==0.2.0
mkdocs-material==9.6.18 mkdocs-material==9.5.47
# Packaging # Packaging
build==1.3.0 build==1.2.2.post1
twine==6.1.0 twine==6.0.1
# Tests & Linting # Tests & Linting
coverage[toml]==7.10.6 coverage[toml]==7.6.1
cryptography==45.0.7 cryptography==44.0.1
mypy==1.17.1 mypy==1.13.0
pytest==8.4.1 pytest==8.3.4
ruff==0.12.11 ruff==0.8.1
trio==0.31.0 trio==0.27.0
trio-typing==0.10.0 trio-typing==0.10.0
trustme==1.2.1 trustme==1.1.0; python_version < '3.9'
uvicorn==0.35.0 trustme==1.2.0; python_version >= '3.9'
uvicorn==0.32.1

View File

@ -326,7 +326,7 @@ async def test_auth_property() -> None:
async with httpx.AsyncClient(transport=httpx.MockTransport(app)) as client: async with httpx.AsyncClient(transport=httpx.MockTransport(app)) as client:
assert client.auth is None assert client.auth is None
client.auth = ("user", "password123") client.auth = ("user", "password123") # type: ignore
assert isinstance(client.auth, httpx.BasicAuth) assert isinstance(client.auth, httpx.BasicAuth)
url = "https://example.org/" url = "https://example.org/"

View File

@ -3,35 +3,35 @@ import httpx
def test_client_base_url(): def test_client_base_url():
client = httpx.Client() client = httpx.Client()
client.base_url = "https://www.example.org/" client.base_url = "https://www.example.org/" # type: ignore
assert isinstance(client.base_url, httpx.URL) assert isinstance(client.base_url, httpx.URL)
assert client.base_url == "https://www.example.org/" assert client.base_url == "https://www.example.org/"
def test_client_base_url_without_trailing_slash(): def test_client_base_url_without_trailing_slash():
client = httpx.Client() client = httpx.Client()
client.base_url = "https://www.example.org/path" client.base_url = "https://www.example.org/path" # type: ignore
assert isinstance(client.base_url, httpx.URL) assert isinstance(client.base_url, httpx.URL)
assert client.base_url == "https://www.example.org/path/" assert client.base_url == "https://www.example.org/path/"
def test_client_base_url_with_trailing_slash(): def test_client_base_url_with_trailing_slash():
client = httpx.Client() client = httpx.Client()
client.base_url = "https://www.example.org/path/" client.base_url = "https://www.example.org/path/" # type: ignore
assert isinstance(client.base_url, httpx.URL) assert isinstance(client.base_url, httpx.URL)
assert client.base_url == "https://www.example.org/path/" assert client.base_url == "https://www.example.org/path/"
def test_client_headers(): def test_client_headers():
client = httpx.Client() client = httpx.Client()
client.headers = {"a": "b"} client.headers = {"a": "b"} # type: ignore
assert isinstance(client.headers, httpx.Headers) assert isinstance(client.headers, httpx.Headers)
assert client.headers["A"] == "b" assert client.headers["A"] == "b"
def test_client_cookies(): def test_client_cookies():
client = httpx.Client() client = httpx.Client()
client.cookies = {"a": "b"} client.cookies = {"a": "b"} # type: ignore
assert isinstance(client.cookies, httpx.Cookies) assert isinstance(client.cookies, httpx.Cookies)
mycookies = list(client.cookies.jar) mycookies = list(client.cookies.jar)
assert len(mycookies) == 1 assert len(mycookies) == 1
@ -42,7 +42,7 @@ def test_client_timeout():
expected_timeout = 12.0 expected_timeout = 12.0
client = httpx.Client() client = httpx.Client()
client.timeout = expected_timeout client.timeout = expected_timeout # type: ignore
assert isinstance(client.timeout, httpx.Timeout) assert isinstance(client.timeout, httpx.Timeout)
assert client.timeout.connect == expected_timeout assert client.timeout.connect == expected_timeout

View File

@ -17,7 +17,7 @@ def test_client_queryparams_string():
assert client.params["a"] == "b" assert client.params["a"] == "b"
client = httpx.Client() client = httpx.Client()
client.params = "a=b" client.params = "a=b" # type: ignore
assert isinstance(client.params, httpx.QueryParams) assert isinstance(client.params, httpx.QueryParams)
assert client.params["a"] == "b" assert client.params["a"] == "b"

View File

@ -1011,10 +1011,7 @@ def test_response_decode_text_using_autodetect():
assert response.status_code == 200 assert response.status_code == 200
assert response.reason_phrase == "OK" assert response.reason_phrase == "OK"
# The encoded byte string is consistent with either ISO-8859-1 or assert response.encoding == "ISO-8859-1"
# WINDOWS-1252. Versions <6.0 of chardet claim the former, while chardet
# 6.0 detects the latter.
assert response.encoding in ("ISO-8859-1", "WINDOWS-1252")
assert response.text == text assert response.text == text

View File

@ -489,18 +489,18 @@ def test_response_invalid_argument():
def test_ensure_ascii_false_with_french_characters(): def test_ensure_ascii_false_with_french_characters():
data = {"greeting": "Bonjour, ça va ?"} data = {"greeting": "Bonjour, ça va ?"}
response = httpx.Response(200, json=data) response = httpx.Response(200, json=data)
assert "ça va" in response.text, ( assert (
"ensure_ascii=False should preserve French accented characters" "ça va" in response.text
) ), "ensure_ascii=False should preserve French accented characters"
assert response.headers["Content-Type"] == "application/json" assert response.headers["Content-Type"] == "application/json"
def test_separators_for_compact_json(): def test_separators_for_compact_json():
data = {"clé": "valeur", "liste": [1, 2, 3]} data = {"clé": "valeur", "liste": [1, 2, 3]}
response = httpx.Response(200, json=data) response = httpx.Response(200, json=data)
assert response.text == '{"clé":"valeur","liste":[1,2,3]}', ( assert (
"separators=(',', ':') should produce a compact representation" response.text == '{"clé":"valeur","liste":[1,2,3]}'
) ), "separators=(',', ':') should produce a compact representation"
assert response.headers["Content-Type"] == "application/json" assert response.headers["Content-Type"] == "application/json"