1 |
Add an AsynchronousTask.scheduler attribute, which will hold an event |
2 |
loop instance in order to work with Future instances. Name the |
3 |
attribute "scheduler" because this is the name used by many existing |
4 |
subclasses of AsynchronousTask. Since the AsyncScheduler class already |
5 |
has an _event_loop attribute that it inherits from PollScheduler, use |
6 |
a property for compatibility. Also update the SlotObject constructor |
7 |
to allow a subclass to override an attribute from __slots__ with a |
8 |
property, so that AsyncScheduler can use a property for the scheduler |
9 |
attribute. |
10 |
|
11 |
Bug: https://bugs.gentoo.org/653856 |
12 |
--- |
13 |
pym/_emerge/AbstractPollTask.py | 3 +-- |
14 |
pym/_emerge/AsynchronousLock.py | 2 +- |
15 |
pym/_emerge/AsynchronousTask.py | 2 +- |
16 |
pym/_emerge/CompositeTask.py | 2 +- |
17 |
pym/portage/util/SlotObject.py | 9 ++++++++- |
18 |
pym/portage/util/_async/AsyncScheduler.py | 7 +++++++ |
19 |
pym/portage/util/_async/AsyncTaskFuture.py | 2 +- |
20 |
7 files changed, 20 insertions(+), 7 deletions(-) |
21 |
|
22 |
diff --git a/pym/_emerge/AbstractPollTask.py b/pym/_emerge/AbstractPollTask.py |
23 |
index 0d38bd481..aa8fc6593 100644 |
24 |
--- a/pym/_emerge/AbstractPollTask.py |
25 |
+++ b/pym/_emerge/AbstractPollTask.py |
26 |
@@ -11,8 +11,7 @@ from _emerge.AsynchronousTask import AsynchronousTask |
27 |
|
28 |
class AbstractPollTask(AsynchronousTask): |
29 |
|
30 |
- __slots__ = ("scheduler",) + \ |
31 |
- ("_registered",) |
32 |
+ __slots__ = ("_registered",) |
33 |
|
34 |
_bufsize = 4096 |
35 |
|
36 |
diff --git a/pym/_emerge/AsynchronousLock.py b/pym/_emerge/AsynchronousLock.py |
37 |
index 78ab37ecb..0178feab2 100644 |
38 |
--- a/pym/_emerge/AsynchronousLock.py |
39 |
+++ b/pym/_emerge/AsynchronousLock.py |
40 |
@@ -37,7 +37,7 @@ class AsynchronousLock(AsynchronousTask): |
41 |
signals to the main thread). |
42 |
""" |
43 |
|
44 |
- __slots__ = ('path', 'scheduler',) + \ |
45 |
+ __slots__ = ('path',) + \ |
46 |
('_imp', '_force_async', '_force_dummy', '_force_process', \ |
47 |
'_force_thread', '_unlock_future') |
48 |
|
49 |
diff --git a/pym/_emerge/AsynchronousTask.py b/pym/_emerge/AsynchronousTask.py |
50 |
index da58261db..e29324440 100644 |
51 |
--- a/pym/_emerge/AsynchronousTask.py |
52 |
+++ b/pym/_emerge/AsynchronousTask.py |
53 |
@@ -16,7 +16,7 @@ class AsynchronousTask(SlotObject): |
54 |
the task is complete and self.returncode has been set. |
55 |
""" |
56 |
|
57 |
- __slots__ = ("background", "cancelled", "returncode") + \ |
58 |
+ __slots__ = ("background", "cancelled", "returncode", "scheduler") + \ |
59 |
("_exit_listeners", "_exit_listener_stack", "_start_listeners", |
60 |
"_waiting") |
61 |
|
62 |
diff --git a/pym/_emerge/CompositeTask.py b/pym/_emerge/CompositeTask.py |
63 |
index f3acc9696..bfd4bacbd 100644 |
64 |
--- a/pym/_emerge/CompositeTask.py |
65 |
+++ b/pym/_emerge/CompositeTask.py |
66 |
@@ -6,7 +6,7 @@ from portage import os |
67 |
|
68 |
class CompositeTask(AsynchronousTask): |
69 |
|
70 |
- __slots__ = ("scheduler",) + ("_current_task",) |
71 |
+ __slots__ = ("_current_task",) |
72 |
|
73 |
_TASK_QUEUED = -1 |
74 |
|
75 |
diff --git a/pym/portage/util/SlotObject.py b/pym/portage/util/SlotObject.py |
76 |
index 4bb682258..ba6215874 100644 |
77 |
--- a/pym/portage/util/SlotObject.py |
78 |
+++ b/pym/portage/util/SlotObject.py |
79 |
@@ -20,7 +20,14 @@ class SlotObject(object): |
80 |
raise AssertionError( |
81 |
"class '%s' duplicates '%s' value in __slots__ of base class '%s'" % |
82 |
(self.__class__.__name__, myattr, c.__name__)) |
83 |
- setattr(self, myattr, myvalue) |
84 |
+ try: |
85 |
+ setattr(self, myattr, myvalue) |
86 |
+ except AttributeError: |
87 |
+ # Allow a property to override a __slots__ value, but raise an |
88 |
+ # error if the intended value is something other than None. |
89 |
+ if not (myvalue is None and |
90 |
+ isinstance(getattr(type(self), myattr, None), property)): |
91 |
+ raise |
92 |
|
93 |
if kwargs: |
94 |
raise TypeError( |
95 |
diff --git a/pym/portage/util/_async/AsyncScheduler.py b/pym/portage/util/_async/AsyncScheduler.py |
96 |
index 9beb8a848..b89b57dab 100644 |
97 |
--- a/pym/portage/util/_async/AsyncScheduler.py |
98 |
+++ b/pym/portage/util/_async/AsyncScheduler.py |
99 |
@@ -20,6 +20,13 @@ class AsyncScheduler(AsynchronousTask, PollScheduler): |
100 |
self._remaining_tasks = True |
101 |
self._loadavg_check_id = None |
102 |
|
103 |
+ @property |
104 |
+ def scheduler(self): |
105 |
+ """ |
106 |
+ Provides compatibility with the AsynchronousTask.scheduler attribute. |
107 |
+ """ |
108 |
+ return self._event_loop |
109 |
+ |
110 |
def _poll(self): |
111 |
if not (self._is_work_scheduled() or self._keep_scheduling()): |
112 |
self.wait() |
113 |
diff --git a/pym/portage/util/_async/AsyncTaskFuture.py b/pym/portage/util/_async/AsyncTaskFuture.py |
114 |
index c2316deeb..ce881ba8d 100644 |
115 |
--- a/pym/portage/util/_async/AsyncTaskFuture.py |
116 |
+++ b/pym/portage/util/_async/AsyncTaskFuture.py |
117 |
@@ -12,7 +12,7 @@ class AsyncTaskFuture(AsynchronousTask): |
118 |
Wraps a Future in an AsynchronousTask, which is useful for |
119 |
scheduling with TaskScheduler. |
120 |
""" |
121 |
- __slots__ = ('future', 'scheduler') |
122 |
+ __slots__ = ('future',) |
123 |
def _start(self): |
124 |
self.future.add_done_callback(self._done_callback) |
125 |
|
126 |
-- |
127 |
2.13.6 |