agronholm / jython-swingutils (http://pypi.python.org/pypi/jython-swingutils/)
An assortment of utility classes and functions that ease the task of writing GUI applications with the Java Swing toolkit.
Clone this repository (size: 401.9 KB): HTTPS / SSH
$ hg clone http://bitbucket.org/agronholm/jython-swingutils/
| commit 64: | 3307347572cf |
| parent 63: | 16a75bb2a223 |
| branch: | default |
Background tasks now return AsyncResult objects, and runNamedTask now supports callbacks
Changed (Δ1.9 KB):
raw changeset »
swingutils/threads.py (76 lines added, 16 lines removed)
Up to file-list swingutils/threads.py:
1 |
from java.lang import Runnable |
|
2 |
from java.util.concurrent import (ThreadPoolExecutor, TimeUnit, |
|
3 |
LinkedBlockingDeque) |
|
1 |
from threading import Event |
|
2 |
import traceback |
|
3 |
||
4 |
from java.lang import Runnable, Throwable |
|
5 |
from java.util.concurrent import ThreadPoolExecutor, TimeUnit, \ |
|
6 |
LinkedBlockingDeque, Future, ExecutionException, \ |
|
7 |
CancellationException |
|
4 |
8 |
|
5 |
9 |
__all__ = ('TaskExecutor',) |
6 |
10 |
|
11 |
||
7 |
12 |
class RunnableWrapper(Runnable): |
8 |
13 |
def __init__(self, func, args, kwargs, name=None, beforeCallback=None, |
9 |
14 |
afterCallback=None): |
10 |
self.func = func |
|
11 |
self.args = args |
|
12 |
self. |
|
15 |
self._func = func |
|
16 |
self._args = args |
|
17 |
self._kwargs = kwargs |
|
13 |
18 |
self.name = name |
14 |
19 |
self.beforeCallback = beforeCallback |
15 |
20 |
self.afterCallback = afterCallback |
16 |
21 |
|
17 |
22 |
def run(self): |
18 |
self. |
|
23 |
self._func(*self._args, **self._kwargs) |
|
24 |
||
25 |
||
26 |
class AsyncResult(RunnableWrapper, Future): |
|
27 |
""" |
|
28 |
Class that stores both the function reference, and the return value or |
|
29 |
raised exception from an asynchronously invoked callable. Users should not |
|
30 |
instantiate or run these directly. |
|
31 |
||
32 |
""" |
|
33 |
def __init__(self, func, args, kwargs, name=None, beforeCallback=None, |
|
34 |
afterCallback=None): |
|
35 |
RunnableWrapper.__init__(self, func, args, kwargs, name, |
|
36 |
beforeCallback, afterCallback) |
|
37 |
self._event = Event() |
|
38 |
||
39 |
def run(self): |
|
40 |
if not self._func: |
|
41 |
return |
|
42 |
||
43 |
try: |
|
44 |
self._retval = self._func(*self._args, **self._kwargs) |
|
45 |
except BaseException, e: |
|
46 |
self._exception = e |
|
47 |
traceback.print_exc() |
|
48 |
||
49 |
self._func = None # Free any memory taken by possible closures |
|
50 |
self._event.set() |
|
51 |
||
52 |
def cancel(self, mayInterruptIfRunning): |
|
53 |
if self.isDone(): |
|
54 |
return False |
|
55 |
self._func = None |
|
56 |
return True |
|
57 |
||
58 |
def get(self, timeout=None, unit=None): |
|
59 |
if timeout and unit: |
|
60 |
timeout = unit.toMillis(timeout) / 1000.0 |
|
61 |
self._event.wait(timeout) |
|
62 |
if hasattr(self, '_exception'): |
|
63 |
if isinstance(self._exception, Throwable): |
|
64 |
raise ExecutionException(self._exception) |
|
65 |
raise ExecutionException(unicode(self._exception), None) |
|
66 |
if not hasattr(self, '_retval'): |
|
67 |
raise CancellationException |
|
68 |
return self._retval |
|
69 |
||
70 |
def isCancelled(self): |
|
71 |
return self._func is None |
|
72 |
||
73 |
def isDone(self): |
|
74 |
return hasattr(self, '_retval') or hasattr(self, '_exception') |
|
19 |
75 |
|
20 |
76 |
|
21 |
77 |
class TaskExecutor(ThreadPoolExecutor): |
| … | … | @@ -44,23 +100,27 @@ class TaskExecutor(ThreadPoolExecutor): |
44 |
100 |
|
45 |
101 |
def task(self, func): |
46 |
102 |
def wrapper(*args, **kwargs): |
47 |
runnable = RunnableWrapper(func, args, kwargs) |
|
48 |
self.execute(runnable) |
|
103 |
return self.runTask(func, *args, **kwargs) |
|
49 |
104 |
return wrapper |
50 |
105 |
|
51 |
106 |
def namedTask(self, name, beforeCallback=None, afterCallback=None): |
52 |
107 |
def outer(func): |
53 |
108 |
def inner(*args, **kwargs): |
54 |
runnable = RunnableWrapper(func, args, kwargs, name, |
|
55 |
beforeCallback, afterCallback) |
|
56 |
|
|
109 |
kwargs['beforeCallback'] = beforeCallback |
|
110 |
kwargs['afterCallback'] = afterCallback |
|
111 |
return self.runNamedTask(func, name, *args, **kwargs) |
|
57 |
112 |
return inner |
58 |
113 |
return outer |
59 |
114 |
|
60 |
115 |
def runTask(self, func, *args, **kwargs): |
61 |
runnable = RunnableWrapper(func, args, kwargs) |
|
62 |
self.execute(runnable) |
|
116 |
result = AsyncResult(func, args, kwargs) |
|
117 |
self.execute(result) |
|
118 |
return result |
|
63 |
119 |
|
64 |
120 |
def runNamedTask(self, func, name, *args, **kwargs): |
65 |
runnable = RunnableWrapper(func, args, kwargs, name) |
|
66 |
self.execute(runnable) |
|
121 |
beforeCallback = kwargs.pop('beforeCallback', None) |
|
122 |
afterCallback = kwargs.pop('afterCallback', None) |
|
123 |
result = AsyncResult(func, args, kwargs, name, beforeCallback, |
|
124 |
afterCallback) |
|
125 |
self.execute(result) |
|
126 |
return result |
