# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Test cases for L{twisted.internet.defer} on Python 3.5 and later. This file is loaded by C{test_defer.py} only when running on an interpreter version that supports the C{async} and C{await} keywords. """ import functools from twisted.internet import defer from twisted.trial import unittest def ensuringDeferred(f): @functools.wraps(f) def wrapper(*args, **kwargs): result = f(*args, **kwargs) return defer.ensureDeferred(result) return wrapper class DeferredTestsAsync(unittest.TestCase): @ensuringDeferred async def test_asyncWithLock(self): """ L{defer.DeferredLock} can be used as an asynchronous context manager. """ lock = defer.DeferredLock() async with lock: self.assertTrue(lock.locked) d = lock.acquire() d.addCallback(lambda _: lock.release()) self.assertTrue(lock.locked) self.assertFalse(d.called) self.assertTrue(d.called) await d self.assertFalse(lock.locked) @ensuringDeferred async def test_asyncWithSemaphore(self): """ L{defer.DeferredSemaphore} can be used as an asynchronous context manager. """ sem = defer.DeferredSemaphore(3) async with sem: self.assertEqual(sem.tokens, 2) async with sem: self.assertEqual(sem.tokens, 1) d1 = sem.acquire() d2 = sem.acquire() self.assertEqual(sem.tokens, 0) self.assertTrue(d1.called) self.assertFalse(d2.called) self.assertEqual(sem.tokens, 0) self.assertTrue(d2.called) d1.addCallback(lambda _: sem.release()) d2.addCallback(lambda _: sem.release()) await d1 await d2 self.assertEqual(sem.tokens, 2) self.assertEqual(sem.tokens, 3) @ensuringDeferred async def test_asyncWithLockException(self): """ C{defer.DeferredLock} correctly propagates exceptions when used as an asynchronous context manager. """ lock = defer.DeferredLock() with self.assertRaisesRegexp(Exception, 'some specific exception'): async with lock: self.assertTrue(lock.locked) raise Exception('some specific exception') self.assertFalse(lock.locked)