Add an AsynchronousTask.scheduler attribute, which will hold an event
loop instance in order to work with Future instances. Name the
attribute "scheduler" because this is the name used by many existing
subclasses of AsynchronousTask. Since the AsyncScheduler class already
has an _event_loop attribute that it inherits from PollScheduler, use
a property for compatibility. Also update the SlotObject constructor
to allow a subclass to override an attribute from __slots__ with a
property, so that AsyncScheduler can use a property for the scheduler
attribute.

Bug: https://bugs.gentoo.org/653856
---
 pym/_emerge/AbstractPollTask.py            | 3 +--
 pym/_emerge/AsynchronousLock.py            | 2 +-
 pym/_emerge/AsynchronousTask.py            | 2 +-
 pym/_emerge/CompositeTask.py               | 2 +-
 pym/portage/util/SlotObject.py             | 9 ++++++++-
 pym/portage/util/_async/AsyncScheduler.py  | 7 +++++++
 pym/portage/util/_async/AsyncTaskFuture.py | 2 +-
 7 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/pym/_emerge/AbstractPollTask.py b/pym/_emerge/AbstractPollTask.py
index 0d38bd481..aa8fc6593 100644
--- a/pym/_emerge/AbstractPollTask.py
+++ b/pym/_emerge/AbstractPollTask.py
@@ -11,8 +11,7 @@ from _emerge.AsynchronousTask import AsynchronousTask
 
 class AbstractPollTask(AsynchronousTask):
 
-       __slots__ = ("scheduler",) + \
-               ("_registered",)
+       __slots__ = ("_registered",)
 
        _bufsize = 4096
 
diff --git a/pym/_emerge/AsynchronousLock.py b/pym/_emerge/AsynchronousLock.py
index 78ab37ecb..0178feab2 100644
--- a/pym/_emerge/AsynchronousLock.py
+++ b/pym/_emerge/AsynchronousLock.py
@@ -37,7 +37,7 @@ class AsynchronousLock(AsynchronousTask):
        signals to the main thread).
        """
 
-       __slots__ = ('path', 'scheduler',) + \
+       __slots__ = ('path',) + \
                ('_imp', '_force_async', '_force_dummy', '_force_process', \
                '_force_thread', '_unlock_future')
 
diff --git a/pym/_emerge/AsynchronousTask.py b/pym/_emerge/AsynchronousTask.py
index da58261db..e29324440 100644
--- a/pym/_emerge/AsynchronousTask.py
+++ b/pym/_emerge/AsynchronousTask.py
@@ -16,7 +16,7 @@ class AsynchronousTask(SlotObject):
        the task is complete and self.returncode has been set.
        """
 
-       __slots__ = ("background", "cancelled", "returncode") + \
+       __slots__ = ("background", "cancelled", "returncode", "scheduler") + \
                ("_exit_listeners", "_exit_listener_stack", "_start_listeners",
                "_waiting")
 
diff --git a/pym/_emerge/CompositeTask.py b/pym/_emerge/CompositeTask.py
index f3acc9696..bfd4bacbd 100644
--- a/pym/_emerge/CompositeTask.py
+++ b/pym/_emerge/CompositeTask.py
@@ -6,7 +6,7 @@ from portage import os
 
 class CompositeTask(AsynchronousTask):
 
-       __slots__ = ("scheduler",) + ("_current_task",)
+       __slots__ = ("_current_task",)
 
        _TASK_QUEUED = -1
 
diff --git a/pym/portage/util/SlotObject.py b/pym/portage/util/SlotObject.py
index 4bb682258..ba6215874 100644
--- a/pym/portage/util/SlotObject.py
+++ b/pym/portage/util/SlotObject.py
@@ -20,7 +20,14 @@ class SlotObject(object):
                                        raise AssertionError(
                                                "class '%s' duplicates '%s' 
value in __slots__ of base class '%s'" %
                                                (self.__class__.__name__, 
myattr, c.__name__))
-                               setattr(self, myattr, myvalue)
+                               try:
+                                       setattr(self, myattr, myvalue)
+                               except AttributeError:
+                                       # Allow a property to override a 
__slots__ value, but raise an
+                                       # error if the intended value is 
something other than None.
+                                       if not (myvalue is None and
+                                               isinstance(getattr(type(self), 
myattr, None), property)):
+                                               raise
 
                if kwargs:
                        raise TypeError(
diff --git a/pym/portage/util/_async/AsyncScheduler.py 
b/pym/portage/util/_async/AsyncScheduler.py
index 9beb8a848..b89b57dab 100644
--- a/pym/portage/util/_async/AsyncScheduler.py
+++ b/pym/portage/util/_async/AsyncScheduler.py
@@ -20,6 +20,13 @@ class AsyncScheduler(AsynchronousTask, PollScheduler):
                self._remaining_tasks = True
                self._loadavg_check_id = None
 
+       @property
+       def scheduler(self):
+               """
+               Provides compatibility with the AsynchronousTask.scheduler 
attribute.
+               """
+               return self._event_loop
+
        def _poll(self):
                if not (self._is_work_scheduled() or self._keep_scheduling()):
                        self.wait()
diff --git a/pym/portage/util/_async/AsyncTaskFuture.py 
b/pym/portage/util/_async/AsyncTaskFuture.py
index c2316deeb..ce881ba8d 100644
--- a/pym/portage/util/_async/AsyncTaskFuture.py
+++ b/pym/portage/util/_async/AsyncTaskFuture.py
@@ -12,7 +12,7 @@ class AsyncTaskFuture(AsynchronousTask):
        Wraps a Future in an AsynchronousTask, which is useful for
        scheduling with TaskScheduler.
        """
-       __slots__ = ('future', 'scheduler')
+       __slots__ = ('future',)
        def _start(self):
                self.future.add_done_callback(self._done_callback)
 
-- 
2.13.6


Reply via email to