commit: 6c865d6b3130de63dc3d534d2a0596dd59d5e662 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Tue Apr 24 02:21:59 2018 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Thu Apr 26 03:19:21 2018 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=6c865d6b
AsynchronousTask: add scheduler attribute (bug 653856) 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)