From ee5ad26a754984d867594809cb5c040be9cd7281 Mon Sep 17 00:00:00 2001 From: Fantix King Date: Mon, 23 Oct 2023 03:04:03 +0900 Subject: [PATCH] Drop support of Python 3.7 and update CI (#578) * Drop support of Python 3.7 * Upgrade and pin action revisions in CI * Exclude C files in wheel dist --- .github/workflows/release.yml | 33 ++++++++++++--------------- .github/workflows/tests.yml | 8 +++---- README.rst | 4 ++-- docs/dev/index.rst | 2 +- docs/user/index.rst | 2 +- pyproject.toml | 6 +++-- setup.py | 4 ++-- tests/test_base.py | 6 +---- tests/test_process.py | 3 --- tests/test_signals.py | 19 ---------------- tests/test_sockets.py | 30 ------------------------ tests/test_tcp.py | 43 ----------------------------------- tests/test_udp.py | 6 ----- uvloop/loop.pyx | 2 +- 14 files changed, 31 insertions(+), 137 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ddbed23..cf707d07 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Validate release PR - uses: edgedb/action-release/validate-pr@master + uses: edgedb/action-release/validate-pr@bae6b9134e872166b43d218dd79397c851c41c9a id: checkver with: require_team: Release Managers @@ -37,7 +37,7 @@ jobs: mkdir -p dist/ echo "${VERSION}" > dist/VERSION - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: dist path: dist/ @@ -50,12 +50,12 @@ jobs: PIP_DISABLE_PIP_VERSION_CHECK: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: fetch-depth: 50 submodules: true - - uses: actions/setup-python@v4 + - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 with: python-version: 3.x @@ -64,7 +64,7 @@ jobs: python -m pip install --upgrade setuptools wheel pip python setup.py sdist - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: dist path: dist/*.tar.* @@ -76,16 +76,13 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - cibw_python: ["cp37-*", "cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*"] + cibw_python: ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*"] cibw_arch: ["x86_64", "aarch64", "universal2"] exclude: - os: ubuntu-latest cibw_arch: universal2 - os: macos-latest cibw_arch: aarch64 - - os: macos-latest - cibw_python: "cp37-*" - cibw_arch: universal2 defaults: run: @@ -95,14 +92,14 @@ jobs: PIP_DISABLE_PIP_VERSION_CHECK: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: fetch-depth: 50 submodules: true - name: Set up QEMU if: matrix.os == 'ubuntu-latest' && matrix.cibw_arch == 'aarch64' - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 with: platforms: arm64 @@ -111,14 +108,14 @@ jobs: run: | brew install gnu-sed libtool autoconf automake - - uses: pypa/cibuildwheel@v2.16.2 + - uses: pypa/cibuildwheel@fff9ec32ed25a9c576750c91e06b410ed0c15db7 # v2.16.2 env: CIBW_BUILD_VERBOSITY: 1 CIBW_BUILD: ${{ matrix.cibw_python }} CIBW_ARCHS: ${{ matrix.cibw_arch }} CIBW_TEST_SKIP: "*universal2:arm64" - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: dist path: wheelhouse/*.whl @@ -128,12 +125,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: fetch-depth: 5 submodules: false - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: dist path: dist/ @@ -142,11 +139,11 @@ jobs: id: relver run: | set -e - echo ::set-output name=version::$(cat dist/VERSION) + echo version=$(cat dist/VERSION) >> $GITHUB_OUTPUT rm dist/VERSION - name: Merge and tag the PR - uses: edgedb/action-release/merge@master + uses: edgedb/action-release/merge@bae6b9134e872166b43d218dd79397c851c41c9a with: github_token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }} ssh_key: ${{ secrets.RELEASE_BOT_SSH_KEY }} @@ -169,7 +166,7 @@ jobs: ls -al dist/ - name: Upload to PyPI - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@b7f401de30cb6434a1e19f805ff006643653240e # v1.8.10 with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3aee2a99..61cf881f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,20 +14,20 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] os: [ubuntu-latest, macos-latest] env: PIP_DISABLE_PIP_VERSION_CHECK: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: fetch-depth: 50 submodules: true - name: Check if release PR. - uses: edgedb/action-release/validate-pr@master + uses: edgedb/action-release/validate-pr@bae6b9134e872166b43d218dd79397c851c41c9a id: release with: github_token: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }} @@ -37,7 +37,7 @@ jobs: __version__\s*=\s*(?:['"])([[:PEP440:]])(?:['"]) - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1 if: steps.release.outputs.version == 0 with: python-version: ${{ matrix.python-version }} diff --git a/README.rst b/README.rst index 45fa7f8f..fe6c000d 100644 --- a/README.rst +++ b/README.rst @@ -39,7 +39,7 @@ about it. Installation ------------ -uvloop requires Python 3.7 or greater and is available on PyPI. +uvloop requires Python 3.8 or greater and is available on PyPI. Use pip to install it:: $ pip install uvloop @@ -96,7 +96,7 @@ snippet can be used: Building From Source -------------------- -To build uvloop, you'll need Python 3.7 or greater: +To build uvloop, you'll need Python 3.8 or greater: 1. Clone the repository: diff --git a/docs/dev/index.rst b/docs/dev/index.rst index 03bf4e3b..6f612397 100644 --- a/docs/dev/index.rst +++ b/docs/dev/index.rst @@ -28,7 +28,7 @@ from the `libuv` Github repository. Build ----- -To build `uvloop`, you'll need ``Cython`` and Python 3.7. +To build `uvloop`, you'll need ``Cython`` and Python 3.8. .. note:: diff --git a/docs/user/index.rst b/docs/user/index.rst index b2e70f0f..b1c26f38 100644 --- a/docs/user/index.rst +++ b/docs/user/index.rst @@ -8,7 +8,7 @@ uvloop. Installation ------------ -`uvloop` is available from PyPI. It requires Python 3.7. +`uvloop` is available from PyPI. It requires Python 3.8. Use pip to install it. diff --git a/pyproject.toml b/pyproject.toml index 0d6d472a..c4f93f0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "uvloop" description = "Fast implementation of asyncio event loop on top of libuv" authors = [{name = "Yury Selivanov", email = "yury@magic.io"}] -requires-python = '>=3.7.0' +requires-python = '>=3.8.0' readme = "README.rst" license = {text = "MIT License"} dynamic = ["version"] @@ -19,7 +19,6 @@ classifiers = [ "Operating System :: POSIX", "Operating System :: MacOS :: MacOS X", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", @@ -64,6 +63,9 @@ build-backend = "setuptools.build_meta" zip-safe = false packages = ["uvloop"] +[tool.setuptools.exclude-package-data] +"*" = ["*.c", "*.h"] + [tool.cibuildwheel] build-frontend = "build" test-extras = "test" diff --git a/setup.py b/setup.py index 5afaee97..ba15af50 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,8 @@ import sys vi = sys.version_info -if vi < (3, 7): - raise RuntimeError('uvloop requires Python 3.7 or greater') +if vi < (3, 8): + raise RuntimeError('uvloop requires Python 3.8 or greater') if sys.platform in ('win32', 'cygwin', 'cli'): raise RuntimeError('uvloop does not support Windows at the moment') diff --git a/tests/test_base.py b/tests/test_base.py index a8eb3b4d..86bbd1d0 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -561,9 +561,6 @@ async def coro(): self.loop.run_until_complete(task) def test_set_task_name(self): - if self.implementation == 'asyncio' and sys.version_info < (3, 8, 0): - raise unittest.SkipTest('unsupported task name') - self.loop._process_events = mock.Mock() result = None @@ -586,8 +583,7 @@ async def coro(): self.assertIsNone(self.loop.get_task_factory()) task = self.loop.create_task(coro(), name="mytask") self.assertFalse(isinstance(task, MyTask)) - if sys.version_info >= (3, 8, 0): - self.assertEqual(task.get_name(), "mytask") + self.assertEqual(task.get_name(), "mytask") self.loop.run_until_complete(task) self.loop.set_task_factory(factory) diff --git a/tests/test_process.py b/tests/test_process.py index ade4742c..bfcbba17 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -166,9 +166,6 @@ async def test(): self.loop.run_until_complete(test()) - @unittest.skipIf(sys.version_info < (3, 8, 0), - "3.5 to 3.7 does not support path-like objects " - "in the asyncio subprocess API") def test_process_executable_2(self): async def test(): proc = await asyncio.create_subprocess_exec( diff --git a/tests/test_signals.py b/tests/test_signals.py index 9ee972fe..7e8ed220 100644 --- a/tests/test_signals.py +++ b/tests/test_signals.py @@ -3,8 +3,6 @@ import subprocess import sys import time -import unittest -import uvloop from uvloop import _testbase as tb @@ -395,23 +393,6 @@ def test_signals_no_SIGCHLD(self): self.loop.add_signal_handler(signal.SIGCHLD, lambda *a: None) - @unittest.skipIf(sys.version_info[:3] >= (3, 8, 0), - 'in 3.8 a ThreadedChildWatcher is used ' - '(does not rely on SIGCHLD)') - def test_asyncio_add_watcher_SIGCHLD_nop(self): - asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy()) - asyncio.get_event_loop_policy().get_child_watcher() - - try: - loop = uvloop.new_event_loop() - with self.assertWarnsRegex( - RuntimeWarning, - "asyncio is trying to install its ChildWatcher"): - asyncio.set_event_loop(loop) - finally: - asyncio.set_event_loop(None) - loop.close() - class Test_AIO_Signals(_TestSignal, tb.AIOTestCase): NEW_LOOP = 'asyncio.new_event_loop()' diff --git a/tests/test_sockets.py b/tests/test_sockets.py index 63bdc33f..e7c335e1 100644 --- a/tests/test_sockets.py +++ b/tests/test_sockets.py @@ -20,36 +20,6 @@ async def recv_all(self, sock, nbytes): buf += await self.loop.sock_recv(sock, nbytes - len(buf)) return buf - def test_socket_connect_recv_send(self): - if sys.version_info[:3] >= (3, 8, 0): - # @asyncio.coroutine is deprecated in 3.8 - raise unittest.SkipTest() - - def srv_gen(sock): - sock.send(b'helo') - data = sock.recv_all(4 * _SIZE) - self.assertEqual(data, b'ehlo' * _SIZE) - sock.send(b'O') - sock.send(b'K') - - # We use @asyncio.coroutine & `yield from` to test - # the compatibility of Cython's 'async def' coroutines. - @asyncio.coroutine - def client(sock, addr): - yield from self.loop.sock_connect(sock, addr) - data = yield from self.recv_all(sock, 4) - self.assertEqual(data, b'helo') - yield from self.loop.sock_sendall(sock, b'ehlo' * _SIZE) - data = yield from self.recv_all(sock, 2) - self.assertEqual(data, b'OK') - - with self.tcp_server(srv_gen) as srv: - - sock = socket.socket() - with sock: - sock.setblocking(False) - self.loop.run_until_complete(client(sock, srv.addr)) - def test_socket_accept_recv_send(self): async def server(): sock = socket.socket() diff --git a/tests/test_tcp.py b/tests/test_tcp.py index 51f45664..812e62b8 100644 --- a/tests/test_tcp.py +++ b/tests/test_tcp.py @@ -1063,49 +1063,6 @@ async def run(): self.loop.run_until_complete(run()) - @unittest.skipIf(sys.version_info[:3] >= (3, 8, 0), - "3.8 has a different method of GCing unclosed streams") - def test_tcp_handle_unclosed_gc(self): - fut = self.loop.create_future() - - async def server(reader, writer): - writer.transport.abort() - fut.set_result(True) - - async def run(): - addr = srv.sockets[0].getsockname() - await asyncio.open_connection(*addr) - await fut - srv.close() - await srv.wait_closed() - - srv = self.loop.run_until_complete(asyncio.start_server( - server, - '127.0.0.1', 0, - family=socket.AF_INET)) - - if self.loop.get_debug(): - rx = r'unclosed resource