commit:     b2d8226af4589d95f44d20d441056f645a523039
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Thu Feb 29 04:26:02 2024 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Thu Feb 29 04:37:21 2024 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=b2d8226a

Delete compat_coroutine module

The compat_coroutine module has been unused since the migration
to PEP 492 async and await syntax in 2021, which began in commit
b3b9acc13c43 and was completed in commit bcda30d0a6fa.

Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 lib/portage/tests/util/futures/meson.build         |   1 -
 .../tests/util/futures/test_compat_coroutine.py    | 210 ---------------------
 lib/portage/util/futures/_asyncio/__init__.py      |  15 +-
 lib/portage/util/futures/compat_coroutine.py       | 142 --------------
 lib/portage/util/futures/meson.build               |   1 -
 5 files changed, 1 insertion(+), 368 deletions(-)

diff --git a/lib/portage/tests/util/futures/meson.build 
b/lib/portage/tests/util/futures/meson.build
index 877acc27cd..cb78314844 100644
--- a/lib/portage/tests/util/futures/meson.build
+++ b/lib/portage/tests/util/futures/meson.build
@@ -1,6 +1,5 @@
 py.install_sources(
     [
-        'test_compat_coroutine.py',
         'test_done_callback.py',
         'test_done_callback_after_exit.py',
         'test_iter_completed.py',

diff --git a/lib/portage/tests/util/futures/test_compat_coroutine.py 
b/lib/portage/tests/util/futures/test_compat_coroutine.py
deleted file mode 100644
index b25708886c..0000000000
--- a/lib/portage/tests/util/futures/test_compat_coroutine.py
+++ /dev/null
@@ -1,210 +0,0 @@
-# Copyright 2018 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-from portage.util.futures import asyncio
-from portage.util.futures.compat_coroutine import (
-    coroutine,
-    coroutine_return,
-)
-from portage.util.futures._sync_decorator import _sync_decorator, _sync_methods
-from portage.tests import TestCase
-
-
-class CompatCoroutineTestCase(TestCase):
-    def test_returning_coroutine(self):
-        @coroutine
-        def returning_coroutine(loop=None):
-            yield asyncio.sleep(0, loop=loop)
-            coroutine_return("success")
-
-        loop = asyncio.get_event_loop()
-        self.assertEqual(
-            "success",
-            
asyncio.get_event_loop().run_until_complete(returning_coroutine(loop=loop)),
-        )
-
-    def test_raising_coroutine(self):
-        class TestException(Exception):
-            pass
-
-        @coroutine
-        def raising_coroutine(loop=None):
-            yield asyncio.sleep(0, loop=loop)
-            raise TestException("exception")
-
-        loop = asyncio.get_event_loop()
-        self.assertRaises(
-            TestException, loop.run_until_complete, 
raising_coroutine(loop=loop)
-        )
-
-    def test_catching_coroutine(self):
-        class TestException(Exception):
-            pass
-
-        @coroutine
-        def catching_coroutine(loop=None):
-            loop = asyncio._wrap_loop(loop)
-            future = loop.create_future()
-            loop.call_soon(future.set_exception, TestException("exception"))
-            try:
-                yield future
-            except TestException:
-                self.assertTrue(True)
-            else:
-                self.assertTrue(False)
-            coroutine_return("success")
-
-        loop = asyncio.get_event_loop()
-        self.assertEqual(
-            "success", loop.run_until_complete(catching_coroutine(loop=loop))
-        )
-
-    def test_cancelled_coroutine(self):
-        """
-        Verify that a coroutine can handle (and reraise) asyncio.CancelledError
-        in order to perform any necessary cleanup. Note that the
-        asyncio.CancelledError will only be thrown in the coroutine if there's
-        an opportunity (yield) before the generator raises StopIteration.
-        """
-        loop = asyncio.get_event_loop()
-        ready_for_exception = loop.create_future()
-        exception_in_coroutine = loop.create_future()
-
-        @coroutine
-        def cancelled_coroutine(loop=None):
-            loop = asyncio._wrap_loop(loop)
-            while True:
-                task = loop.create_future()
-                try:
-                    ready_for_exception.set_result(None)
-                    yield task
-                except BaseException as e:
-                    # Since python3.8, asyncio.CancelledError inherits
-                    # from BaseException.
-                    task.done() or task.cancel()
-                    exception_in_coroutine.set_exception(e)
-                    raise
-                else:
-                    exception_in_coroutine.set_result(None)
-
-        future = cancelled_coroutine(loop=loop)
-        loop.run_until_complete(ready_for_exception)
-        future.cancel()
-
-        self.assertRaises(asyncio.CancelledError, loop.run_until_complete, 
future)
-
-        self.assertRaises(
-            asyncio.CancelledError, loop.run_until_complete, 
exception_in_coroutine
-        )
-
-    def test_cancelled_future(self):
-        """
-        When a coroutine raises CancelledError, the coroutine's
-        future is cancelled.
-        """
-
-        @coroutine
-        def cancelled_future_coroutine(loop=None):
-            loop = asyncio._wrap_loop(loop)
-            while True:
-                future = loop.create_future()
-                loop.call_soon(future.cancel)
-                yield future
-
-        loop = asyncio.get_event_loop()
-        future = loop.run_until_complete(
-            asyncio.wait([cancelled_future_coroutine(loop=loop)], loop=loop)
-        )[0].pop()
-        self.assertTrue(future.cancelled())
-
-    def test_yield_expression_result(self):
-        @coroutine
-        def yield_expression_coroutine(loop=None):
-            for i in range(3):
-                x = yield asyncio.sleep(0, result=i, loop=loop)
-                self.assertEqual(x, i)
-
-        loop = asyncio.get_event_loop()
-        loop.run_until_complete(yield_expression_coroutine(loop=loop))
-
-    def test_method_coroutine(self):
-        class Cubby:
-            _empty = object()
-
-            def __init__(self, loop):
-                self._loop = loop
-                self._value = self._empty
-                self._waiters = []
-
-            def _notify(self):
-                waiters = self._waiters
-                self._waiters = []
-                for waiter in waiters:
-                    waiter.cancelled() or waiter.set_result(None)
-
-            def _wait(self):
-                waiter = self._loop.create_future()
-                self._waiters.append(waiter)
-                return waiter
-
-            @coroutine
-            def read(self, loop=None):
-                while self._value is self._empty:
-                    yield self._wait()
-
-                value = self._value
-                self._value = self._empty
-                self._notify()
-                coroutine_return(value)
-
-            @coroutine
-            def write(self, value, loop=None):
-                while self._value is not self._empty:
-                    yield self._wait()
-
-                self._value = value
-                self._notify()
-
-        @coroutine
-        def writer_coroutine(cubby, values, sentinel, loop=None):
-            for value in values:
-                yield cubby.write(value, loop=loop)
-            yield cubby.write(sentinel, loop=loop)
-
-        @coroutine
-        def reader_coroutine(cubby, sentinel, loop=None):
-            results = []
-            while True:
-                result = yield cubby.read(loop=loop)
-                if result == sentinel:
-                    break
-                results.append(result)
-            coroutine_return(results)
-
-        loop = asyncio.get_event_loop()
-        cubby = Cubby(loop)
-        values = list(range(3))
-        writer = asyncio.ensure_future(
-            writer_coroutine(cubby, values, None, loop=loop), loop=loop
-        )
-        reader = asyncio.ensure_future(
-            reader_coroutine(cubby, None, loop=loop), loop=loop
-        )
-        loop.run_until_complete(asyncio.wait([writer, reader], loop=loop))
-
-        self.assertEqual(reader.result(), values)
-
-        # Test decoration of coroutine methods and functions for
-        # synchronous usage, allowing coroutines to smoothly
-        # blend with synchronous code.
-        sync_cubby = _sync_methods(cubby, loop=loop)
-        sync_reader = _sync_decorator(reader_coroutine, loop=loop)
-        writer = asyncio.ensure_future(
-            writer_coroutine(cubby, values, None, loop=loop), loop=loop
-        )
-        self.assertEqual(sync_reader(cubby, None), values)
-        self.assertTrue(writer.done())
-
-        for i in range(3):
-            sync_cubby.write(i)
-            self.assertEqual(sync_cubby.read(), i)

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index 4eecc46a89..e377a9cdd1 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -38,6 +38,7 @@ from asyncio import (
     FIRST_EXCEPTION,
     Future,
     InvalidStateError,
+    iscoroutinefunction,
     Lock as _Lock,
     shield,
     TimeoutError,
@@ -51,7 +52,6 @@ import portage
 portage.proxy.lazyimport.lazyimport(
     globals(),
     "portage.util.futures.unix_events:_PortageEventLoopPolicy",
-    "portage.util.futures:compat_coroutine@_compat_coroutine",
 )
 from portage.util._eventloop.asyncio_event_loop import (
     AsyncioEventLoop as _AsyncioEventLoop,
@@ -158,19 +158,6 @@ def wait(futures, loop=None, timeout=None, 
return_when=ALL_COMPLETED):
     return _real_asyncio.wait(futures, timeout=timeout, 
return_when=return_when)
 
 
-def iscoroutinefunction(func):
-    """
-    Return True if func is a decorated coroutine function,
-    supporting both asyncio.coroutine and compat_coroutine since
-    their behavior is identical for all practical purposes.
-    """
-    if _compat_coroutine._iscoroutinefunction(func):
-        return True
-    if _real_asyncio.iscoroutinefunction(func):
-        return True
-    return False
-
-
 class Lock(_Lock):
     """
     Inject loop parameter for python3.9 or less in order to avoid

diff --git a/lib/portage/util/futures/compat_coroutine.py 
b/lib/portage/util/futures/compat_coroutine.py
deleted file mode 100644
index afb8500402..0000000000
--- a/lib/portage/util/futures/compat_coroutine.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# Copyright 2018-2021 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-import functools
-
-import portage
-
-portage.proxy.lazyimport.lazyimport(
-    globals(),
-    "portage.util.futures:asyncio",
-)
-
-# A marker for iscoroutinefunction.
-_is_coroutine = object()
-
-
-def _iscoroutinefunction(func):
-    """
-    Return True if func is a decorated coroutine function
-    created with the coroutine decorator for this module.
-    """
-    return getattr(func, "_is_coroutine", None) is _is_coroutine
-
-
-def coroutine(generator_func):
-    """
-    A decorator for a generator function that behaves as coroutine function.
-    The generator should yield a Future instance in order to wait for it,
-    and the result becomes the result of the current yield-expression,
-    via the PEP 342 generator send() method.
-
-    The decorated function returns a Future which is done when the generator
-    is exhausted. The generator can return a value via the coroutine_return
-    function.
-
-    @param generator_func: A generator function that yields Futures, and
-            will receive the result of each Future as the result of the
-            corresponding yield-expression.
-    @type generator_func: function
-    @rtype: function
-    @return: A function which calls the given generator function and
-            returns a Future that is done when the generator is exhausted.
-    """
-
-    # Note that functools.partial does not work for decoration of
-    # methods, since it doesn't implement the descriptor protocol.
-    # This problem is solve by defining a wrapper function.
-    @functools.wraps(generator_func)
-    def wrapped(*args, **kwargs):
-        return _generator_future(generator_func, *args, **kwargs)
-
-    wrapped._is_coroutine = _is_coroutine
-    return wrapped
-
-
-def coroutine_return(result=None):
-    """
-    Terminate the current coroutine and set the result of the associated
-    Future.
-
-    @param result: of the current coroutine's Future
-    @type object
-    """
-    raise _CoroutineReturnValue(result)
-
-
-def _generator_future(generator_func, *args, **kwargs):
-    """
-    Call generator_func with the given arguments, and return a Future
-    that is done when the resulting generation is exhausted. If a
-    keyword argument named 'loop' is given, then it is used instead of
-    the default event loop.
-    """
-    loop = kwargs.get("loop")
-    loop = asyncio._wrap_loop(loop)
-    result = loop.create_future()
-    _GeneratorTask(generator_func(*args, **kwargs), result, loop=loop)
-    return result
-
-
-class _CoroutineReturnValue(Exception):
-    def __init__(self, result):
-        self.result = result
-
-
-class _GeneratorTask:
-    """
-    Asynchronously executes the generator to completion, waiting for
-    the result of each Future that it yields, and sending the result
-    to the generator.
-    """
-
-    def __init__(self, generator, result, loop):
-        self._generator = generator
-        self._result = result
-        self._current_task = None
-        self._loop = loop
-        result.add_done_callback(self._cancel_callback)
-        loop.call_soon(self._next)
-
-    def _cancel_callback(self, result):
-        if result.cancelled() and self._current_task is not None:
-            # The done callback for self._current_task invokes
-            # _next in either case here.
-            self._current_task.done() or self._current_task.cancel()
-
-    def _next(self, previous=None):
-        self._current_task = None
-        if self._result.cancelled():
-            if previous is not None:
-                # Consume exceptions, in order to avoid triggering
-                # the event loop's exception handler.
-                previous.cancelled() or previous.exception()
-
-            # This will throw asyncio.CancelledError in the coroutine if
-            # there's an opportunity (yield) before the generator raises
-            # StopIteration.
-            previous = self._result
-        try:
-            if previous is None:
-                future = next(self._generator)
-            elif previous.cancelled():
-                future = self._generator.throw(asyncio.CancelledError())
-            elif previous.exception() is None:
-                future = self._generator.send(previous.result())
-            else:
-                future = self._generator.throw(previous.exception())
-
-        except asyncio.CancelledError:
-            self._result.cancel()
-        except _CoroutineReturnValue as e:
-            if not self._result.cancelled():
-                self._result.set_result(e.result)
-        except StopIteration:
-            if not self._result.cancelled():
-                self._result.set_result(None)
-        except Exception as e:
-            if not self._result.cancelled():
-                self._result.set_exception(e)
-        else:
-            self._current_task = asyncio.ensure_future(future, loop=self._loop)
-            self._current_task.add_done_callback(self._next)

diff --git a/lib/portage/util/futures/meson.build 
b/lib/portage/util/futures/meson.build
index 90bfc86669..d561fa312a 100644
--- a/lib/portage/util/futures/meson.build
+++ b/lib/portage/util/futures/meson.build
@@ -1,6 +1,5 @@
 py.install_sources(
     [
-        'compat_coroutine.py',
         'extendedfutures.py',
         'futures.py',
         'iter_completed.py',

Reply via email to