Skip to content

Commit fe90d32

Browse files
committed
[#35] Since 3.8, CancelledError is a subclass of BaseException rather than Exception, so we need to catch it explicitly.
1 parent 0b720c9 commit fe90d32

File tree

4 files changed

+40
-3
lines changed

4 files changed

+40
-3
lines changed

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
3.1.1
2+
-----
3+
4+
* Since 3.8, CancelledError is a subclass of BaseException rather than Exception, so we need to catch it explicitly.
5+
16
3.1.0
27
-----
38

memoize/wrapper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import datetime
77
import functools
88
import logging
9-
from asyncio import Future
9+
from asyncio import Future, CancelledError
1010
from typing import Optional, Callable
1111

1212
from memoize.configuration import CacheConfiguration, NotConfiguredCacheCalledException, \
@@ -116,7 +116,7 @@ async def refresh(actual_entry: Optional[CacheEntry], key: CacheKey,
116116
logger.debug('Timeout for %s: %s', key, e)
117117
update_statuses.mark_update_aborted(key, e)
118118
raise CachedMethodFailedException('Refresh timed out') from e
119-
except Exception as e:
119+
except (Exception, CancelledError) as e:
120120
logger.debug('Error while refreshing cache for %s: %s', key, e)
121121
update_statuses.mark_update_aborted(key, e)
122122
raise CachedMethodFailedException('Refresh failed to complete') from e

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def prepare_description():
1111

1212
setup(
1313
name='py-memoize',
14-
version='3.1.0',
14+
version='3.1.1',
1515
author='Michal Zmuda',
1616
author_email='[email protected]',
1717
url='https://github.com/DreamLab/memoize',

tests/end2end/test_wrapper.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import asyncio
22
import time
3+
from asyncio import CancelledError
34
from datetime import timedelta
45
from unittest.mock import Mock
56

@@ -174,6 +175,37 @@ async def get_value(arg, kwarg=None):
174175
assert context.value.__class__ == CachedMethodFailedException
175176
assert str(context.value.__cause__) == str(ValueError('stub0'))
176177

178+
async def test_should_return_cancelled_exception_for_all_concurrent_callers(self):
179+
# given
180+
value = 0
181+
182+
@memoize()
183+
async def get_value(arg, kwarg=None):
184+
new_task = asyncio.create_task(asyncio.sleep(1))
185+
new_task.cancel() # this will raise CancelledError
186+
await new_task
187+
188+
# when
189+
res1 = get_value('test', kwarg='args1')
190+
res2 = get_value('test', kwarg='args1')
191+
res3 = get_value('test', kwarg='args1')
192+
193+
# then
194+
with pytest.raises(Exception) as context:
195+
await res1
196+
assert context.value.__class__ == CachedMethodFailedException
197+
assert str(context.value.__cause__) == str(CancelledError())
198+
199+
with pytest.raises(Exception) as context:
200+
await res2
201+
assert context.value.__class__ == CachedMethodFailedException
202+
assert str(context.value.__cause__) == str(CancelledError())
203+
204+
with pytest.raises(Exception) as context:
205+
await res3
206+
assert context.value.__class__ == CachedMethodFailedException
207+
assert str(context.value.__cause__) == str(CancelledError())
208+
177209
async def test_should_return_timeout_for_all_concurrent_callers(self):
178210
# given
179211
value = 0

0 commit comments

Comments
 (0)