Skip to content

Commit 26612ae

Browse files
authored
Merge branch 'master' into iscoroutinefunction-deprecation
2 parents 74e8760 + 8da4547 commit 26612ae

File tree

6 files changed

+98
-81
lines changed

6 files changed

+98
-81
lines changed

tests/test_dns.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ def test_getaddrinfo_22(self):
217217
self._test_getaddrinfo(payload, 80)
218218
self._test_getaddrinfo(payload, 80, type=socket.SOCK_STREAM)
219219

220+
def test_getaddrinfo_broadcast(self):
221+
self._test_getaddrinfo('<broadcast>', 80)
222+
self._test_getaddrinfo('<broadcast>', 80, type=socket.SOCK_STREAM)
223+
220224
######
221225

222226
def test_getnameinfo_1(self):

tests/test_fs_event.py

Lines changed: 67 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,87 @@
11
import asyncio
2+
import contextlib
23
import os.path
34
import tempfile
45

56
from uvloop import _testbase as tb
67
from uvloop.loop import FileSystemEvent
78

89

9-
class Test_UV_FS_EVENT_CHANGE(tb.UVTestCase):
10-
async def _file_writer(self):
11-
f = await self.q.get()
12-
while True:
13-
f.write('hello uvloop\n')
14-
f.flush()
15-
x = await self.q.get()
16-
if x is None:
17-
return
18-
19-
def fs_event_setup(self):
20-
self.change_event_count = 0
21-
self.fname = ''
22-
self.q = asyncio.Queue()
23-
24-
def event_cb(self, ev_fname: bytes, evt: FileSystemEvent):
25-
_d, fn = os.path.split(self.fname)
26-
self.assertEqual(ev_fname, fn)
27-
self.assertEqual(evt, FileSystemEvent.CHANGE)
28-
self.change_event_count += 1
29-
if self.change_event_count < 4:
30-
self.q.put_nowait(0)
31-
else:
32-
self.q.put_nowait(None)
10+
class Test_UV_FS_Event(tb.UVTestCase):
11+
def setUp(self):
12+
super().setUp()
13+
self.exit_stack = contextlib.ExitStack()
14+
self.tmp_dir = self.exit_stack.enter_context(
15+
tempfile.TemporaryDirectory()
16+
)
17+
18+
def tearDown(self):
19+
self.exit_stack.close()
20+
super().tearDown()
3321

3422
def test_fs_event_change(self):
35-
self.fs_event_setup()
36-
37-
async def run(write_task):
38-
self.q.put_nowait(tf)
39-
try:
40-
await asyncio.wait_for(write_task, 4)
41-
except asyncio.TimeoutError:
42-
write_task.cancel()
43-
44-
with tempfile.NamedTemporaryFile('wt') as tf:
45-
self.fname = tf.name.encode()
46-
h = self.loop._monitor_fs(tf.name, self.event_cb)
23+
change_event_count = 0
24+
filename = "fs_event_change.txt"
25+
path = os.path.join(self.tmp_dir, filename)
26+
q = asyncio.Queue()
27+
28+
with open(path, 'wt') as f:
29+
async def file_writer():
30+
while True:
31+
f.write('hello uvloop\n')
32+
f.flush()
33+
x = await q.get()
34+
if x is None:
35+
return
36+
37+
def event_cb(ev_fname: bytes, evt: FileSystemEvent):
38+
nonlocal change_event_count
39+
self.assertEqual(ev_fname, filename.encode())
40+
self.assertEqual(evt, FileSystemEvent.CHANGE)
41+
change_event_count += 1
42+
if change_event_count < 4:
43+
q.put_nowait(0)
44+
else:
45+
q.put_nowait(None)
46+
47+
h = self.loop._monitor_fs(path, event_cb)
48+
self.loop.run_until_complete(
49+
asyncio.sleep(0.1) # let monitor start
50+
)
4751
self.assertFalse(h.cancelled())
4852

49-
self.loop.run_until_complete(run(
50-
self.loop.create_task(self._file_writer())))
53+
self.loop.run_until_complete(asyncio.wait_for(file_writer(), 4))
5154
h.cancel()
5255
self.assertTrue(h.cancelled())
5356

54-
self.assertEqual(self.change_event_count, 4)
55-
56-
57-
class Test_UV_FS_EVENT_RENAME(tb.UVTestCase):
58-
async def _file_renamer(self):
59-
await self.q.get()
60-
os.rename(os.path.join(self.dname, self.changed_name),
61-
os.path.join(self.dname, self.changed_name + "-new"))
62-
await self.q.get()
63-
64-
def fs_event_setup(self):
65-
self.dname = ''
66-
self.changed_name = "hello_fs_event.txt"
67-
self.changed_set = {self.changed_name, self.changed_name + '-new'}
68-
self.q = asyncio.Queue()
69-
70-
def event_cb(self, ev_fname: bytes, evt: FileSystemEvent):
71-
ev_fname = ev_fname.decode()
72-
self.assertEqual(evt, FileSystemEvent.RENAME)
73-
self.changed_set.remove(ev_fname)
74-
if len(self.changed_set) == 0:
75-
self.q.put_nowait(None)
57+
self.assertEqual(change_event_count, 4)
7658

7759
def test_fs_event_rename(self):
78-
self.fs_event_setup()
79-
80-
async def run(write_task):
81-
self.q.put_nowait(0)
82-
try:
83-
await asyncio.wait_for(write_task, 4)
84-
except asyncio.TimeoutError:
85-
write_task.cancel()
86-
87-
with tempfile.TemporaryDirectory() as td_name:
88-
self.dname = td_name
89-
f = open(os.path.join(td_name, self.changed_name), 'wt')
60+
orig_name = "hello_fs_event.txt"
61+
new_name = "hello_fs_event_rename.txt"
62+
changed_set = {orig_name, new_name}
63+
event = asyncio.Event()
64+
65+
async def file_renamer():
66+
os.rename(os.path.join(self.tmp_dir, orig_name),
67+
os.path.join(self.tmp_dir, new_name))
68+
await event.wait()
69+
70+
def event_cb(ev_fname: bytes, evt: FileSystemEvent):
71+
ev_fname = ev_fname.decode()
72+
self.assertEqual(evt, FileSystemEvent.RENAME)
73+
changed_set.discard(ev_fname)
74+
if len(changed_set) == 0:
75+
event.set()
76+
77+
with open(os.path.join(self.tmp_dir, orig_name), 'wt') as f:
9078
f.write('hello!')
91-
f.close()
92-
h = self.loop._monitor_fs(td_name, self.event_cb)
93-
self.assertFalse(h.cancelled())
79+
h = self.loop._monitor_fs(self.tmp_dir, event_cb)
80+
self.loop.run_until_complete(asyncio.sleep(0.5)) # let monitor start
81+
self.assertFalse(h.cancelled())
9482

95-
self.loop.run_until_complete(run(
96-
self.loop.create_task(self._file_renamer())))
97-
h.cancel()
98-
self.assertTrue(h.cancelled())
83+
self.loop.run_until_complete(asyncio.wait_for(file_renamer(), 4))
84+
h.cancel()
85+
self.assertTrue(h.cancelled())
9986

100-
self.assertEqual(len(self.changed_set), 0)
87+
self.assertEqual(len(changed_set), 0)

tests/test_process.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,12 @@ async def cancel_make_transport():
685685
self.loop.run_until_complete(cancel_make_transport())
686686

687687
def test_cancel_post_init(self):
688+
if sys.version_info >= (3, 13) and self.implementation == 'asyncio':
689+
# https://github.com/python/cpython/issues/103847#issuecomment-3736561321
690+
# This test started to flake on CPython 3.13 and later,
691+
# so we skip it for asyncio tests until the issue is resolved.
692+
self.skipTest('flaky test on CPython 3.13+')
693+
688694
async def cancel_make_transport():
689695
coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol,
690696
*self.PROGRAM_BLOCKED)

tests/test_tcp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ async def client(addr):
405405
self.assertEqual(await reader.readexactly(2), b'OK')
406406

407407
re = r'(a bytes-like object)|(must be byte-ish)'
408-
if sys.version_info >= (3, 14):
408+
if sys.version_info >= (3, 13, 9):
409409
re += r'|(must be a bytes, bytearray, or memoryview object)'
410410
with self.assertRaisesRegex(TypeError, re):
411411
writer.write('AAAA')

tests/test_udp.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,22 @@ def test_udp_sendto_dns(self):
378378
s_transport.close()
379379
self.loop.run_until_complete(asyncio.sleep(0.01))
380380

381+
def test_udp_sendto_broadcast(self):
382+
coro = self.loop.create_datagram_endpoint(
383+
asyncio.DatagramProtocol,
384+
local_addr=('127.0.0.1', 0),
385+
family=socket.AF_INET)
386+
387+
s_transport, server = self.loop.run_until_complete(coro)
388+
389+
try:
390+
s_transport.sendto(b'aaaa', ('<broadcast>', 80))
391+
except ValueError as exc:
392+
raise AssertionError('sendto raises {}.'.format(exc))
393+
394+
s_transport.close()
395+
self.loop.run_until_complete(asyncio.sleep(0.01))
396+
381397
def test_send_after_close(self):
382398
coro = self.loop.create_datagram_endpoint(
383399
asyncio.DatagramProtocol,

uvloop/handles/udp.pyx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ cdef class UDPTransport(UVBaseTransport):
208208
if addr is None:
209209
saddr = NULL
210210
else:
211+
# resolve special hostname <broadcast> to the broadcast address before use
212+
if self._family == uv.AF_INET and addr[0] == '<broadcast>':
213+
addr = (b'255.255.255.255', addr[1])
214+
211215
try:
212216
__convert_pyaddr_to_sockaddr(self._family, addr,
213217
<system.sockaddr*>&saddr_st)

0 commit comments

Comments
 (0)