diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml index 9a6d9d2..1f6f371 100644 --- a/.github/workflows/weekly.yml +++ b/.github/workflows/weekly.yml @@ -13,24 +13,16 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Setup uv + - uses: actions/setup-uv@v5 with: + enable-cache: true python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - make requirements - - name: Lint - run: | - make lint - - name: Format - run: | - make format && git diff --quiet HEAD - - name: Type check - run: | - make type-check + - name: Sync Environment + run: uv sync --frozen - name: Test - run: | - make test + run: make test + - name: Type check + run: make type-check # vim: sw=2 diff --git a/Makefile b/Makefile index 9967f70..89b0b65 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,10 @@ # substring expression UT ?= +# When enabled, tests/type-checking will be more verbose and not capture +# stdout/err. +V ?= + # Run uv offline by default OFFLINE ?= 1 @@ -44,8 +48,11 @@ format: lint: @$(UV) run flake8 --filename='*' $(LINT_TARGETS) type-check: - @$(UV) run mypy $(PACKAGE) test/ example.py + @$(UV) run mypy $(if $(V),--show-error-context) $(PACKAGE) test/ example.py test: @$(UV) run pytest --log-level=DEBUG -W default -v -s $(TEST_TARGETS): - @$(UV) run pytest --log-cli-level=DEBUG -W default -v -s test/$(@).py $(if $(UT),-k $(UT),) + @$(UV) run pytest --log-cli-level=DEBUG -W default -v \ + test/$(@).py \ + $(if $(V),,-s) \ + $(if $(UT),-k $(UT)) diff --git a/test/test_aio.py b/test/test_aio.py index 50501d3..33e234d 100644 --- a/test/test_aio.py +++ b/test/test_aio.py @@ -393,6 +393,10 @@ async def test_unconnected_sender(addr: _Address) -> None: connected.close() +@pytest.mark.skipif( + sys.version_info >= (3, 13), + reason="https://github.com/python/cpython/issues/135444", +) @pytest.mark.asyncio async def test_protocol_pause_resume( monkeypatch: pytest.MonkeyPatch, @@ -441,21 +445,22 @@ async def passthrough() -> None: """ pass - mock_socket = unittest.mock.create_autospec(socket.socket) - mock_socket.family = socket.AF_INET - mock_socket.type = socket.SOCK_DGRAM - - with monkeypatch.context() as ctx: + with monkeypatch.context() as ctx, socket.socket( + socket.AF_INET, socket.SOCK_DGRAM + ) as sock: + sock.setblocking(False) ctx.setattr(asyncio_dgram.aio, "Protocol", TestableProtocol) + mock_socket = unittest.mock.create_autospec(socket.socket) + mock_socket.family = socket.AF_INET + mock_socket.type = socket.SOCK_DGRAM + mock_socket.fileno.return_value = sock.fileno() + client = await asyncio_dgram.from_socket(mock_socket) assert isinstance(client, asyncio_dgram.aio.DatagramClient) assert TestableProtocol.instance is not None mock_socket.send.side_effect = BlockingIOError - mock_socket.fileno.return_value = os.open( - tmp_path / "socket", os.O_RDONLY | os.O_CREAT - ) with monkeypatch.context() as ctx2: ctx2.setattr(client._drained, "wait", passthrough) @@ -466,9 +471,6 @@ async def passthrough() -> None: assert not TestableProtocol.instance._drained.is_set() mock_socket.send.side_effect = None - fd = os.open(tmp_path / "socket", os.O_WRONLY) - os.write(fd, b"\n") - os.close(fd) with monkeypatch.context() as ctx2: ctx2.setattr(client._drained, "wait", passthrough) @@ -479,8 +481,6 @@ async def passthrough() -> None: assert TestableProtocol.instance.resume_writing_called == 1 assert TestableProtocol.instance._drained.is_set() - os.close(mock_socket.fileno.return_value) - @pytest.mark.asyncio async def test_transport_closed() -> None: