Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

Add Python 3.10 support, and remove deprecated API usage #50

Merged
merged 3 commits into from
Oct 23, 2021
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
python-version: ['3.7', '3.8', '3.9']
python-version: ['3.7', '3.8', '3.9', '3.10']
steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
Expand Down
1 change: 1 addition & 0 deletions changes/50.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added support for Python 3.10.
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ classifiers =
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Topic :: Software Development :: Libraries :: Python Modules
license = Apache 2.0
license_file = LICENSE
Expand Down
12 changes: 5 additions & 7 deletions src/gbulb/glib_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,7 @@ def _make_write_pipe_transport(self, pipe, protocol, waiter=None, extra=None):
channel = self._channel_from_fileobj(pipe)
return transports.PipeWriteTransport(self, channel, protocol, waiter, extra)

@asyncio.coroutine
def _make_subprocess_transport(
async def _make_subprocess_transport(
self,
protocol,
args,
Expand Down Expand Up @@ -400,14 +399,14 @@ def _make_subprocess_transport(
transport.get_pid(), self._child_watcher_callback, transport
)
try:
yield from waiter
await waiter
except Exception as exc:
err = exc
else:
err = None
if err is not None:
transport.close()
yield from transport._wait()
await transport._wait()
raise err

return transport
Expand Down Expand Up @@ -629,11 +628,10 @@ def sock_accept(self, sock):
def sock_connection_received(sock):
return (True, sock.accept())

@asyncio.coroutine
def accept_coro(future, conn):
async def accept_coro(future, conn):
# Coroutine closing the accept socket if the future is cancelled
try:
return (yield from future)
return (await future)
except CancelledError:
sock.close()
raise
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def gtk_policy():
return GtkEventLoopPolicy()


@pytest.yield_fixture(scope="function")
@pytest.fixture(scope="function")
def glib_loop(glib_policy):
loop = glib_policy.new_event_loop()
setup_test_loop(loop)
Expand All @@ -38,7 +38,7 @@ def glib_loop(glib_policy):
loop.close()


@pytest.yield_fixture(scope="function")
@pytest.fixture(scope="function")
def gtk_loop(gtk_policy):
loop = gtk_policy.new_event_loop()
setup_test_loop(loop)
Expand Down
65 changes: 28 additions & 37 deletions tests/test_glib_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ def test_attachment_order(self, glib_loop):
assert call_manager.mock_calls == expected_calls


@asyncio.coroutine
def no_op_coro():
async def no_op_coro():
pass


Expand Down Expand Up @@ -112,13 +111,15 @@ def test_remove_signal_handler_unhandled(self, glib_loop):
assert not glib_loop.remove_signal_handler(signal.SIGHUP)

@skipIf(is_windows, "Unix signal handlers are not supported on Windows")
@pytest.mark.filterwarnings('ignore:g_unix_signal_source_new')
def test_remove_signal_handler_sigkill(self, glib_loop):
import signal

with pytest.raises(RuntimeError):
glib_loop.add_signal_handler(signal.SIGKILL, None)

@skipIf(is_windows, "Unix signal handlers are not supported on Windows")
@pytest.mark.filterwarnings('ignore:g_unix_signal_source_new')
def test_remove_signal_handler_sigill(self, glib_loop):
import signal

Expand All @@ -128,10 +129,9 @@ def test_remove_signal_handler_sigill(self, glib_loop):
def test_run_until_complete_early_stop(self, glib_loop):
import asyncio

@asyncio.coroutine
def coro():
async def coro():
glib_loop.call_soon(glib_loop.stop)
yield from asyncio.sleep(5)
await asyncio.sleep(5)

with pytest.raises(RuntimeError):
glib_loop.run_until_complete(coro())
Expand Down Expand Up @@ -487,25 +487,23 @@ def test_subprocesses_read_after_closure(glib_loop):

gbulb.install()

@asyncio.coroutine
def coro():
proc = yield from asyncio.create_subprocess_exec(
async def coro():
proc = await asyncio.create_subprocess_exec(
"cat",
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
loop=glib_loop,
)

proc.stdin.write(b"hey\n")
yield from proc.stdin.drain()
await proc.stdin.drain()

proc.stdin.close()

out = yield from proc.stdout.read()
out = await proc.stdout.read()
assert out == b"hey\n"

yield from proc.wait()
await proc.wait()

glib_loop.run_until_complete(coro())

Expand All @@ -516,71 +514,64 @@ def test_subprocesses_readline_without_closure(glib_loop):

gbulb.install()

@asyncio.coroutine
def run():
proc = yield from asyncio.create_subprocess_exec(
async def run():
proc = await asyncio.create_subprocess_exec(
"cat",
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
loop=glib_loop,
)

try:
proc.stdin.write(b"test line\n")
yield from proc.stdin.drain()
await proc.stdin.drain()

line = yield from asyncio.wait_for(
proc.stdout.readline(), timeout=5, loop=glib_loop
)
line = await asyncio.wait_for(proc.stdout.readline(), timeout=5)
assert line == b"test line\n"

proc.stdin.close()

line = yield from asyncio.wait_for(
proc.stdout.readline(), timeout=5, loop=glib_loop
)
line = await asyncio.wait_for(proc.stdout.readline(), timeout=5)
assert line == b""
finally:
yield from proc.wait()
await proc.wait()

glib_loop.run_until_complete(run())


def test_sockets(glib_loop):
server_done = asyncio.Event(loop=glib_loop)
server_done = asyncio.Event()
server_done._loop = glib_loop
server_success = False

@asyncio.coroutine
def cb(reader, writer):
async def cb(reader, writer):
nonlocal server_success

writer.write(b"cool data\n")
yield from writer.drain()
await writer.drain()

print("reading")
d = yield from reader.readline()
d = await reader.readline()
print("hrm", d)
server_success = d == b"thank you\n"

writer.close()
server_done.set()

@asyncio.coroutine
def run():
s = yield from asyncio.start_server(cb, "127.0.0.1", 0, loop=glib_loop)
reader, writer = yield from asyncio.open_connection(
"127.0.0.1", s.sockets[0].getsockname()[-1], loop=glib_loop
async def run():
s = await asyncio.start_server(cb, "127.0.0.1", 0)
reader, writer = await asyncio.open_connection(
"127.0.0.1", s.sockets[0].getsockname()[-1]
)

d = yield from reader.readline()
d = await reader.readline()
assert d == b"cool data\n"

writer.write(b"thank you\n")
yield from writer.drain()
await writer.drain()

writer.close()

yield from server_done.wait()
await server_done.wait()

assert server_success

Expand Down
3 changes: 3 additions & 0 deletions tests/test_gtk.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import pytest

try:
import gi
gi.require_version('Gtk', '3.0')

from gi.repository import Gtk
except ImportError: # pragma: no cover
Gtk = None
Expand Down
15 changes: 7 additions & 8 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def test_wait_signal(glib_loop):

class TestObject(GObject.GObject):
__gsignals__ = {
"foo": (GObject.SIGNAL_RUN_LAST, None, (str,)),
"foo": (GObject.SignalFlags.RUN_LAST, None, (str,)),
}

t = TestObject()
Expand All @@ -71,15 +71,14 @@ def emitter():

called = False

@asyncio.coroutine
def waiter():
async def waiter():
nonlocal called
r = yield from wait_signal(t, "foo", loop=glib_loop)
r = await wait_signal(t, "foo")
assert r == (t, "frozen brains tell no tales")
called = True

glib_loop.run_until_complete(
asyncio.wait([waiter(), emitter()], timeout=1, loop=glib_loop)
asyncio.wait([waiter(), emitter()], timeout=1)
)

assert called
Expand All @@ -92,7 +91,7 @@ def test_wait_signal_cancel(glib_loop):

class TestObject(GObject.GObject):
__gsignals__ = {
"foo": (GObject.SIGNAL_RUN_LAST, None, (str,)),
"foo": (GObject.SignalFlags.RUN_LAST, None, (str,)),
}

t = TestObject()
Expand All @@ -108,7 +107,7 @@ def waiter():
nonlocal cancelled
yield

r = wait_signal(t, "foo", loop=glib_loop)
r = wait_signal(t, "foo")

@r.add_done_callback
def caller(r):
Expand All @@ -120,7 +119,7 @@ def caller(r):
cancelled = True

glib_loop.run_until_complete(
asyncio.wait([waiter(), emitter()], timeout=1, loop=glib_loop)
asyncio.wait([waiter(), emitter()], timeout=1)
)

assert cancelled
Expand Down