uvloop-0.8.1/ 0000775 0003720 0003720 00000000000 13156037661 013716 5 ustar travis travis 0000000 0000000 uvloop-0.8.1/MANIFEST.in 0000664 0003720 0003720 00000000566 13156036740 015460 0 ustar travis travis 0000000 0000000 recursive-include docs *.py *.rst
recursive-include examples *.py
recursive-include tests *.py *.pem
recursive-include uvloop *.pyx *.pxd *.pxi *.py *.c *.h
recursive-include vendor/libuv *
recursive-exclude vendor/libuv/.git *
recursive-exclude vendor/libuv/docs *
recursive-exclude vendor/libuv/img *
include LICENSE-MIT LICENSE-APACHE README.rst Makefile performance.png
uvloop-0.8.1/LICENSE-MIT 0000664 0003720 0003720 00000002115 13156036740 015346 0 ustar travis travis 0000000 0000000 The MIT License
Copyright (c) 2015-present MagicStack Inc. http://magic.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
uvloop-0.8.1/README.rst 0000664 0003720 0003720 00000004055 13156036740 015406 0 ustar travis travis 0000000 0000000 .. image:: https://travis-ci.org/MagicStack/uvloop.svg?branch=master
:target: https://travis-ci.org/MagicStack/uvloop
.. image:: https://img.shields.io/pypi/v/uvloop.svg
:target: https://pypi.python.org/pypi/uvloop
uvloop is a fast, drop-in replacement of the built-in asyncio
event loop. uvloop is implemented in Cython and uses libuv
under the hood.
The project documentation can be found
`here `_. Please also check out the
`wiki `_.
Performance
-----------
uvloop makes asyncio 2-4x faster.
.. image:: performance.png
:target: http://magic.io/blog/uvloop-blazing-fast-python-networking/
The above chart shows the performance of an echo server with different
message sizes. The *sockets* benchmark uses ``loop.sock_recv()`` and
``loop.sock_sendall()`` methods; the *streams* benchmark uses asyncio
high-level streams, created by the ``asyncio.start_server()`` function;
and the *protocol* benchmark uses ``loop.create_server()`` with a simple
echo protocol. Read more about uvloop
`performance `_.
Installation
------------
uvloop requires Python 3.5 and is available on PyPI.
Use pip to install it::
$ pip install uvloop
Using uvloop
------------
To make asyncio use uvloop, you can install the uvloop event
loop policy:
.. code:: python
import asyncio
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
Alternatively, you can create an instance of the loop
manually, using:
.. code:: python
loop = uvloop.new_event_loop()
asyncio.set_event_loop(loop)
Development of uvloop
---------------------
To build uvloop, you'll need Cython and Python 3.5. The best way
is to create a virtual env, so that you'll have ``cython`` and
``python`` commands pointing to the correct tools.
1. ``git clone --recursive git@github.com:MagicStack/uvloop.git``
2. ``cd uvloop``
3. ``make``
4. ``make test``
License
-------
uvloop is dual-licensed under MIT and Apache 2.0 licenses.
uvloop-0.8.1/LICENSE-APACHE 0000664 0003720 0003720 00000025006 13156036740 015642 0 ustar travis travis 0000000 0000000 Copyright (c) 2015-present MagicStack Inc. http://magic.io
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
uvloop-0.8.1/tests/ 0000775 0003720 0003720 00000000000 13156037661 015060 5 ustar travis travis 0000000 0000000 uvloop-0.8.1/tests/test_futures.py 0000664 0003720 0003720 00000036515 13156036740 020175 0 ustar travis travis 0000000 0000000 # LICENSE: PSF.
import asyncio
import concurrent.futures
import re
import sys
import threading
import unittest
import uvloop
from asyncio import test_utils
from uvloop import _testbase as tb
from unittest import mock
from test import support
# Most of the tests are copied from asyncio
def _fakefunc(f):
return f
def first_cb():
pass
def last_cb():
pass
class _TestFutures:
def create_future(self):
raise NotImplementedError
def test_future_initial_state(self):
f = self.create_future()
self.assertFalse(f.cancelled())
self.assertFalse(f.done())
f.cancel()
self.assertTrue(f.cancelled())
def test_future_cancel(self):
f = self.create_future()
self.assertTrue(f.cancel())
self.assertTrue(f.cancelled())
self.assertTrue(f.done())
self.assertRaises(asyncio.CancelledError, f.result)
self.assertRaises(asyncio.CancelledError, f.exception)
self.assertRaises(asyncio.InvalidStateError, f.set_result, None)
self.assertRaises(asyncio.InvalidStateError, f.set_exception, None)
self.assertFalse(f.cancel())
def test_future_result(self):
f = self.create_future()
self.assertRaises(asyncio.InvalidStateError, f.result)
f.set_result(42)
self.assertFalse(f.cancelled())
self.assertTrue(f.done())
self.assertEqual(f.result(), 42)
self.assertEqual(f.exception(), None)
self.assertRaises(asyncio.InvalidStateError, f.set_result, None)
self.assertRaises(asyncio.InvalidStateError, f.set_exception, None)
self.assertFalse(f.cancel())
def test_future_exception(self):
exc = RuntimeError()
f = self.create_future()
self.assertRaises(asyncio.InvalidStateError, f.exception)
if sys.version_info[:3] > (3, 5, 1):
# StopIteration cannot be raised into a Future - CPython issue26221
self.assertRaisesRegex(TypeError,
"StopIteration .* cannot be raised",
f.set_exception, StopIteration)
f.set_exception(exc)
self.assertFalse(f.cancelled())
self.assertTrue(f.done())
self.assertRaises(RuntimeError, f.result)
self.assertEqual(f.exception(), exc)
self.assertRaises(asyncio.InvalidStateError, f.set_result, None)
self.assertRaises(asyncio.InvalidStateError, f.set_exception, None)
self.assertFalse(f.cancel())
def test_future_exception_class(self):
f = self.create_future()
f.set_exception(RuntimeError)
self.assertIsInstance(f.exception(), RuntimeError)
def test_future_yield_from_twice(self):
f = self.create_future()
def fixture():
yield 'A'
x = yield from f
yield 'B', x
y = yield from f
yield 'C', y
g = fixture()
self.assertEqual(next(g), 'A') # yield 'A'.
self.assertEqual(next(g), f) # First yield from f.
f.set_result(42)
self.assertEqual(next(g), ('B', 42)) # yield 'B', x.
# The second "yield from f" does not yield f.
self.assertEqual(next(g), ('C', 42)) # yield 'C', y.
def test_future_repr(self):
self.loop.set_debug(True)
f_pending_debug = self.create_future()
frame = f_pending_debug._source_traceback[-1]
self.assertEqual(repr(f_pending_debug),
''
% (frame[0], frame[1]))
f_pending_debug.cancel()
self.loop.set_debug(False)
f_pending = self.create_future()
self.assertEqual(repr(f_pending), '')
f_pending.cancel()
f_cancelled = self.create_future()
f_cancelled.cancel()
self.assertEqual(repr(f_cancelled), '')
f_result = self.create_future()
f_result.set_result(4)
self.assertEqual(repr(f_result), '')
self.assertEqual(f_result.result(), 4)
exc = RuntimeError()
f_exception = self.create_future()
f_exception.set_exception(exc)
self.assertEqual(repr(f_exception),
'')
self.assertIs(f_exception.exception(), exc)
def func_repr(func):
filename, lineno = test_utils.get_function_source(func)
text = '%s() at %s:%s' % (func.__qualname__, filename, lineno)
return re.escape(text)
f_one_callbacks = self.create_future()
f_one_callbacks.add_done_callback(_fakefunc)
fake_repr = func_repr(_fakefunc)
self.assertRegex(repr(f_one_callbacks),
r'' % fake_repr)
f_one_callbacks.cancel()
self.assertEqual(repr(f_one_callbacks),
'')
f_two_callbacks = self.create_future()
f_two_callbacks.add_done_callback(first_cb)
f_two_callbacks.add_done_callback(last_cb)
first_repr = func_repr(first_cb)
last_repr = func_repr(last_cb)
self.assertRegex(repr(f_two_callbacks),
r''
% (first_repr, last_repr))
f_many_callbacks = self.create_future()
f_many_callbacks.add_done_callback(first_cb)
for i in range(8):
f_many_callbacks.add_done_callback(_fakefunc)
f_many_callbacks.add_done_callback(last_cb)
cb_regex = r'%s, <8 more>, %s' % (first_repr, last_repr)
self.assertRegex(repr(f_many_callbacks),
r'' % cb_regex)
f_many_callbacks.cancel()
self.assertEqual(repr(f_many_callbacks),
'')
def test_future_copy_state(self):
if sys.version_info[:3] < (3, 5, 1):
raise unittest.SkipTest()
from asyncio.futures import _copy_future_state
f = self.create_future()
f.set_result(10)
newf = self.create_future()
_copy_future_state(f, newf)
self.assertTrue(newf.done())
self.assertEqual(newf.result(), 10)
f_exception = self.create_future()
f_exception.set_exception(RuntimeError())
newf_exception = self.create_future()
_copy_future_state(f_exception, newf_exception)
self.assertTrue(newf_exception.done())
self.assertRaises(RuntimeError, newf_exception.result)
f_cancelled = self.create_future()
f_cancelled.cancel()
newf_cancelled = self.create_future()
_copy_future_state(f_cancelled, newf_cancelled)
self.assertTrue(newf_cancelled.cancelled())
@mock.patch('asyncio.base_events.logger')
def test_future_tb_logger_abandoned(self, m_log):
fut = self.create_future()
del fut
self.assertFalse(m_log.error.called)
@mock.patch('asyncio.base_events.logger')
def test_future_tb_logger_result_unretrieved(self, m_log):
fut = self.create_future()
fut.set_result(42)
del fut
self.assertFalse(m_log.error.called)
@mock.patch('asyncio.base_events.logger')
def test_future_tb_logger_result_retrieved(self, m_log):
fut = self.create_future()
fut.set_result(42)
fut.result()
del fut
self.assertFalse(m_log.error.called)
def test_future_wrap_future(self):
def run(arg):
return (arg, threading.get_ident())
ex = concurrent.futures.ThreadPoolExecutor(1)
f1 = ex.submit(run, 'oi')
f2 = asyncio.wrap_future(f1, loop=self.loop)
res, ident = self.loop.run_until_complete(f2)
self.assertIsInstance(f2, asyncio.Future)
self.assertEqual(res, 'oi')
self.assertNotEqual(ident, threading.get_ident())
def test_future_wrap_future_future(self):
f1 = self.create_future()
f2 = asyncio.wrap_future(f1)
self.assertIs(f1, f2)
def test_future_wrap_future_use_global_loop(self):
with mock.patch('asyncio.futures.events') as events:
events.get_event_loop = lambda: self.loop
def run(arg):
return (arg, threading.get_ident())
ex = concurrent.futures.ThreadPoolExecutor(1)
f1 = ex.submit(run, 'oi')
f2 = asyncio.wrap_future(f1)
self.assertIs(self.loop, f2._loop)
def test_future_wrap_future_cancel(self):
f1 = concurrent.futures.Future()
f2 = asyncio.wrap_future(f1, loop=self.loop)
f2.cancel()
test_utils.run_briefly(self.loop)
self.assertTrue(f1.cancelled())
self.assertTrue(f2.cancelled())
def test_future_wrap_future_cancel2(self):
f1 = concurrent.futures.Future()
f2 = asyncio.wrap_future(f1, loop=self.loop)
f1.set_result(42)
f2.cancel()
test_utils.run_briefly(self.loop)
self.assertFalse(f1.cancelled())
self.assertEqual(f1.result(), 42)
self.assertTrue(f2.cancelled())
def test_future_source_traceback(self):
self.loop.set_debug(True)
future = self.create_future()
lineno = sys._getframe().f_lineno - 1
self.assertIsInstance(future._source_traceback, list)
self.assertEqual(future._source_traceback[-2][:3],
(__file__,
lineno,
'test_future_source_traceback'))
def check_future_exception_never_retrieved(self, debug):
last_ctx = None
def handler(loop, context):
nonlocal last_ctx
last_ctx = context
self.loop.set_debug(debug)
self.loop.set_exception_handler(handler)
def memory_error():
try:
raise MemoryError()
except BaseException as exc:
return exc
exc = memory_error()
future = self.create_future()
if debug:
source_traceback = future._source_traceback
future.set_exception(exc)
future = None
support.gc_collect()
test_utils.run_briefly(self.loop)
self.assertIsNotNone(last_ctx)
self.assertIs(last_ctx['exception'], exc)
self.assertEqual(last_ctx['message'],
'Future exception was never retrieved')
if debug:
tb = last_ctx['source_traceback']
self.assertEqual(tb[-2].name,
'check_future_exception_never_retrieved')
def test_future_exception_never_retrieved(self):
self.check_future_exception_never_retrieved(False)
def test_future_exception_never_retrieved_debug(self):
self.check_future_exception_never_retrieved(True)
def test_future_wrap_future(self):
from uvloop.loop import _wrap_future
def run(arg):
return (arg, threading.get_ident())
ex = concurrent.futures.ThreadPoolExecutor(1)
f1 = ex.submit(run, 'oi')
f2 = _wrap_future(f1, loop=self.loop)
res, ident = self.loop.run_until_complete(f2)
self.assertIsInstance(f2, asyncio.Future)
self.assertEqual(res, 'oi')
self.assertNotEqual(ident, threading.get_ident())
def test_future_wrap_future_future(self):
from uvloop.loop import _wrap_future
f1 = self.create_future()
f2 = _wrap_future(f1)
self.assertIs(f1, f2)
def test_future_wrap_future_cancel(self):
from uvloop.loop import _wrap_future
f1 = concurrent.futures.Future()
f2 = _wrap_future(f1, loop=self.loop)
f2.cancel()
test_utils.run_briefly(self.loop)
self.assertTrue(f1.cancelled())
self.assertTrue(f2.cancelled())
def test_future_wrap_future_cancel2(self):
from uvloop.loop import _wrap_future
f1 = concurrent.futures.Future()
f2 = _wrap_future(f1, loop=self.loop)
f1.set_result(42)
f2.cancel()
test_utils.run_briefly(self.loop)
self.assertFalse(f1.cancelled())
self.assertEqual(f1.result(), 42)
self.assertTrue(f2.cancelled())
class _TestFuturesDoneCallbacks:
def run_briefly(self):
test_utils.run_briefly(self.loop)
def _make_callback(self, bag, thing):
# Create a callback function that appends thing to bag.
def bag_appender(future):
bag.append(thing)
return bag_appender
def _new_future(self):
raise NotImplementedError
def test_future_callbacks_invoked_on_set_result(self):
bag = []
f = self._new_future()
f.add_done_callback(self._make_callback(bag, 42))
f.add_done_callback(self._make_callback(bag, 17))
self.assertEqual(bag, [])
f.set_result('foo')
self.run_briefly()
self.assertEqual(bag, [42, 17])
self.assertEqual(f.result(), 'foo')
def test_future_callbacks_invoked_on_set_exception(self):
bag = []
f = self._new_future()
f.add_done_callback(self._make_callback(bag, 100))
self.assertEqual(bag, [])
exc = RuntimeError()
f.set_exception(exc)
self.run_briefly()
self.assertEqual(bag, [100])
self.assertEqual(f.exception(), exc)
def test_future_remove_done_callback(self):
bag = []
f = self._new_future()
cb1 = self._make_callback(bag, 1)
cb2 = self._make_callback(bag, 2)
cb3 = self._make_callback(bag, 3)
# Add one cb1 and one cb2.
f.add_done_callback(cb1)
f.add_done_callback(cb2)
# One instance of cb2 removed. Now there's only one cb1.
self.assertEqual(f.remove_done_callback(cb2), 1)
# Never had any cb3 in there.
self.assertEqual(f.remove_done_callback(cb3), 0)
# After this there will be 6 instances of cb1 and one of cb2.
f.add_done_callback(cb2)
for i in range(5):
f.add_done_callback(cb1)
# Remove all instances of cb1. One cb2 remains.
self.assertEqual(f.remove_done_callback(cb1), 6)
self.assertEqual(bag, [])
f.set_result('foo')
self.run_briefly()
self.assertEqual(bag, [2])
self.assertEqual(f.result(), 'foo')
###############################################################################
# Tests Matrix
###############################################################################
class Test_UV_UV_create_future(_TestFutures, tb.UVTestCase):
# Test uvloop.Loop.create_future
def create_future(self):
return self.loop.create_future()
class Test_UV_UV_Future(_TestFutures, tb.UVTestCase):
# Test that uvloop.Future can be instantiated directly
def create_future(self):
return uvloop.Future(loop=self.loop)
class Test_UV_AIO_Futures(_TestFutures, tb.UVTestCase):
def create_future(self):
return asyncio.Future(loop=self.loop)
class Test_AIO_Futures(_TestFutures, tb.AIOTestCase):
def create_future(self):
return asyncio.Future(loop=self.loop)
class Test_UV_UV_FuturesCallbacks(_TestFuturesDoneCallbacks, tb.UVTestCase):
def _new_future(self):
return self.loop.create_future()
class Test_UV_AIO_FuturesCallbacks(_TestFuturesDoneCallbacks, tb.UVTestCase):
def _new_future(self):
return asyncio.Future(loop=self.loop)
class Test_AIO_FuturesCallbacks(_TestFuturesDoneCallbacks, tb.AIOTestCase):
def _new_future(self):
return asyncio.Future(loop=self.loop)
uvloop-0.8.1/tests/test_sockets.py 0000664 0003720 0003720 00000010661 13156036740 020145 0 ustar travis travis 0000000 0000000 import asyncio
import select
import socket
import sys
import unittest
from uvloop import _testbase as tb
_SIZE = 1024 * 1024
class _TestSockets:
async def recv_all(self, sock, nbytes):
buf = b''
while len(buf) < nbytes:
buf += await self.loop.sock_recv(sock, nbytes - len(buf))
return buf
def test_socket_connect_recv_send(self):
if self.is_asyncio_loop() and sys.version_info[:3] == (3, 5, 2):
# See https://github.com/python/asyncio/pull/366 for details.
raise unittest.SkipTest()
def srv_gen():
yield tb.write(b'helo')
data = yield tb.read(4 * _SIZE)
self.assertEqual(data, b'ehlo' * _SIZE)
yield tb.write(b'O')
yield tb.write(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 tb.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()
sock.setblocking(False)
with sock:
sock.bind(('127.0.0.1', 0))
sock.listen()
fut = self.loop.run_in_executor(None, client,
sock.getsockname())
client_sock, _ = await self.loop.sock_accept(sock)
with client_sock:
data = await self.recv_all(client_sock, _SIZE)
self.assertEqual(data, b'a' * _SIZE)
await fut
def client(addr):
sock = socket.socket()
with sock:
sock.connect(addr)
sock.sendall(b'a' * _SIZE)
self.loop.run_until_complete(server())
def test_socket_failed_connect(self):
sock = socket.socket()
with sock:
sock.bind(('127.0.0.1', 0))
addr = sock.getsockname()
async def run():
sock = socket.socket()
with sock:
sock.setblocking(False)
with self.assertRaises(ConnectionRefusedError):
await self.loop.sock_connect(sock, addr)
self.loop.run_until_complete(run())
def test_socket_blocking_error(self):
self.loop.set_debug(True)
sock = socket.socket()
with sock:
with self.assertRaisesRegex(ValueError, 'must be non-blocking'):
self.loop.run_until_complete(
self.loop.sock_recv(sock, 0))
with self.assertRaisesRegex(ValueError, 'must be non-blocking'):
self.loop.run_until_complete(
self.loop.sock_sendall(sock, b''))
with self.assertRaisesRegex(ValueError, 'must be non-blocking'):
self.loop.run_until_complete(
self.loop.sock_accept(sock))
with self.assertRaisesRegex(ValueError, 'must be non-blocking'):
self.loop.run_until_complete(
self.loop.sock_connect(sock, (b'', 0)))
class TestUVSockets(_TestSockets, tb.UVTestCase):
@unittest.skipUnless(hasattr(select, 'epoll'), 'Linux only test')
def test_socket_sync_remove(self):
# See https://github.com/MagicStack/uvloop/issues/61 for details
sock = socket.socket()
epoll = select.epoll.fromfd(self.loop._get_backend_id())
try:
cb = lambda: None
sock.bind(('127.0.0.1', 0))
sock.listen(0)
fd = sock.fileno()
self.loop.add_reader(fd, cb)
self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop))
self.loop.remove_reader(fd)
with self.assertRaises(FileNotFoundError):
epoll.modify(fd, 0)
finally:
sock.close()
self.loop.close()
epoll.close()
class TestAIOSockets(_TestSockets, tb.AIOTestCase):
pass
uvloop-0.8.1/tests/test_process.py 0000664 0003720 0003720 00000050272 13156036740 020152 0 ustar travis travis 0000000 0000000 import asyncio
import contextlib
import os
import signal
import subprocess
import sys
import tempfile
import time
from asyncio import test_utils
from uvloop import _testbase as tb
class _TestProcess:
def test_process_env_1(self):
async def test():
cmd = 'echo $FOO$BAR'
env = {'FOO': 'sp', 'BAR': 'am'}
proc = await asyncio.create_subprocess_shell(
cmd,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
loop=self.loop)
out, _ = await proc.communicate()
self.assertEqual(out, b'spam\n')
self.assertEqual(proc.returncode, 0)
self.loop.run_until_complete(test())
def test_process_cwd_1(self):
async def test():
cmd = 'pwd'
env = {}
cwd = '/'
proc = await asyncio.create_subprocess_shell(
cmd,
cwd=cwd,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
loop=self.loop)
out, _ = await proc.communicate()
self.assertEqual(out, b'/\n')
self.assertEqual(proc.returncode, 0)
self.loop.run_until_complete(test())
def test_process_preexec_fn_1(self):
# Copied from CPython/test_suprocess.py
# DISCLAIMER: Setting environment variables is *not* a good use
# of a preexec_fn. This is merely a test.
async def test():
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, '-c',
'import os,sys;sys.stdout.write(os.getenv("FRUIT"))',
stdout=subprocess.PIPE,
preexec_fn=lambda: os.putenv("FRUIT", "apple"),
loop=self.loop)
out, _ = await proc.communicate()
self.assertEqual(out, b'apple')
self.assertEqual(proc.returncode, 0)
self.loop.run_until_complete(test())
def test_process_preexec_fn_2(self):
# Copied from CPython/test_suprocess.py
def raise_it():
raise ValueError("spam")
async def test():
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, '-c', 'import time; time.sleep(10)',
preexec_fn=raise_it,
loop=self.loop)
await proc.communicate()
started = time.time()
try:
self.loop.run_until_complete(test())
except subprocess.SubprocessError as ex:
self.assertIn('preexec_fn', ex.args[0])
if ex.__cause__ is not None:
# uvloop will set __cause__
self.assertIs(type(ex.__cause__), ValueError)
self.assertEqual(ex.__cause__.args[0], 'spam')
else:
self.fail(
'exception in preexec_fn did not propagate to the parent')
if time.time() - started > 5:
self.fail(
'exception in preexec_fn did not kill the child process')
def test_process_executable_1(self):
async def test():
proc = await asyncio.create_subprocess_exec(
b'doesnotexist', b'-c', b'print("spam")',
executable=sys.executable,
stdout=subprocess.PIPE,
loop=self.loop)
out, err = await proc.communicate()
self.assertEqual(out, b'spam\n')
self.loop.run_until_complete(test())
def test_process_pid_1(self):
async def test():
prog = '''\
import os
print(os.getpid())
'''
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-c', prog,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
loop=self.loop)
pid = proc.pid
expected_result = '{}\n'.format(pid).encode()
out, err = await proc.communicate()
self.assertEqual(out, expected_result)
self.loop.run_until_complete(test())
def test_process_send_signal_1(self):
async def test():
prog = '''\
import signal
def handler(signum, frame):
if signum == signal.SIGUSR1:
print('WORLD')
signal.signal(signal.SIGUSR1, handler)
a = input()
print(a)
a = input()
print(a)
exit(11)
'''
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-c', prog,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
loop=self.loop)
proc.stdin.write(b'HELLO\n')
await proc.stdin.drain()
self.assertEqual(await proc.stdout.readline(), b'HELLO\n')
proc.send_signal(signal.SIGUSR1)
proc.stdin.write(b'!\n')
await proc.stdin.drain()
self.assertEqual(await proc.stdout.readline(), b'WORLD\n')
self.assertEqual(await proc.stdout.readline(), b'!\n')
self.assertEqual(await proc.wait(), 11)
self.loop.run_until_complete(test())
def test_process_streams_basic_1(self):
async def test():
prog = '''\
import sys
while True:
a = input()
if a == 'stop':
exit(20)
elif a == 'stderr':
print('OUCH', file=sys.stderr)
else:
print('>' + a + '<')
'''
cmd = sys.executable
proc = await asyncio.create_subprocess_exec(
cmd, b'-c', prog,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
loop=self.loop)
self.assertGreater(proc.pid, 0)
self.assertIs(proc.returncode, None)
transp = proc._transport
with self.assertRaises(NotImplementedError):
# stdin is WriteTransport
transp.get_pipe_transport(0).pause_reading()
with self.assertRaises((NotImplementedError, AttributeError)):
# stdout is ReadTransport
transp.get_pipe_transport(1).write(b'wat')
proc.stdin.write(b'foobar\n')
await proc.stdin.drain()
out = await proc.stdout.readline()
self.assertEqual(out, b'>foobar<\n')
proc.stdin.write(b'stderr\n')
await proc.stdin.drain()
out = await proc.stderr.readline()
self.assertEqual(out, b'OUCH\n')
proc.stdin.write(b'stop\n')
await proc.stdin.drain()
exitcode = await proc.wait()
self.assertEqual(exitcode, 20)
self.loop.run_until_complete(test())
def test_process_streams_stderr_to_stdout(self):
async def test():
prog = '''\
import sys
print('out', flush=True)
print('err', file=sys.stderr, flush=True)
'''
proc = await asyncio.create_subprocess_exec(
sys.executable, '-c', prog,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
loop=self.loop)
out, err = await proc.communicate()
self.assertIsNone(err)
self.assertEqual(out, b'out\nerr\n')
self.loop.run_until_complete(test())
def test_process_streams_devnull(self):
async def test():
prog = '''\
import sys
print('out', flush=True)
print('err', file=sys.stderr, flush=True)
'''
proc = await asyncio.create_subprocess_exec(
sys.executable, '-c', prog,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
loop=self.loop)
out, err = await proc.communicate()
self.assertIsNone(err)
self.assertIsNone(out)
self.loop.run_until_complete(test())
def test_process_streams_pass_fds(self):
async def test():
prog = '''\
import sys, os
assert sys.argv[1] == '--'
inherited = int(sys.argv[2])
non_inherited = int(sys.argv[3])
os.fstat(inherited)
try:
os.fstat(non_inherited)
except:
pass
else:
raise RuntimeError()
print("OK")
'''
with tempfile.TemporaryFile() as inherited, \
tempfile.TemporaryFile() as non_inherited:
proc = await asyncio.create_subprocess_exec(
sys.executable, '-c', prog, '--',
str(inherited.fileno()),
str(non_inherited.fileno()),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
pass_fds=(inherited.fileno(),),
loop=self.loop)
out, err = await proc.communicate()
self.assertEqual(err, b'')
self.assertEqual(out, b'OK\n')
self.loop.run_until_complete(test())
class _AsyncioTests:
# Program blocking
PROGRAM_BLOCKED = [sys.executable, '-c', 'import time; time.sleep(3600)']
# Program copying input to output
PROGRAM_CAT = [
sys.executable, '-c',
';'.join(('import sys',
'data = sys.stdin.buffer.read()',
'sys.stdout.buffer.write(data)'))]
def test_stdin_not_inheritable(self):
# asyncio issue #209: stdin must not be inheritable, otherwise
# the Process.communicate() hangs
@asyncio.coroutine
def len_message(message):
code = 'import sys; data = sys.stdin.read(); print(len(data))'
proc = yield from asyncio.create_subprocess_exec(
sys.executable, '-c', code,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
close_fds=False,
loop=self.loop)
stdout, stderr = yield from proc.communicate(message)
exitcode = yield from proc.wait()
return (stdout, exitcode)
output, exitcode = self.loop.run_until_complete(len_message(b'abc'))
self.assertEqual(output.rstrip(), b'3')
self.assertEqual(exitcode, 0)
def test_stdin_stdout(self):
args = self.PROGRAM_CAT
@asyncio.coroutine
def run(data):
proc = yield from asyncio.create_subprocess_exec(
*args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
loop=self.loop)
# feed data
proc.stdin.write(data)
yield from proc.stdin.drain()
proc.stdin.close()
# get output and exitcode
data = yield from proc.stdout.read()
exitcode = yield from proc.wait()
return (exitcode, data)
task = run(b'some data')
task = asyncio.wait_for(task, 60.0, loop=self.loop)
exitcode, stdout = self.loop.run_until_complete(task)
self.assertEqual(exitcode, 0)
self.assertEqual(stdout, b'some data')
def test_communicate(self):
args = self.PROGRAM_CAT
@asyncio.coroutine
def run(data):
proc = yield from asyncio.create_subprocess_exec(
*args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
loop=self.loop)
stdout, stderr = yield from proc.communicate(data)
return proc.returncode, stdout
task = run(b'some data')
task = asyncio.wait_for(task, 60.0, loop=self.loop)
exitcode, stdout = self.loop.run_until_complete(task)
self.assertEqual(exitcode, 0)
self.assertEqual(stdout, b'some data')
def test_start_new_session(self):
# start the new process in a new session
create = asyncio.create_subprocess_shell('exit 8',
start_new_session=True,
loop=self.loop)
proc = self.loop.run_until_complete(create)
exitcode = self.loop.run_until_complete(proc.wait())
self.assertEqual(exitcode, 8)
def test_shell(self):
create = asyncio.create_subprocess_shell('exit 7',
loop=self.loop)
proc = self.loop.run_until_complete(create)
exitcode = self.loop.run_until_complete(proc.wait())
self.assertEqual(exitcode, 7)
def test_kill(self):
args = self.PROGRAM_BLOCKED
create = asyncio.create_subprocess_exec(*args, loop=self.loop)
proc = self.loop.run_until_complete(create)
proc.kill()
returncode = self.loop.run_until_complete(proc.wait())
self.assertEqual(-signal.SIGKILL, returncode)
def test_terminate(self):
args = self.PROGRAM_BLOCKED
create = asyncio.create_subprocess_exec(*args, loop=self.loop)
proc = self.loop.run_until_complete(create)
proc.terminate()
returncode = self.loop.run_until_complete(proc.wait())
self.assertEqual(-signal.SIGTERM, returncode)
def test_send_signal(self):
code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
args = [sys.executable, '-c', code]
create = asyncio.create_subprocess_exec(*args,
stdout=subprocess.PIPE,
loop=self.loop)
proc = self.loop.run_until_complete(create)
@asyncio.coroutine
def send_signal(proc):
# basic synchronization to wait until the program is sleeping
line = yield from proc.stdout.readline()
self.assertEqual(line, b'sleeping\n')
proc.send_signal(signal.SIGHUP)
returncode = (yield from proc.wait())
return returncode
returncode = self.loop.run_until_complete(send_signal(proc))
self.assertEqual(-signal.SIGHUP, returncode)
def test_cancel_process_wait(self):
# Issue #23140: cancel Process.wait()
@asyncio.coroutine
def cancel_wait():
proc = yield from asyncio.create_subprocess_exec(
*self.PROGRAM_BLOCKED,
loop=self.loop)
# Create an internal future waiting on the process exit
task = self.loop.create_task(proc.wait())
self.loop.call_soon(task.cancel)
try:
yield from task
except asyncio.CancelledError:
pass
# Cancel the future
task.cancel()
# Kill the process and wait until it is done
proc.kill()
yield from proc.wait()
self.loop.run_until_complete(cancel_wait())
def test_cancel_make_subprocess_transport_exec(self):
@asyncio.coroutine
def cancel_make_transport():
coro = asyncio.create_subprocess_exec(*self.PROGRAM_BLOCKED,
loop=self.loop)
task = self.loop.create_task(coro)
self.loop.call_soon(task.cancel)
try:
yield from task
except asyncio.CancelledError:
pass
# ignore the log:
# "Exception during subprocess creation, kill the subprocess"
with test_utils.disable_logger():
self.loop.run_until_complete(cancel_make_transport())
def test_cancel_post_init(self):
@asyncio.coroutine
def cancel_make_transport():
coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol,
*self.PROGRAM_BLOCKED)
task = self.loop.create_task(coro)
self.loop.call_soon(task.cancel)
try:
yield from task
except asyncio.CancelledError:
pass
# ignore the log:
# "Exception during subprocess creation, kill the subprocess"
with test_utils.disable_logger():
self.loop.run_until_complete(cancel_make_transport())
test_utils.run_briefly(self.loop)
class Test_UV_Process(_TestProcess, tb.UVTestCase):
def test_process_lated_stdio_init(self):
class TestProto:
def __init__(self):
self.lost = 0
self.stages = []
def connection_made(self, transport):
self.stages.append(('CM', transport))
def pipe_data_received(self, fd, data):
if fd == 1:
self.stages.append(('STDOUT', data))
def pipe_connection_lost(self, fd, exc):
if fd == 1:
self.stages.append(('STDOUT', 'LOST'))
def process_exited(self):
self.stages.append('PROC_EXIT')
def connection_lost(self, exc):
self.stages.append(('CL', self.lost, exc))
self.lost += 1
async def run(**kwargs):
return await self.loop.subprocess_shell(
lambda: TestProto(),
'echo 1',
**kwargs)
with self.subTest('paused, stdin pipe'):
transport, proto = self.loop.run_until_complete(
run(stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
__uvloop_sleep_after_fork=True))
self.assertIsNot(transport, None)
self.assertEqual(transport.get_returncode(), 0)
self.assertEqual(
set(proto.stages),
{
('CM', transport),
'PROC_EXIT',
('STDOUT', b'1\n'),
('STDOUT', 'LOST'),
('CL', 0, None)
})
with self.subTest('paused, no stdin'):
transport, proto = self.loop.run_until_complete(
run(stdin=None,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
__uvloop_sleep_after_fork=True))
self.assertIsNot(transport, None)
self.assertEqual(transport.get_returncode(), 0)
self.assertEqual(
set(proto.stages),
{
('CM', transport),
'PROC_EXIT',
('STDOUT', b'1\n'),
('STDOUT', 'LOST'),
('CL', 0, None)
})
with self.subTest('no pause, no stdin'):
transport, proto = self.loop.run_until_complete(
run(stdin=None,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE))
self.loop.run_until_complete(transport._wait())
self.assertEqual(transport.get_returncode(), 0)
self.assertIsNot(transport, None)
self.assertEqual(
set(proto.stages),
{
('CM', transport),
'PROC_EXIT',
('STDOUT', b'1\n'),
('STDOUT', 'LOST'),
('CL', 0, None)
})
def test_process_streams_redirect(self):
# This won't work for asyncio implementation of subprocess
async def test():
prog = bR'''
import sys
print('out', flush=True)
print('err', file=sys.stderr, flush=True)
'''
proc = await asyncio.create_subprocess_exec(
sys.executable, '-c', prog,
loop=self.loop)
out, err = await proc.communicate()
self.assertIsNone(out)
self.assertIsNone(err)
with tempfile.NamedTemporaryFile('w') as stdout:
with tempfile.NamedTemporaryFile('w') as stderr:
with contextlib.redirect_stdout(stdout):
with contextlib.redirect_stderr(stderr):
self.loop.run_until_complete(test())
stdout.flush()
stderr.flush()
with open(stdout.name, 'rb') as so:
self.assertEqual(so.read(), b'out\n')
with open(stderr.name, 'rb') as se:
self.assertEqual(se.read(), b'err\n')
class Test_AIO_Process(_TestProcess, tb.AIOTestCase):
pass
class TestAsyncio_UV_Process(_AsyncioTests, tb.UVTestCase):
pass
class TestAsyncio_AIO_Process(_AsyncioTests, tb.AIOTestCase):
pass
uvloop-0.8.1/tests/test_testbase.py 0000664 0003720 0003720 00000002536 13156036740 020306 0 ustar travis travis 0000000 0000000 import unittest
from uvloop import _testbase as tb
class TestBaseTest(unittest.TestCase):
def test_duplicate_methods(self):
with self.assertRaisesRegex(RuntimeError, 'duplicate test Foo.test_a'):
class Foo(tb.BaseTestCase):
def test_a(self):
pass
def test_b(self):
pass
def test_a(self): # NOQA
pass
def test_duplicate_methods_parent_1(self):
class FooBase:
def test_a(self):
pass
with self.assertRaisesRegex(RuntimeError,
'duplicate test Foo.test_a.*'
'defined in FooBase'):
class Foo(FooBase, tb.BaseTestCase):
def test_b(self):
pass
def test_a(self):
pass
def test_duplicate_methods_parent_2(self):
class FooBase(tb.BaseTestCase):
def test_a(self):
pass
with self.assertRaisesRegex(RuntimeError,
'duplicate test Foo.test_a.*'
'defined in FooBase'):
class Foo(FooBase):
def test_b(self):
pass
def test_a(self):
pass
uvloop-0.8.1/tests/test_dns.py 0000664 0003720 0003720 00000013163 13156036740 017256 0 ustar travis travis 0000000 0000000 import socket
import unittest
from uvloop import _testbase as tb
class BaseTestDNS:
def _test_getaddrinfo(self, *args, **kwargs):
err = None
try:
a1 = socket.getaddrinfo(*args, **kwargs)
except socket.gaierror as ex:
err = ex
try:
a2 = self.loop.run_until_complete(
self.loop.getaddrinfo(*args, **kwargs))
except socket.gaierror as ex:
if err is not None:
self.assertEqual(ex.args, err.args)
else:
ex.__context__ = err
raise ex
except OSError as ex:
ex.__context__ = err
raise ex
else:
if err is not None:
raise err
self.assertEqual(a1, a2)
def _test_getnameinfo(self, *args, **kwargs):
err = None
try:
a1 = socket.getnameinfo(*args, **kwargs)
except Exception as ex:
err = ex
try:
a2 = self.loop.run_until_complete(
self.loop.getnameinfo(*args, **kwargs))
except Exception as ex:
if err is not None:
if ex.__class__ is not err.__class__:
print(ex, err)
self.assertIs(ex.__class__, err.__class__)
self.assertEqual(ex.args, err.args)
else:
raise
else:
if err is not None:
raise err
self.assertEqual(a1, a2)
def test_getaddrinfo_1(self):
self._test_getaddrinfo('example.com', 80)
self._test_getaddrinfo('example.com', 80, type=socket.SOCK_STREAM)
def test_getaddrinfo_2(self):
self._test_getaddrinfo('example.com', 80, flags=socket.AI_CANONNAME)
def test_getaddrinfo_3(self):
self._test_getaddrinfo('a' + '1' * 50 + '.wat', 800)
def test_getaddrinfo_4(self):
self._test_getaddrinfo('example.com', 80, family=-1)
self._test_getaddrinfo('example.com', 80, type=socket.SOCK_STREAM,
family=-1)
def test_getaddrinfo_5(self):
self._test_getaddrinfo('example.com', '80')
self._test_getaddrinfo('example.com', '80', type=socket.SOCK_STREAM)
def test_getaddrinfo_6(self):
self._test_getaddrinfo(b'example.com', b'80')
self._test_getaddrinfo(b'example.com', b'80', type=socket.SOCK_STREAM)
def test_getaddrinfo_7(self):
self._test_getaddrinfo(None, 0)
self._test_getaddrinfo(None, 0, type=socket.SOCK_STREAM)
def test_getaddrinfo_8(self):
self._test_getaddrinfo('', 0)
self._test_getaddrinfo('', 0, type=socket.SOCK_STREAM)
def test_getaddrinfo_9(self):
self._test_getaddrinfo(b'', 0)
self._test_getaddrinfo(b'', 0, type=socket.SOCK_STREAM)
def test_getaddrinfo_10(self):
self._test_getaddrinfo(None, None)
self._test_getaddrinfo(None, None, type=socket.SOCK_STREAM)
def test_getaddrinfo_11(self):
self._test_getaddrinfo(b'example.com', '80')
self._test_getaddrinfo(b'example.com', '80', type=socket.SOCK_STREAM)
def test_getaddrinfo_12(self):
self._test_getaddrinfo('127.0.0.1', '80')
self._test_getaddrinfo('127.0.0.1', '80', type=socket.SOCK_STREAM)
def test_getaddrinfo_13(self):
self._test_getaddrinfo(b'127.0.0.1', b'80')
self._test_getaddrinfo(b'127.0.0.1', b'80', type=socket.SOCK_STREAM)
def test_getaddrinfo_14(self):
self._test_getaddrinfo(b'127.0.0.1', b'http')
self._test_getaddrinfo(b'127.0.0.1', b'http', type=socket.SOCK_STREAM)
def test_getaddrinfo_15(self):
self._test_getaddrinfo('127.0.0.1', 'http')
self._test_getaddrinfo('127.0.0.1', 'http', type=socket.SOCK_STREAM)
def test_getaddrinfo_16(self):
self._test_getaddrinfo('localhost', 'http')
self._test_getaddrinfo('localhost', 'http', type=socket.SOCK_STREAM)
def test_getaddrinfo_17(self):
self._test_getaddrinfo(b'localhost', 'http')
self._test_getaddrinfo(b'localhost', 'http', type=socket.SOCK_STREAM)
def test_getaddrinfo_18(self):
self._test_getaddrinfo('localhost', b'http')
self._test_getaddrinfo('localhost', b'http', type=socket.SOCK_STREAM)
def test_getaddrinfo_19(self):
self._test_getaddrinfo('::1', 80)
self._test_getaddrinfo('::1', 80, type=socket.SOCK_STREAM)
def test_getaddrinfo_20(self):
self._test_getaddrinfo('127.0.0.1', 80)
self._test_getaddrinfo('127.0.0.1', 80, type=socket.SOCK_STREAM)
######
def test_getnameinfo_1(self):
self._test_getnameinfo(('127.0.0.1', 80), 0)
def test_getnameinfo_2(self):
self._test_getnameinfo(('127.0.0.1', 80, 1231231231213), 0)
def test_getnameinfo_3(self):
self._test_getnameinfo(('127.0.0.1', 80, 0, 0), 0)
def test_getnameinfo_4(self):
self._test_getnameinfo(('::1', 80), 0)
def test_getnameinfo_5(self):
self._test_getnameinfo(('localhost', 8080), 0)
class Test_UV_DNS(BaseTestDNS, tb.UVTestCase):
def test_getaddrinfo_close_loop(self):
# Test that we can close the loop with a running
# DNS query.
try:
# Check that we have internet connection
socket.getaddrinfo('example.com', 80)
except socket.error:
raise unittest.SkipTest
async def run():
fut = self.loop.getaddrinfo('example.com', 80)
fut.cancel()
self.loop.stop()
try:
self.loop.run_until_complete(run())
finally:
self.loop.close()
class Test_AIO_DNS(BaseTestDNS, tb.AIOTestCase):
pass
uvloop-0.8.1/tests/test_base.py 0000664 0003720 0003720 00000052200 13156036740 017377 0 ustar travis travis 0000000 0000000 import asyncio
import fcntl
import logging
import os
import threading
import time
import uvloop
import unittest
import weakref
from unittest import mock
from uvloop._testbase import UVTestCase, AIOTestCase
class _TestBase:
def test_close(self):
self.assertFalse(self.loop._closed)
self.assertFalse(self.loop.is_closed())
self.loop.close()
self.assertTrue(self.loop._closed)
self.assertTrue(self.loop.is_closed())
# it should be possible to call close() more than once
self.loop.close()
self.loop.close()
# operation blocked when the loop is closed
f = asyncio.Future(loop=self.loop)
self.assertRaises(RuntimeError, self.loop.run_forever)
self.assertRaises(RuntimeError, self.loop.run_until_complete, f)
def test_handle_weakref(self):
wd = weakref.WeakValueDictionary()
h = self.loop.call_soon(lambda: None)
wd['h'] = h # Would fail without __weakref__ slot.
def test_call_soon(self):
calls = []
def cb(inc):
calls.append(inc)
self.loop.stop()
self.loop.call_soon(cb, 10)
h = self.loop.call_soon(cb, 100)
self.assertIn('.cb', repr(h))
h.cancel()
self.assertIn('cancelled', repr(h))
self.loop.call_soon(cb, 1)
self.loop.run_forever()
self.assertEqual(calls, [10, 1])
def test_call_soon_base_exc(self):
def cb():
raise KeyboardInterrupt()
self.loop.call_soon(cb)
with self.assertRaises(KeyboardInterrupt):
self.loop.run_forever()
self.assertFalse(self.loop.is_closed())
def test_calls_debug_reporting(self):
def run_test(debug, meth, stack_adj):
context = None
def handler(loop, ctx):
nonlocal context
context = ctx
self.loop.set_debug(debug)
self.loop.set_exception_handler(handler)
def cb():
1 / 0
meth(cb)
self.assertIsNone(context)
self.loop.run_until_complete(asyncio.sleep(0.05, loop=self.loop))
self.assertIs(type(context['exception']), ZeroDivisionError)
self.assertTrue(context['message'].startswith(
'Exception in callback'))
if debug:
tb = context['source_traceback']
self.assertEqual(tb[-1 + stack_adj].name, 'run_test')
else:
self.assertFalse('source_traceback' in context)
del context
for debug in (True, False):
for meth_name, meth, stack_adj in (
('call_soon',
self.loop.call_soon, 0),
('call_later', # `-1` accounts for lambda
lambda *args: self.loop.call_later(0.01, *args), -1)
):
with self.subTest(debug=debug, meth_name=meth_name):
run_test(debug, meth, stack_adj)
def test_now_update(self):
async def run():
st = self.loop.time()
time.sleep(0.05)
return self.loop.time() - st
delta = self.loop.run_until_complete(run())
self.assertTrue(delta > 0.049 and delta < 0.6)
def test_call_later_1(self):
calls = []
def cb(inc=10, stop=False):
calls.append(inc)
self.assertTrue(self.loop.is_running())
if stop:
self.loop.call_soon(self.loop.stop)
self.loop.call_later(0.05, cb)
# canceled right away
h = self.loop.call_later(0.05, cb, 100, True)
self.assertIn('.cb', repr(h))
h.cancel()
self.assertIn('cancelled', repr(h))
self.loop.call_later(0.05, cb, 1, True)
self.loop.call_later(1000, cb, 1000) # shouldn't be called
started = time.monotonic()
self.loop.run_forever()
finished = time.monotonic()
self.assertEqual(calls, [10, 1])
self.assertFalse(self.loop.is_running())
self.assertLess(finished - started, 0.1)
self.assertGreater(finished - started, 0.04)
def test_call_later_2(self):
# Test that loop.call_later triggers an update of
# libuv cached time.
async def main():
await asyncio.sleep(0.001, loop=self.loop)
time.sleep(0.01)
await asyncio.sleep(0.01, loop=self.loop)
started = time.monotonic()
self.loop.run_until_complete(main())
delta = time.monotonic() - started
self.assertGreater(delta, 0.019)
def test_call_later_negative(self):
calls = []
def cb(arg):
calls.append(arg)
self.loop.stop()
self.loop.call_later(-1, cb, 'a')
self.loop.run_forever()
self.assertEqual(calls, ['a'])
def test_call_at(self):
if os.environ.get('TRAVIS_OS_NAME'):
# Time seems to be really unpredictable on Travis.
raise unittest.SkipTest('time is not monotonic on Travis')
i = 0
def cb(inc):
nonlocal i
i += inc
self.loop.stop()
at = self.loop.time() + 0.05
self.loop.call_at(at, cb, 100).cancel()
self.loop.call_at(at, cb, 10)
started = time.monotonic()
self.loop.run_forever()
finished = time.monotonic()
self.assertEqual(i, 10)
self.assertLess(finished - started, 0.07)
self.assertGreater(finished - started, 0.045)
def test_check_thread(self):
def check_thread(loop, debug):
def cb():
pass
loop.set_debug(debug)
if debug:
msg = ("Non-thread-safe operation invoked on an "
"event loop other than the current one")
with self.assertRaisesRegex(RuntimeError, msg):
loop.call_soon(cb)
with self.assertRaisesRegex(RuntimeError, msg):
loop.call_later(60, cb)
with self.assertRaisesRegex(RuntimeError, msg):
loop.call_at(loop.time() + 60, cb)
else:
loop.call_soon(cb)
loop.call_later(60, cb)
loop.call_at(loop.time() + 60, cb)
def check_in_thread(loop, event, debug, create_loop, fut):
# wait until the event loop is running
event.wait()
try:
if create_loop:
loop2 = self.new_loop()
try:
asyncio.set_event_loop(loop2)
check_thread(loop, debug)
finally:
asyncio.set_event_loop(None)
loop2.close()
else:
check_thread(loop, debug)
except Exception as exc:
loop.call_soon_threadsafe(fut.set_exception, exc)
else:
loop.call_soon_threadsafe(fut.set_result, None)
def test_thread(loop, debug, create_loop=False):
event = threading.Event()
fut = asyncio.Future(loop=loop)
loop.call_soon(event.set)
args = (loop, event, debug, create_loop, fut)
thread = threading.Thread(target=check_in_thread, args=args)
thread.start()
loop.run_until_complete(fut)
thread.join()
# raise RuntimeError if the thread has no event loop
test_thread(self.loop, True)
# check disabled if debug mode is disabled
test_thread(self.loop, False)
# raise RuntimeError if the event loop of the thread is not the called
# event loop
test_thread(self.loop, True, create_loop=True)
# check disabled if debug mode is disabled
test_thread(self.loop, False, create_loop=True)
def test_run_once_in_executor_plain(self):
called = []
def cb(arg):
called.append(arg)
async def runner():
await self.loop.run_in_executor(None, cb, 'a')
self.loop.run_until_complete(runner())
self.assertEqual(called, ['a'])
def test_set_debug(self):
self.loop.set_debug(True)
self.assertTrue(self.loop.get_debug())
self.loop.set_debug(False)
self.assertFalse(self.loop.get_debug())
def test_run_until_complete_type_error(self):
self.assertRaises(
TypeError, self.loop.run_until_complete, 'blah')
def test_run_until_complete_loop(self):
task = asyncio.Future(loop=self.loop)
other_loop = self.new_loop()
self.addCleanup(other_loop.close)
self.assertRaises(
ValueError, other_loop.run_until_complete, task)
def test_run_until_complete_error(self):
async def foo():
raise ValueError('aaa')
with self.assertRaisesRegex(ValueError, 'aaa'):
self.loop.run_until_complete(foo())
def test_debug_slow_callbacks(self):
logger = logging.getLogger('asyncio')
self.loop.set_debug(True)
self.loop.slow_callback_duration = 0.2
self.loop.call_soon(lambda: time.sleep(0.3))
with mock.patch.object(logger, 'warning') as log:
self.loop.run_until_complete(asyncio.sleep(0, loop=self.loop))
self.assertEqual(log.call_count, 1)
# format message
msg = log.call_args[0][0] % log.call_args[0][1:]
self.assertIn('Executing