Compare commits

..

6 Commits

Author SHA1 Message Date
Kim Christie
07a88cc679
Merge branch 'master' into support-3-14 2025-12-10 15:17:09 +00:00
Kar Petrosyan
15c4b63315 Add folks to co-authors
Co-authored-by: mirthebeijers <mirthebeijers@users.noreply.github.com>
Co-authored-by: SamMorrowDrums <SamMorrowDrums@users.noreply.github.com>
2025-12-10 18:07:27 +04:00
Kar Petrosyan
be7ef24aea properly support python 3.14 2025-12-10 18:03:20 +04:00
Kar Petrosyan
9d59507dc4 more fixes 2025-12-10 17:49:29 +04:00
Kar Petrosyan
61630c4a4b get rid of prefix variables in sh 2025-12-10 17:41:54 +04:00
Kar Petrosyan
6d121eae8d Adopt uv 2025-12-10 17:32:45 +04:00
15 changed files with 2052 additions and 105 deletions

View File

@ -14,14 +14,16 @@ jobs:
strategy: strategy:
matrix: matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
steps: steps:
- uses: "actions/checkout@v4" - uses: "actions/checkout@v4"
- uses: "actions/setup-python@v6" - name: Install uv (official Astral action)
uses: astral-sh/setup-uv@v5
with: with:
python-version: "${{ matrix.python-version }}" version: "0.9.13"
allow-prereleases: true enable-cache: true
python-version: ${{ matrix.python-version }}
- name: "Install dependencies" - name: "Install dependencies"
run: "scripts/install" run: "scripts/install"
- name: "Run linting checks" - name: "Run linting checks"

View File

@ -25,6 +25,7 @@ classifiers = [
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP",
] ]
dependencies = [ dependencies = [
@ -64,6 +65,40 @@ Documentation = "https://www.python-httpx.org"
Homepage = "https://github.com/encode/httpx" Homepage = "https://github.com/encode/httpx"
Source = "https://github.com/encode/httpx" Source = "https://github.com/encode/httpx"
[dependency-groups]
dev = [
# Install httpx with all optional dependencies
{ include-group = "test" },
{ include-group = "docs" },
{ include-group = "package" },
{ include-group = "lint" },
]
test = [
# Optional charset auto-detection (used in test cases)
"chardet==5.2.0",
# Testing dependencies
"coverage[toml]==7.10.6",
"cryptography==45.0.7",
"pytest==8.4.1",
"trio==0.31.0",
"trio-typing==0.10.0",
"trustme==1.2.1",
"uvicorn==0.38.0",
]
docs = [
"mkdocs==1.6.1",
"mkautodoc==0.2.0",
"mkdocs-material==9.6.18",
]
package = [
"build==1.3.0",
"twine==6.1.0",
]
lint = [
"mypy==1.17.1",
"ruff==0.12.11",
]
[tool.hatch.version] [tool.hatch.version]
path = "httpx/__version__.py" path = "httpx/__version__.py"

View File

@ -1,29 +0,0 @@
# We're pinning our tooling, because it's an environment we can strictly control.
# On the other hand, we're not pinning package dependencies, because our tests
# needs to pass with the latest version of the packages.
# Reference: https://github.com/encode/httpx/pull/1721#discussion_r661241588
-e .[brotli,cli,http2,socks,zstd]
# Optional charset auto-detection
# Used in our test cases
chardet==5.2.0
# Documentation
mkdocs==1.6.1
mkautodoc==0.2.0
mkdocs-material==9.6.18
# Packaging
build==1.3.0
twine==6.1.0
# Tests & Linting
coverage[toml]==7.10.6
cryptography==45.0.7
mypy==1.17.1
pytest==8.4.1
ruff==0.12.11
trio==0.31.0
trio-typing==0.10.0
trustme==1.2.1
uvicorn==0.35.0

View File

@ -1,13 +1,7 @@
#!/bin/sh -e #!/bin/sh -e
if [ -d 'venv' ] ; then
PREFIX="venv/bin/"
else
PREFIX=""
fi
set -x set -x
${PREFIX}python -m build uv run python -m build
${PREFIX}twine check dist/* uv run twine check dist/*
${PREFIX}mkdocs build uv run mkdocs build

View File

@ -1,14 +1,16 @@
#!/bin/sh -e #!/bin/sh -e
export PREFIX=""
if [ -d 'venv' ] ; then
export PREFIX="venv/bin/"
fi
export SOURCE_FILES="httpx tests" export SOURCE_FILES="httpx tests"
set -x set -x
./scripts/sync-version ./scripts/sync-version
${PREFIX}ruff format $SOURCE_FILES --diff
${PREFIX}mypy $SOURCE_FILES echo "==> Checking formatting…"
${PREFIX}ruff check $SOURCE_FILES uv run ruff format $SOURCE_FILES --diff
echo "==> Running type checks and linting…"
uv run mypy $SOURCE_FILES
echo "==> Running linting checks…"
uv run ruff check $SOURCE_FILES

View File

@ -1,11 +1,7 @@
#!/bin/sh -e #!/bin/sh -e
export PREFIX=""
if [ -d 'venv' ] ; then
export PREFIX="venv/bin/"
fi
export SOURCE_FILES="httpx tests" export SOURCE_FILES="httpx tests"
set -x set -x
${PREFIX}coverage report --show-missing --skip-covered --fail-under=100 uv run coverage report --show-missing --skip-covered --fail-under=100

View File

@ -1,10 +1,5 @@
#!/bin/sh -e #!/bin/sh -e
export PREFIX=""
if [ -d 'venv' ] ; then
export PREFIX="venv/bin/"
fi
set -x set -x
${PREFIX}mkdocs serve uv run mkdocs serve

View File

@ -1,19 +1,4 @@
#!/bin/sh -e #!/bin/sh -e
# Use the Python executable provided from the `-p` option, or a default. echo "==> Installing Python dependencies…"
[ "$1" = "-p" ] && PYTHON=$2 || PYTHON="python3" uv sync --all-extras
REQUIREMENTS="requirements.txt"
VENV="venv"
set -x
if [ -z "$GITHUB_ACTIONS" ]; then
"$PYTHON" -m venv "$VENV"
PIP="$VENV/bin/pip"
else
PIP="pip"
fi
"$PIP" install -U pip
"$PIP" install -r "$REQUIREMENTS"

View File

@ -1,12 +1,11 @@
#!/bin/sh -e #!/bin/sh -e
export PREFIX=""
if [ -d 'venv' ]; then
export PREFIX="venv/bin/"
fi
export SOURCE_FILES="httpx tests" export SOURCE_FILES="httpx tests"
set -x set -x
${PREFIX}ruff check --fix $SOURCE_FILES echo "==> Running linting checks…"
${PREFIX}ruff format $SOURCE_FILES uv run ruff check --fix $SOURCE_FILES
echo "==> Formatting source code…"
uv run ruff format $SOURCE_FILES

View File

@ -2,11 +2,6 @@
VERSION_FILE="httpx/__version__.py" VERSION_FILE="httpx/__version__.py"
if [ -d 'venv' ] ; then
PREFIX="venv/bin/"
else
PREFIX=""
fi
if [ ! -z "$GITHUB_ACTIONS" ]; then if [ ! -z "$GITHUB_ACTIONS" ]; then
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
@ -22,5 +17,5 @@ fi
set -x set -x
${PREFIX}twine upload dist/* uv run twine upload dist/*
${PREFIX}mkdocs gh-deploy --force uv run mkdocs gh-deploy --force

View File

@ -1,17 +1,12 @@
#!/bin/sh #!/bin/sh
export PREFIX=""
if [ -d 'venv' ] ; then
export PREFIX="venv/bin/"
fi
set -ex set -ex
if [ -z $GITHUB_ACTIONS ]; then if [ -z $GITHUB_ACTIONS ]; then
scripts/check scripts/check
fi fi
${PREFIX}coverage run -m pytest "$@" uv run coverage run -m pytest "$@"
if [ -z $GITHUB_ACTIONS ]; then if [ -z $GITHUB_ACTIONS ]; then
scripts/coverage scripts/coverage

View File

@ -235,10 +235,9 @@ class TestServer(Server):
async def serve(self, sockets=None): async def serve(self, sockets=None):
self.restart_requested = asyncio.Event() self.restart_requested = asyncio.Event()
loop = asyncio.get_event_loop()
tasks = { tasks = {
loop.create_task(super().serve(sockets=sockets)), asyncio.create_task(super().serve(sockets=sockets)),
loop.create_task(self.watch_restarts()), asyncio.create_task(self.watch_restarts()),
} }
await asyncio.wait(tasks) await asyncio.wait(tasks)
@ -269,7 +268,15 @@ class TestServer(Server):
def serve_in_thread(server: TestServer) -> typing.Iterator[TestServer]: def serve_in_thread(server: TestServer) -> typing.Iterator[TestServer]:
thread = threading.Thread(target=server.run) def run_server() -> None:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(server.serve()) # type: ignore
finally:
loop.close()
thread = threading.Thread(target=run_server)
thread.start() thread.start()
try: try:
while not server.started: while not server.started:
@ -282,6 +289,6 @@ def serve_in_thread(server: TestServer) -> typing.Iterator[TestServer]:
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def server() -> typing.Iterator[TestServer]: def server() -> typing.Iterator[TestServer]:
config = Config(app=app, lifespan="off", loop="asyncio") config = Config(app=app, lifespan="off")
server = TestServer(config=config) server = TestServer(config=config)
yield from serve_in_thread(server) yield from serve_in_thread(server)

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

@ -12,6 +12,8 @@ async def test_read_timeout(server):
await client.get(server.url.copy_with(path="/slow_response")) await client.get(server.url.copy_with(path="/slow_response"))
# TODO: Fix ResourceWarning in this test for Python>=3.14
@pytest.mark.filterwarnings("ignore::ResourceWarning")
@pytest.mark.anyio @pytest.mark.anyio
async def test_write_timeout(server): async def test_write_timeout(server):
timeout = httpx.Timeout(None, write=1e-6) timeout = httpx.Timeout(None, write=1e-6)

1972
uv.lock generated Normal file

File diff suppressed because it is too large Load Diff