Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/install-linux-test-deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail

# cryptography has no CPython 3.15t wheels yet. These dependencies are only
# needed to build test dependencies inside the cibuildwheel container.
if command -v apk >/dev/null 2>&1; then
apk add --no-cache openssl-dev libffi-dev pkgconf
else
# manylinux_2_28 ships OpenSSL 1.1.1; cryptography needs OpenSSL 3.
yum install -y openssl3-devel libffi-devel pkgconfig
# EPEL names its pkg-config file openssl3.pc; the build looks for openssl.
mkdir -p /usr/local/lib/pkgconfig
ln -s /usr/lib64/pkgconfig/openssl3.pc /usr/local/lib/pkgconfig/openssl.pc
fi
48 changes: 34 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, ubuntu-22.04-arm]
os:
- ubuntu-latest
- ubuntu-22.04-arm
- macos-15-intel
- macos-latest
python:
- "cp38"
- "cp39"
Expand All @@ -85,17 +89,17 @@ jobs:
- "cp313"
- "cp314"
- "cp314t"
cibw_arch: ["x86_64", "aarch64", "universal2"]
exclude:
- "cp315"
- "cp315t"
include:
- os: ubuntu-latest
cibw_arch: universal2
- os: ubuntu-latest
cibw_arch: aarch64
- os: macos-latest
cibw_arch: aarch64
- os: ubuntu-22.04-arm
cibw_arch: x86_64
- os: ubuntu-22.04-arm
cibw_arch: aarch64
# Use native OpenSSL when compiling x86_64 test dependencies.
- os: macos-15-intel
cibw_arch: x86_64
- os: macos-latest
cibw_arch: universal2

defaults:
Expand All @@ -104,6 +108,13 @@ jobs:

env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
CIBW_BUILD_VERBOSITY: 1
CIBW_BUILD: ${{ matrix.python }}-*
CIBW_ARCHS: ${{ matrix.cibw_arch }}
# Let tests inside Linux containers recognize GitHub CI.
CIBW_ENVIRONMENT_PASS_LINUX: GITHUB_WORKFLOW
# Exercise arm64 here; x86_64 wheels have their own test jobs.
CIBW_TEST_SKIP: "*universal2:x86_64"

steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
Expand All @@ -114,14 +125,23 @@ jobs:
- name: Install macOS deps
if: startsWith(matrix.os, 'macos')
run: |
brew install gnu-sed libtool autoconf automake
brew install gnu-sed libtool autoconf automake openssl@3
echo "OPENSSL_DIR=$(brew --prefix openssl@3)" >> "$GITHUB_ENV"

# cibuildwheel 4 added Python 3.15 but removed Python 3.8.
- uses: pypa/cibuildwheel@7c619efba910c04005a835b110b057fc28fd6e93 # v3.2.0
if: matrix.python == 'cp38'

- uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
if: matrix.python != 'cp38'
env:
CIBW_BUILD_VERBOSITY: 1
CIBW_BUILD: ${{ matrix.python }}-*
CIBW_ARCHS: ${{ matrix.cibw_arch }}
CIBW_TEST_SKIP: "*universal2:arm64"
CIBW_BEFORE_ALL_LINUX: >-
${{ matrix.python == 'cp315t' && 'bash {project}/.github/workflows/install-linux-test-deps.sh' || '' }}
# Build universal2 wheels, but compile their test dependencies for arm64.
CIBW_TEST_ENVIRONMENT_MACOS: >-
${{ matrix.cibw_arch == 'universal2'
&& 'ARCHFLAGS="-arch arm64" _PYTHON_HOST_PLATFORM="macosx-11.0-arm64"'
|| '' }}

- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ jobs:
- "3.13"
- "3.14"
- "3.14t"
- "3.15"
- "3.15t"
os: [ubuntu-latest, macos-latest]

env:
Expand Down Expand Up @@ -55,7 +57,8 @@ jobs:
- name: Install macOS deps
if: matrix.os == 'macos-latest' && steps.release.outputs.version == 0
run: |
brew install gnu-sed libtool autoconf automake
brew install gnu-sed libtool autoconf automake openssl@3
echo "OPENSSL_DIR=$(brew --prefix openssl@3)" >> "$GITHUB_ENV"

- name: Install Python Deps
if: steps.release.outputs.version == 0
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ test = [
'flake8~=6.1',
'psutil',
'pycodestyle~=2.11.0',
'pyOpenSSL~=25.3.0',
# pyOpenSSL 26.4 requires Python 3.9 or later.
'pyOpenSSL~=25.3.0; python_version < "3.9"',
'pyOpenSSL~=26.4.0; python_version >= "3.9"',
'mypy>=0.800',
]
dev = [
Expand Down
9 changes: 8 additions & 1 deletion tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,16 @@ def check_in_thread(loop, event, debug, create_loop, fut):
def test_thread(loop, debug, create_loop=False):
event = threading.Event()
fut = asyncio.Future(loop=loop)
loop.call_soon(event.set)
args = (loop, event, debug, create_loop, fut)
thread = threading.Thread(target=check_in_thread, args=args)

def run_thread():
# Keep the loop running for the thread checks, but prevent
# concurrent access to its non-thread-safe scheduling APIs.
event.set()
thread.join()

loop.call_soon(run_thread)
thread.start()
loop.run_until_complete(fut)
thread.join()
Expand Down
9 changes: 6 additions & 3 deletions tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -884,9 +884,10 @@ class TestAsyncio_AIO_Process(_AsyncioTests, tb.AIOTestCase):
class Test_UV_Process_Delayed(tb.UVTestCase):

class TestProto:
def __init__(self):
def __init__(self, closed):
self.lost = 0
self.stages = []
self.closed = closed

def connection_made(self, transport):
self.stages.append(('CM', transport))
Expand All @@ -905,10 +906,11 @@ def process_exited(self):
def connection_lost(self, exc):
self.stages.append(('CL', self.lost, exc))
self.lost += 1
self.closed.set_result(None)

async def run_sub(self, **kwargs):
return await self.loop.subprocess_shell(
lambda: self.TestProto(),
lambda: self.TestProto(self.loop.create_future()),
'echo 1',
**kwargs)

Expand Down Expand Up @@ -962,7 +964,8 @@ def test_process_delayed_stdio__not_paused__no_stdin(self):
stdin=None,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE))
self.loop.run_until_complete(transport._wait())
# Process exit alone does not guarantee that pipe callbacks have run.
self.loop.run_until_complete(asyncio.wait_for(proto.closed, 10))
self.assertEqual(transport.get_returncode(), 0)
self.assertIsNot(transport, None)
self.assertEqual(
Expand Down
7 changes: 5 additions & 2 deletions tests/test_sockets.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import os
import pickle
import select
import socket
Expand Down Expand Up @@ -272,7 +273,9 @@ def test_socket_sync_remove(self):
# See https://github.com/MagicStack/uvloop/issues/61 for details

sock = socket.socket()
epoll = select.epoll.fromfd(self.loop._get_backend_id())
# Keep a separate descriptor for the backend epoll instance. The loop
# owns its descriptor and closes it when the loop is closed.
epoll = select.epoll.fromfd(os.dup(self.loop._get_backend_id()))

try:
cb = lambda: None
Expand All @@ -288,8 +291,8 @@ def test_socket_sync_remove(self):

finally:
sock.close()
self.loop.close()
epoll.close()
self.loop.close()

def test_add_reader_or_writer_transport_fd(self):
def assert_raises():
Expand Down
Loading