10000 bpo-42392: Update code after merge review from 1st1 by uriyyo · Pull Request #23499 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-42392: Update code after merge review from 1st1 #23499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions Lib/asyncio/locks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@
from . import mixins


# Used as a sentinel for loop parameter
_marker = object()


def _verify_no_loop(obj, loop):
if loop is not _marker:
raise TypeError(
f'As of 3.10, the *loop* parameter was removed from '
f'{type(obj).__name__}() since it is no longer necessary'
)


class _ContextManagerMixin:
async def __aenter__(self):
await self.acquire()
Expand All @@ -19,7 +31,7 @@ async def __aexit__(self, exc_type, exc, tb):
self.release()


class Lock(_ContextManagerMixin, mixins._LoopBoundedMixin):
class Lock(_ContextManagerMixin, mixins._LoopBoundMixin):
"""Primitive lock objects.

A primitive lock is a synchronization primitive that is not owned
Expand Down Expand Up @@ -73,7 +85,8 @@ class Lock(_ContextManagerMixin, mixins._LoopBoundedMixin):

"""

def __init__(self):
def __init__(self, *, loop=_marker):
_verify_no_loop(self, loop)
self._waiters = None
self._locked = False

Expand Down Expand Up @@ -153,7 +166,7 @@ def _wake_up_first(self):
fut.set_result(True)


class Event(mixins._LoopBoundedMixin):
class Event(mixins._LoopBoundMixin):
"""Asynchronous equivalent to threading.Event.

Class implementing event objects. An event manages a flag that can be set
Expand All @@ -162,7 +175,8 @@ class Event(mixins._LoopBoundedMixin):
false.
"""

def __init__(self):
def __init__(self, loop=_marker):
_verify_no_loop(self, loop)
self._waiters = collections.deque()
self._value = False

Expand Down Expand Up @@ -214,7 +228,7 @@ async def wait(self):
self._waiters.remove(fut)


class Condition(_ContextManagerMixin, mixins._LoopBoundedMixin):
class Condition(_ContextManagerMixin, mixins._LoopBoundMixin):
"""Asynchronous equivalent to threading.Condition.

This class implements condition variable objects. A condition variable
Expand All @@ -224,7 +238,8 @@ class Condition(_ContextManagerMixin, mixins._LoopBoundedMixin):
A new Lock object is created and used as the underlying lock.
"""

def __init__(self, lock=None):
def __init__(self, lock=None, *, loop=_marker):
_verify_no_loop(self, loop)
if lock is None:
lock = Lock()
elif lock._loop is not self._get_loop():
Expand Down Expand Up @@ -328,7 +343,7 @@ def notify_all(self):
self.notify(len(self._waiters))


class Semaphore(_ContextManagerMixin, mixins._LoopBoundedMixin):
class Semaphore(_ContextManagerMixin, mixins._LoopBoundMixin):
"""A Semaphore implementation.

A semaphore manages an internal counter which is decremented by each
Expand All @@ -343,7 +358,8 @@ class Semaphore(_ContextManagerMixin, mixins._LoopBoundedMixin):
ValueError is raised.
"""

def __init__(self, value=1):
def __init__(self, value=1, *, loop=_marker):
_verify_no_loop(self, loop)
if value < 0:
raise ValueError("Semaphore initial value must be >= 0")
self._value = value
Expand Down Expand Up @@ -406,7 +422,8 @@ class BoundedSemaphore(Semaphore):
above the initial value.
"""

def __init__(self, value=1):
def __init__(self, value=1, *, loop=_marker):
_verify_no_loop(self, loop)
self._bound_value = value
super().__init__(value)

Expand Down
4 changes: 2 additions & 2 deletions Lib/asyncio/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
_global_lock = threading.Lock()


class _LoopBoundedMixin:
class _LoopBoundMixin:
_loop = None

def _get_loop(self):
Expand All @@ -17,5 +17,5 @@ def _get_loop(self):
if self._loop is None:
self._loop = loop
if loop is not self._loop:
raise RuntimeError(f'{type(self).__name__} have already bounded to another loop')
raise RuntimeError(f'{self!r} is bound to a different event loop')
return loop
2 changes: 1 addition & 1 deletion Lib/asyncio/queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class QueueFull(Exception):
pass


class Queue(mixins._LoopBoundedMixin):
class Queue(mixins._LoopBoundMixin):
"""A queue, useful for coordinating producer and consumer coroutines.

If maxsize is less than or equal to zero, the queue size is infinite. If it
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/test_asyncio/test_locks.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ def acquire_lock():

self.assertFalse(lock.locked())

def test_lock_doesnt_accept_loop_parameter(self):
primitives_cls = [
asyncio.Lock,
asyncio.Condition,
asyncio.Event,
asyncio.Semaphore,
asyncio.BoundedSemaphore,
]

for cls in primitives_cls:
with self.assertRaisesRegex(
TypeError,
rf'As of 3.10, the \*loop\* parameter was removed from '
rf'{cls.__name__}\(\) since it is no longer necessary'
):
cls(loop=self.loop)

def test_lock_by_with_statement(self):
loop = asyncio.new_event_loop() # don't use TestLoop quirks
self.set_event_loop(loop)
Expand Down
21 changes: 0 additions & 21 deletions Lib/test/test_asyncio/utils.py
< 388B /table>
0
Original file line number Diff line number Diff line change
Expand Up @@ -541,31 +541,10 @@ def new_test_loop(self, gen=None):
self.set_event_loop(loop)
return loop

def unpatch_get_running_loop(self):
events._get_running_loop = self._get_running_loop

def setUp(self):
self._get_running_loop = events._get_running_loop

def _get_running_loop():
frame = sys._getframe(1)

if frame.f_globals['__name__'] == 'asyncio.mixins':
# When we called from LoopBoundedMixin we should
# fallback to default implementation of get_running_loop
try:
return events.get_running_loop()
except RuntimeError:
return None

return None

events._get_running_loop = _get_running_loop
self._thread_cleanup = threading_helper.threading_setup()

def tearDown(self):
self.unpatch_get_running_loop()

events.set_event_loop(None)

# Detect CPython bug #23353: ensure that yield/yield-from is not used
Expand Down