Skip to content

Commit c3a5ec8

Browse files
pfreixes1st1
authored andcommitted
Support for PY37 without contextvars.
This MR aligns the uvloop code to become compatible, not production ready, with PY37 adding the following changes: * Support for the new API used behind the set_debug function. * Adds the context=None KW to those functions that will receive it when uvloop runs with PY37. * Former asyncio.test_utils moved as an uvloop test resource. -- Yury: the original PR for this change is #138. I stripped out all the CI bits and squashed all commits by hand. The CI will be addressed later.
1 parent 7384b22 commit c3a5ec8

File tree

9 files changed

+123
-117
lines changed

9 files changed

+123
-117
lines changed

tests/test_pipes.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import asyncio
22
import io
33
import os
4+
import socket
45

5-
from asyncio import test_utils
66
from uvloop import _testbase as tb
77

88

@@ -81,11 +81,11 @@ def connect():
8181
self.loop.run_until_complete(connect())
8282

8383
os.write(wpipe, b'1')
84-
test_utils.run_until(self.loop, lambda: proto.nbytes >= 1)
84+
tb.run_until(self.loop, lambda: proto.nbytes >= 1)
8585
self.assertEqual(1, proto.nbytes)
8686

8787
os.write(wpipe, b'2345')
88-
test_utils.run_until(self.loop, lambda: proto.nbytes >= 5)
88+
tb.run_until(self.loop, lambda: proto.nbytes >= 5)
8989
self.assertEqual(['INITIAL', 'CONNECTED'], proto.state)
9090
self.assertEqual(5, proto.nbytes)
9191

@@ -114,11 +114,11 @@ def connect():
114114
self.loop.run_until_complete(connect())
115115

116116
os.write(slave, b'1')
117-
test_utils.run_until(self.loop, lambda: proto.nbytes)
117+
tb.run_until(self.loop, lambda: proto.nbytes)
118118
self.assertEqual(1, proto.nbytes)
119119

120120
os.write(slave, b'2345')
121-
test_utils.run_until(self.loop, lambda: proto.nbytes >= 5)
121+
tb.run_until(self.loop, lambda: proto.nbytes >= 5)
122122
self.assertEqual(['INITIAL', 'CONNECTED'], proto.state)
123123
self.assertEqual(5, proto.nbytes)
124124

@@ -158,11 +158,11 @@ def reader(data):
158158
data += chunk
159159
return len(data)
160160

161-
test_utils.run_until(self.loop, lambda: reader(data) >= 1)
161+
tb.run_until(self.loop, lambda: reader(data) >= 1)
162162
self.assertEqual(b'1', data)
163163

164164
transport.write(b'2345')
165-
test_utils.run_until(self.loop, lambda: reader(data) >= 5)
165+
tb.run_until(self.loop, lambda: reader(data) >= 5)
166166
self.assertEqual(b'12345', data)
167167
self.assertEqual('CONNECTED', proto.state)
168168

@@ -177,7 +177,7 @@ def reader(data):
177177
self.assertEqual('CLOSED', proto.state)
178178

179179
def test_write_pipe_disconnect_on_close(self):
180-
rsock, wsock = test_utils.socketpair()
180+
rsock, wsock = socket.socketpair()
181181
rsock.setblocking(False)
182182

183183
pipeobj = io.open(wsock.detach(), 'wb', 1024)
@@ -223,12 +223,12 @@ def reader(data):
223223
data += chunk
224224
return len(data)
225225

226-
test_utils.run_until(self.loop, lambda: reader(data) >= 1,
226+
tb.run_until(self.loop, lambda: reader(data) >= 1,
227227
timeout=10)
228228
self.assertEqual(b'1', data)
229229

230230
transport.write(b'2345')
231-
test_utils.run_until(self.loop, lambda: reader(data) >= 5,
231+
tb.run_until(self.loop, lambda: reader(data) >= 5,
232232
timeout=10)
233233
self.assertEqual(b'12345', data)
234234
self.assertEqual('CONNECTED', proto.state)

tests/test_process.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import time
1010
import unittest
1111

12-
from asyncio import test_utils
1312
from uvloop import _testbase as tb
1413

1514

@@ -504,7 +503,7 @@ def cancel_make_transport():
504503

505504
# ignore the log:
506505
# "Exception during subprocess creation, kill the subprocess"
507-
with test_utils.disable_logger():
506+
with tb.disable_logger():
508507
self.loop.run_until_complete(cancel_make_transport())
509508

510509
def test_cancel_post_init(self):
@@ -522,9 +521,9 @@ def cancel_make_transport():
522521

523522
# ignore the log:
524523
# "Exception during subprocess creation, kill the subprocess"
525-
with test_utils.disable_logger():
524+
with tb.disable_logger():
526525
self.loop.run_until_complete(cancel_make_transport())
527-
test_utils.run_briefly(self.loop)
526+
tb.run_briefly(self.loop)
528527

529528

530529
class Test_UV_Process(_TestProcess, tb.UVTestCase):

tests/test_tasks.py

Lines changed: 16 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import asyncio
44

5-
from asyncio import test_utils
65
from uvloop import _testbase as tb
76

87

@@ -30,59 +29,6 @@ def format_coroutine(qualname, state, src, source_traceback, generator=False):
3029

3130
class _TestTasks:
3231

33-
def test_task_repr(self):
34-
self.loop.set_debug(False)
35-
36-
@asyncio.coroutine
37-
def notmuch():
38-
yield from []
39-
return 'abc'
40-
41-
# test coroutine function
42-
self.assertEqual(notmuch.__name__, 'notmuch')
43-
self.assertEqual(notmuch.__qualname__,
44-
'_TestTasks.test_task_repr.<locals>.notmuch')
45-
self.assertEqual(notmuch.__module__, __name__)
46-
47-
filename, lineno = test_utils.get_function_source(notmuch)
48-
src = "%s:%s" % (filename, lineno)
49-
50-
# test coroutine object
51-
gen = notmuch()
52-
coro_qualname = '_TestTasks.test_task_repr.<locals>.notmuch'
53-
self.assertEqual(gen.__name__, 'notmuch')
54-
self.assertEqual(gen.__qualname__, coro_qualname)
55-
56-
# test pending Task
57-
t = asyncio.Task(gen, loop=self.loop)
58-
t.add_done_callback(Dummy())
59-
60-
coro = format_coroutine(coro_qualname, 'running', src,
61-
t._source_traceback, generator=True)
62-
self.assertEqual(repr(t),
63-
'<Task pending %s cb=[<Dummy>()]>' % coro)
64-
65-
# test canceling Task
66-
t.cancel() # Does not take immediate effect!
67-
self.assertEqual(repr(t),
68-
'<Task cancelling %s cb=[<Dummy>()]>' % coro)
69-
70-
# test canceled Task
71-
self.assertRaises(asyncio.CancelledError,
72-
self.loop.run_until_complete, t)
73-
coro = format_coroutine(coro_qualname, 'done', src,
74-
t._source_traceback)
75-
self.assertEqual(repr(t),
76-
'<Task cancelled %s>' % coro)
77-
78-
# test finished Task
79-
t = asyncio.Task(notmuch(), loop=self.loop)
80-
self.loop.run_until_complete(t)
81-
coro = format_coroutine(coro_qualname, 'done', src,
82-
t._source_traceback)
83-
self.assertEqual(repr(t),
84-
"<Task finished %s result='abc'>" % coro)
85-
8632
def test_task_basics(self):
8733
@asyncio.coroutine
8834
def outer():
@@ -109,7 +55,7 @@ def task():
10955
return 12
11056

11157
t = self.create_task(task())
112-
test_utils.run_briefly(self.loop) # start coro
58+
tb.run_briefly(self.loop) # start coro
11359
t.cancel()
11460
self.assertRaises(
11561
asyncio.CancelledError, self.loop.run_until_complete, t)
@@ -126,7 +72,7 @@ def task():
12672
return 12
12773

12874
t = self.create_task(task())
129-
test_utils.run_briefly(self.loop) # start task
75+
tb.run_briefly(self.loop) # start task
13076
f.cancel()
13177
with self.assertRaises(asyncio.CancelledError):
13278
self.loop.run_until_complete(t)
@@ -143,7 +89,7 @@ def task():
14389

14490
t = self.create_task(task())
14591
self.assertEqual(asyncio.Task.all_tasks(loop=self.loop), {t})
146-
test_utils.run_briefly(self.loop)
92+
tb.run_briefly(self.loop)
14793

14894
f.cancel()
14995
t.cancel()
@@ -168,10 +114,10 @@ def task():
168114
return 42
169115

170116
t = self.create_task(task())
171-
test_utils.run_briefly(self.loop)
117+
tb.run_briefly(self.loop)
172118
self.assertIs(t._fut_waiter, fut1) # White-box test.
173119
fut1.set_result(None)
174-
test_utils.run_briefly(self.loop)
120+
tb.run_briefly(self.loop)
175121
self.assertIs(t._fut_waiter, fut2) # White-box test.
176122
t.cancel()
177123
self.assertTrue(fut2.cancelled())
@@ -195,14 +141,14 @@ def task():
195141
return res
196142

197143
t = self.create_task(task())
198-
test_utils.run_briefly(self.loop)
144+
tb.run_briefly(self.loop)
199145
self.assertIs(t._fut_waiter, fut1) # White-box test.
200146
fut1.set_result(None)
201-
test_utils.run_briefly(self.loop)
147+
tb.run_briefly(self.loop)
202148
self.assertIs(t._fut_waiter, fut2) # White-box test.
203149
t.cancel()
204150
self.assertTrue(fut2.cancelled())
205-
test_utils.run_briefly(self.loop)
151+
tb.run_briefly(self.loop)
206152
self.assertIs(t._fut_waiter, fut3) # White-box test.
207153
fut3.set_result(42)
208154
res = self.loop.run_until_complete(t)
@@ -232,7 +178,8 @@ def notmutch():
232178
raise BaseException()
233179

234180
task = self.create_task(notmutch())
235-
self.assertRaises(BaseException, task._step)
181+
with self.assertRaises(BaseException):
182+
tb.run_briefly(self.loop)
236183

237184
self.assertTrue(task.done())
238185
self.assertIsInstance(task.exception(), BaseException)
@@ -245,7 +192,7 @@ def __init__(self, *args, **kwds):
245192
self.cb_added = False
246193
super().__init__(*args, **kwds)
247194

248-
def add_done_callback(self, fn):
195+
def add_done_callback(self, fn, context=None):
249196
self.cb_added = True
250197
super().add_done_callback(fn)
251198

@@ -258,12 +205,12 @@ def wait_for_future():
258205
result = yield from fut
259206

260207
t = self.create_task(wait_for_future())
261-
test_utils.run_briefly(self.loop)
208+
tb.run_briefly(self.loop)
262209
self.assertTrue(fut.cb_added)
263210

264211
res = object()
265212
fut.set_result(res)
266-
test_utils.run_briefly(self.loop)
213+
tb.run_briefly(self.loop)
267214
self.assertIs(res, result)
268215
self.assertTrue(t.done())
269216
self.assertIsNone(t.result())
@@ -356,7 +303,7 @@ def outer():
356303
proof += 10
357304

358305
f = asyncio.ensure_future(outer(), loop=self.loop)
359-
test_utils.run_briefly(self.loop)
306+
tb.run_briefly(self.loop)
360307
f.cancel()
361308
self.loop.run_until_complete(f)
362309
self.assertEqual(proof, 101)
@@ -381,12 +328,12 @@ def outer():
381328
proof += 100
382329

383330
f = asyncio.ensure_future(outer(), loop=self.loop)
384-
test_utils.run_briefly(self.loop)
331+
tb.run_briefly(self.loop)
385332
f.cancel()
386333
self.assertRaises(
387334
asyncio.CancelledError, self.loop.run_until_complete, f)
388335
waiter.set_result(None)
389-
test_utils.run_briefly(self.loop)
336+
tb.run_briefly(self.loop)
390337
self.assertEqual(proof, 1)
391338

392339

tests/test_udp.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import unittest
44
import sys
55

6-
from asyncio import test_utils
76
from uvloop import _testbase as tb
87

98

@@ -77,9 +76,9 @@ def datagram_received(self, data, addr):
7776
self.assertIs(client.transport, transport)
7877

7978
transport.sendto(b'xxx')
80-
test_utils.run_until(self.loop, lambda: server.nbytes)
79+
tb.run_until(self.loop, lambda: server.nbytes)
8180
self.assertEqual(3, server.nbytes)
82-
test_utils.run_until(self.loop, lambda: client.nbytes)
81+
tb.run_until(self.loop, lambda: client.nbytes)
8382

8483
# received
8584
self.assertEqual(8, client.nbytes)

tests/test_unix.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import tempfile
66
import time
77
import unittest
8+
import sys
89

910
from uvloop import _testbase as tb
1011

@@ -362,6 +363,7 @@ async def client():
362363
self.assertIn(excs[0].__class__,
363364
(BrokenPipeError, ConnectionResetError))
364365

366+
@unittest.skipUnless(sys.version_info < (3, 7), 'Python version must be < 3.7')
365367
def test_transport_unclosed_warning(self):
366368
async def test(sock):
367369
return await self.loop.create_unix_connection(

uvloop/_testbase.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,3 +483,46 @@ def _handle_client(self, sock):
483483
@property
484484
def addr(self):
485485
return self._sock.getsockname()
486+
487+
488+
###############################################################################
489+
# A few helpers from asyncio/tests/testutils.py
490+
###############################################################################
491+
492+
493+
def run_briefly(loop):
494+
async def once():
495+
pass
496+
gen = once()
497+
t = loop.create_task(gen)
498+
# Don't log a warning if the task is not done after run_until_complete().
499+
# It occurs if the loop is stopped or if a task raises a BaseException.
500+
t._log_destroy_pending = False
501+
try:
502+
loop.run_until_complete(t)
503+
finally:
504+
gen.close()
505+
506+
507+
def run_until(loop, pred, timeout=30):
508+
deadline = time.time() + timeout
509+
while not pred():
510+
if timeout is not None:
511+
timeout = deadline - time.time()
512+
if timeout <= 0:
513+
raise asyncio.futures.TimeoutError()
514+
loop.run_until_complete(asyncio.tasks.sleep(0.001, loop=loop))
515+
516+
517+
@contextlib.contextmanager
518+
def disable_logger():
519+
"""Context manager to disable asyncio logger.
520+
521+
For example, it can be used to ignore warnings in debug mode.
522+
"""
523+
old_level = asyncio.log.logger.level
524+
try:
525+
asyncio.log.logger.setLevel(logging.CRITICAL + 1)
526+
yield
527+
finally:
528+
asyncio.log.logger.setLevel(old_level)

uvloop/includes/stdlib.pxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ cdef aio_iscoroutinefunction = asyncio.iscoroutinefunction
3838
cdef aio_BaseProtocol = asyncio.BaseProtocol
3939
cdef aio_Protocol = asyncio.Protocol
4040
cdef aio_SSLProtocol = asyncio.sslproto.SSLProtocol
41-
cdef aio_debug_wrapper = asyncio.coroutines.debug_wrapper
4241
cdef aio_isfuture = getattr(asyncio, 'isfuture', None)
4342
cdef aio_get_running_loop = getattr(asyncio, '_get_running_loop', None)
4443
cdef aio_set_running_loop = getattr(asyncio, '_set_running_loop', None)
44+
cdef aio_debug_wrapper = getattr(asyncio.coroutines, 'debug_wrapper', None)
4545

4646
cdef col_deque = collections.deque
4747
cdef col_Iterable = collections.Iterable

0 commit comments

Comments
 (0)