From: Ben Darnell Date: Sun, 30 Dec 2018 19:03:06 +0000 (-0500) Subject: locks: Update docs X-Git-Tag: v6.0.0b1~9^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0155041dbe62972b015a8fa7f454a804dc32bb91;p=thirdparty%2Ftornado.git locks: Update docs --- diff --git a/docs/locks.rst b/docs/locks.rst index 9f991880c..df30351ce 100644 --- a/docs/locks.rst +++ b/docs/locks.rst @@ -10,9 +10,10 @@ similar to those provided in the standard library's `asyncio package .. warning:: - Note that these primitives are not actually thread-safe and cannot be used in - place of those from the standard library--they are meant to coordinate Tornado - coroutines in a single-threaded app, not to protect shared objects in a + Note that these primitives are not actually thread-safe and cannot + be used in place of those from the standard library's `threading` + module--they are meant to coordinate Tornado coroutines in a + single-threaded app, not to protect shared objects in a multithreaded app. .. automodule:: tornado.locks diff --git a/tornado/locks.py b/tornado/locks.py index 0da19766c..8b1a53410 100644 --- a/tornado/locks.py +++ b/tornado/locks.py @@ -20,7 +20,7 @@ import types from tornado import gen, ioloop from tornado.concurrent import Future, future_set_result_unless_cancelled -from typing import Union, Optional, Type, Any +from typing import Union, Optional, Type, Any, Awaitable import typing if typing.TYPE_CHECKING: @@ -121,7 +121,7 @@ class Condition(_TimeoutGarbageCollector): result += " waiters[%s]" % len(self._waiters) return result + ">" - def wait(self, timeout: Union[float, datetime.timedelta] = None) -> "Future[bool]": + def wait(self, timeout: Union[float, datetime.timedelta] = None) -> Awaitable[bool]: """Wait for `.notify`. Returns a `.Future` that resolves ``True`` if the condition is notified, @@ -231,10 +231,10 @@ class Event(object): """ self._value = False - def wait(self, timeout: Union[float, datetime.timedelta] = None) -> "Future[None]": + def wait(self, timeout: Union[float, datetime.timedelta] = None) -> Awaitable[None]: """Block until the internal flag is true. - Returns a Future, which raises `tornado.util.TimeoutError` after a + Returns an awaitable, which raises `tornado.util.TimeoutError` after a timeout. """ fut = Future() # type: Future[None] @@ -413,10 +413,10 @@ class Semaphore(_TimeoutGarbageCollector): def acquire( self, timeout: Union[float, datetime.timedelta] = None - ) -> "Future[_ReleasingContextManager]": - """Decrement the counter. Returns a Future. + ) -> Awaitable[_ReleasingContextManager]: + """Decrement the counter. Returns an awaitable. - Block if the counter is zero and wait for a `.release`. The Future + Block if the counter is zero and wait for a `.release`. The awaitable raises `.TimeoutError` after the deadline. """ waiter = Future() # type: Future[_ReleasingContextManager] @@ -440,10 +440,7 @@ class Semaphore(_TimeoutGarbageCollector): return waiter def __enter__(self) -> None: - raise RuntimeError( - "Use Semaphore like 'with (yield semaphore.acquire())', not like" - " 'with semaphore'" - ) + raise RuntimeError("Use 'async with' instead of 'with' for Semaphore") def __exit__( self, @@ -530,10 +527,10 @@ class Lock(object): def acquire( self, timeout: Union[float, datetime.timedelta] = None - ) -> "Future[_ReleasingContextManager]": - """Attempt to lock. Returns a Future. + ) -> Awaitable[_ReleasingContextManager]: + """Attempt to lock. Returns an awaitable. - Returns a Future, which raises `tornado.util.TimeoutError` after a + Returns an awaitable, which raises `tornado.util.TimeoutError` after a timeout. """ return self._block.acquire(timeout) @@ -551,7 +548,7 @@ class Lock(object): raise RuntimeError("release unlocked lock") def __enter__(self) -> None: - raise RuntimeError("Use Lock like 'with (yield lock)', not like 'with lock'") + raise RuntimeError("Use `async with` instead of `with` for Lock") def __exit__( self, diff --git a/tornado/queues.py b/tornado/queues.py index 6c4fbd755..726477560 100644 --- a/tornado/queues.py +++ b/tornado/queues.py @@ -277,7 +277,7 @@ class Queue(Generic[_T]): if self._unfinished_tasks == 0: self._finished.set() - def join(self, timeout: Union[float, datetime.timedelta] = None) -> "Future[None]": + def join(self, timeout: Union[float, datetime.timedelta] = None) -> Awaitable[None]: """Block until all items in the queue are processed. Returns a Future, which raises `tornado.util.TimeoutError` after a diff --git a/tornado/test/locks_test.py b/tornado/test/locks_test.py index 787bfca31..7f88ab34b 100644 --- a/tornado/test/locks_test.py +++ b/tornado/test/locks_test.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +import asyncio from datetime import timedelta import typing # noqa: F401 import unittest @@ -164,7 +165,7 @@ class ConditionTest(AsyncTestCase): c = locks.Condition() # Three waiters. - futures = [c.wait() for _ in range(3)] + futures = [asyncio.ensure_future(c.wait()) for _ in range(3)] # First and second futures resolved. Second future reenters notify(), # resolving third future. @@ -180,7 +181,7 @@ class ConditionTest(AsyncTestCase): for _ in range(101): c.wait(timedelta(seconds=0.01)) - future = c.wait() + future = asyncio.ensure_future(c.wait()) self.assertEqual(102, len(c._waiters)) # Let first 101 waiters time out, triggering a collection. @@ -204,11 +205,11 @@ class EventTest(AsyncTestCase): def test_event(self): e = locks.Event() - future_0 = e.wait() + future_0 = asyncio.ensure_future(e.wait()) e.set() - future_1 = e.wait() + future_1 = asyncio.ensure_future(e.wait()) e.clear() - future_2 = e.wait() + future_2 = asyncio.ensure_future(e.wait()) self.assertTrue(future_0.done()) self.assertTrue(future_1.done()) @@ -232,9 +233,9 @@ class EventTest(AsyncTestCase): def test_event_wait_clear(self): e = locks.Event() - f0 = e.wait() + f0 = asyncio.ensure_future(e.wait()) e.clear() - f1 = e.wait() + f1 = asyncio.ensure_future(e.wait()) e.set() self.assertTrue(f0.done()) self.assertTrue(f1.done()) @@ -256,13 +257,13 @@ class SemaphoreTest(AsyncTestCase): def test_acquire(self): sem = locks.Semaphore() - f0 = sem.acquire() + f0 = asyncio.ensure_future(sem.acquire()) self.assertTrue(f0.done()) # Wait for release(). - f1 = sem.acquire() + f1 = asyncio.ensure_future(sem.acquire()) self.assertFalse(f1.done()) - f2 = sem.acquire() + f2 = asyncio.ensure_future(sem.acquire()) sem.release() self.assertTrue(f1.done()) self.assertFalse(f2.done()) @@ -271,7 +272,7 @@ class SemaphoreTest(AsyncTestCase): sem.release() # Now acquire() is instant. - self.assertTrue(sem.acquire().done()) + self.assertTrue(asyncio.ensure_future(sem.acquire()).done()) self.assertEqual(0, len(sem._waiters)) @gen_test @@ -286,7 +287,7 @@ class SemaphoreTest(AsyncTestCase): yield acquire sem.acquire() - f = sem.acquire() + f = asyncio.ensure_future(sem.acquire()) self.assertFalse(f.done()) sem.release() self.assertTrue(f.done()) @@ -309,18 +310,21 @@ class SemaphoreTest(AsyncTestCase): sem.release() # Now the counter is 3. We can acquire three times before blocking. - self.assertTrue(sem.acquire().done()) - self.assertTrue(sem.acquire().done()) - self.assertTrue(sem.acquire().done()) - self.assertFalse(sem.acquire().done()) + self.assertTrue(asyncio.ensure_future(sem.acquire()).done()) + self.assertTrue(asyncio.ensure_future(sem.acquire()).done()) + self.assertTrue(asyncio.ensure_future(sem.acquire()).done()) + self.assertFalse(asyncio.ensure_future(sem.acquire()).done()) @gen_test def test_garbage_collection(self): # Test that timed-out waiters are occasionally cleaned from the queue. sem = locks.Semaphore(value=0) - futures = [sem.acquire(timedelta(seconds=0.01)) for _ in range(101)] + futures = [ + asyncio.ensure_future(sem.acquire(timedelta(seconds=0.01))) + for _ in range(101) + ] - future = sem.acquire() + future = asyncio.ensure_future(sem.acquire()) self.assertEqual(102, len(sem._waiters)) # Let first 101 waiters time out, triggering a collection. @@ -345,7 +349,7 @@ class SemaphoreContextManagerTest(AsyncTestCase): self.assertTrue(yielded is None) # Semaphore was released and can be acquired again. - self.assertTrue(sem.acquire().done()) + self.assertTrue(asyncio.ensure_future(sem.acquire()).done()) @gen_test def test_context_manager_async_await(self): @@ -359,7 +363,7 @@ class SemaphoreContextManagerTest(AsyncTestCase): yield f() # Semaphore was released and can be acquired again. - self.assertTrue(sem.acquire().done()) + self.assertTrue(asyncio.ensure_future(sem.acquire()).done()) @gen_test def test_context_manager_exception(self): @@ -369,7 +373,7 @@ class SemaphoreContextManagerTest(AsyncTestCase): 1 / 0 # Semaphore was released and can be acquired again. - self.assertTrue(sem.acquire().done()) + self.assertTrue(asyncio.ensure_future(sem.acquire()).done()) @gen_test def test_context_manager_timeout(self): @@ -378,7 +382,7 @@ class SemaphoreContextManagerTest(AsyncTestCase): pass # Semaphore was released and can be acquired again. - self.assertTrue(sem.acquire().done()) + self.assertTrue(asyncio.ensure_future(sem.acquire()).done()) @gen_test def test_context_manager_timeout_error(self): @@ -388,7 +392,7 @@ class SemaphoreContextManagerTest(AsyncTestCase): pass # Counter is still 0. - self.assertFalse(sem.acquire().done()) + self.assertFalse(asyncio.ensure_future(sem.acquire()).done()) @gen_test def test_context_manager_contended(self): @@ -433,7 +437,7 @@ class BoundedSemaphoreTest(AsyncTestCase): # Value is 0. sem.acquire() # Block on acquire(). - future = sem.acquire() + future = asyncio.ensure_future(sem.acquire()) self.assertFalse(future.done()) sem.release() self.assertTrue(future.done()) @@ -452,8 +456,8 @@ class LockTests(AsyncTestCase): def test_acquire_release(self): lock = locks.Lock() - self.assertTrue(lock.acquire().done()) - future = lock.acquire() + self.assertTrue(asyncio.ensure_future(lock.acquire()).done()) + future = asyncio.ensure_future(lock.acquire()) self.assertFalse(future.done()) lock.release() self.assertTrue(future.done()) @@ -461,7 +465,7 @@ class LockTests(AsyncTestCase): @gen_test def test_acquire_fifo(self): lock = locks.Lock() - self.assertTrue(lock.acquire().done()) + self.assertTrue(asyncio.ensure_future(lock.acquire()).done()) N = 5 history = [] @@ -481,7 +485,7 @@ class LockTests(AsyncTestCase): # Repeat the above test using `async with lock:` # instead of `with (yield lock.acquire()):`. lock = locks.Lock() - self.assertTrue(lock.acquire().done()) + self.assertTrue(asyncio.ensure_future(lock.acquire()).done()) N = 5 history = [] @@ -502,7 +506,7 @@ class LockTests(AsyncTestCase): yield lock.acquire(timeout=timedelta(seconds=0.01)) # Still locked. - self.assertFalse(lock.acquire().done()) + self.assertFalse(asyncio.ensure_future(lock.acquire()).done()) def test_multi_release(self): lock = locks.Lock()