Author: tack
Date: Wed Feb 13 10:48:32 2008
New Revision: 3057
Log:
Removed deprecated code for mainloop functions in kaa.notifier; removed
deprecated code for MainThreadCallback.set_async() functionality; renamed
decorators:
@kaa.execute_in_timer --> @kaa.timed
@kaa.execute_in_thread --> @kaa.threaded
@kaa.execute_in_mainloop --> @kaa.threaded(kaa.MAINTHREAD)
@kaa.yield_execution --> @kaa.coroutine
Updated asynctest.py to reflect API changes
Modified:
trunk/base/API_CHANGES.txt
trunk/base/src/__init__.py
trunk/base/src/notifier/__init__.py
trunk/base/src/notifier/decorators.py
trunk/base/src/notifier/jobserver.py
trunk/base/src/notifier/main.py
trunk/base/src/notifier/sockets.py
trunk/base/src/notifier/thread.py
trunk/base/src/notifier/yieldfunc.py
trunk/base/test/asynctest.py
Modified: trunk/base/API_CHANGES.txt
==============================================================================
--- trunk/base/API_CHANGES.txt (original)
+++ trunk/base/API_CHANGES.txt Wed Feb 13 10:48:32 2008
@@ -9,6 +9,9 @@
kaa.main can be accessed by importing kaa, you can NOT import
kaa.main directly.
+ NOTE: as of 0.4.0 (svn r3057) these functions under kaa.notifier
+ have been completely removed.
+
2. Move kaa.notifier classes and functions into the kaa namespace.
E.g. kaa.notifier.Timer is now kaa.Timer. No part of the code
should use anything from kaa.notifier.
@@ -43,3 +46,15 @@
9. MainThreadCallback.set_async() is deprecated. Calling a
MainThreadCallback will return an InProgress object, and the
correct approach now is to wait() on this InProgress.
+
+ NOTE: as of 0.4.0 (svn r3057), set_async() has been removed. Calling
+ it will raise an Exception instead of logging a warning.
+
+10. Several decorators renamed:
+ @kaa.execute_in_timer --> @kaa.timed
+ @kaa.execute_in_thread --> @kaa.threaded
+ @kaa.execute_in_mainloop --> @kaa.threaded(kaa.MAINTHREAD)
+ @kaa.yield_execution --> @kaa.coroutine
+
+ Currently the old names are still functional but a warning will be
+ logged if they are used.
Modified: trunk/base/src/__init__.py
==============================================================================
--- trunk/base/src/__init__.py (original)
+++ trunk/base/src/__init__.py Wed Feb 13 10:48:32 2008
@@ -37,21 +37,5 @@
# tempfile support. FIXME: remove TEMP when no longer used
from tmpfile import tempfile, TEMP
-
-# XXX: when support for deprecated API is removed, everything below can be
deleted
-# and replaced by 'from kaa.notifier import main'
-import kaa.notifier.main
-
-class MainWrapper:
- signals = kaa.notifier.main.signals
-
- def __call__(self):
- import logging
- log = logging.getLogger('notifier')
- log.warning('Deprecated call to kaa.main(); use kaa.main.run()
instead')
- return kaa.notifier.main.run()
-
- def __getattr__(self, attr):
- return getattr(kaa.notifier.main, attr)
-
-main = MainWrapper()
+# Expose main loop functions under kaa.main
+from kaa.notifier import main
Modified: trunk/base/src/notifier/__init__.py
==============================================================================
--- trunk/base/src/notifier/__init__.py (original)
+++ trunk/base/src/notifier/__init__.py Wed Feb 13 10:48:32 2008
@@ -36,54 +36,29 @@
from timer import Timer, WeakTimer, OneShotTimer, WeakOneShotTimer, AtTimer,
OneShotAtTimer
from sockets import SocketDispatcher, WeakSocketDispatcher, Socket, IO_READ,
IO_WRITE
from event import Event, EventHandler, WeakEventHandler
-from yieldfunc import YieldContinue, YieldCallback, YieldFunction,
yield_execution
-from jobserver import NamedThreadCallback, execute_in_thread
+from yieldfunc import YieldContinue, YieldCallback, YieldFunction, coroutine
+from jobserver import NamedThreadCallback
from async import InProgress
-from decorators import execute_in_timer, execute_in_mainloop
+from decorators import timed, threaded, MAINTHREAD
-# Here's what will be imported into the kaa namespace.
-__all__ = [
- 'Process', 'Callback', 'WeakCallback', 'Signal', 'Signals',
'MainThreadCallback',
- 'Timer', 'WeakTimer', 'OneShotTimer', 'WeakOneShotTimer', 'AtTimer',
- 'OneShotAtTimer', 'SocketDispatcher', 'WeakSocketDispatcher', 'Socket',
- 'IO_READ', 'IO_WRITE', 'Event', 'EventHandler', 'WeakEventHandler',
- 'YieldContinue', 'YieldCallback', 'YieldFunction', 'NamedThreadCallback',
- 'InProgress', 'ThreadCallback',
-
- # decorator for sub modules
- # FIXME: while we are breaking the API right now, do we want to keep
- # these names and keep them in the global kaa scope?
- 'execute_in_timer', 'execute_in_mainloop', 'yield_execution',
'execute_in_thread',
-
- # FIXME: I don't like the following functions in the global kaa namespace
- 'is_mainthread',
-
- # XXX: DEPRECATED wrappers From this module
- 'init', 'shutdown', 'step', 'running', 'signals', 'loop'
-]
-import main
-# XXX: support for deprecated API. Delete everything below when support is
removed.
-
-# get logging object
+# XXX: wrappers for deprecated (renamed) decorators. Everything below
+# this comment can be removed once support for deprecated names is
+# removed.
import logging
log = logging.getLogger('notifier')
-def wrap(old_name, new_name, *args, **kwargs):
- def f(*args, **kwargs):
- log.warning('Deprecated call to notifier.%s(); use main.%s() instead'
% (old_name, new_name))
- return getattr(main, new_name)(*args, **kwargs)
- return f
-
-class RunningWrapper:
- def __nonzero__(self):
- log.warning('Deprecated access of notifier.running; use
main.is_running() instead')
- return main.is_running()
-
-init = wrap('init', 'select_notifier')
-loop = wrap('loop', 'run')
-shutdown = wrap('shutdown', 'stop')
-step = wrap('step', 'step')
-signals = main.signals
-running = RunningWrapper()
+def execute_in_mainloop(async=False):
+ log.warning('Decorator @kaa.execute_in_mainloop deprecated; use
@kaa.threaded(kaa.MAINTHREAD)');
+ return threaded(MAINTHREAD, async=async)
+
+def wrap(func, old_name, new_name):
+ def decorator(*args, **kwargs):
+ log.warning('Decorator @kaa.%s deprecated; use @kaa.%s' % (old_name,
new_name))
+ return func(*args, **kwargs)
+ return decorator
+
+execute_in_timer=wrap(timed, 'execute_in_timer', 'timed')
+execute_in_thread=wrap(threaded, 'execute_in_thread', 'threaded')
+yield_execution=wrap(coroutine, 'yield_execution', 'coroutine')
Modified: trunk/base/src/notifier/decorators.py
==============================================================================
--- trunk/base/src/notifier/decorators.py (original)
+++ trunk/base/src/notifier/decorators.py Wed Feb 13 10:48:32 2008
@@ -29,19 +29,22 @@
#
# -----------------------------------------------------------------------------
-__all__ = [ 'execute_in_timer', 'execute_in_mainloop' ]
+__all__ = [ 'timed', 'threaded', 'MAINTHREAD' ]
# python imports
import logging
# notifier thread imports
-from thread import MainThreadCallback, is_mainthread
+from thread import MainThreadCallback, ThreadCallback, is_mainthread
+from jobserver import NamedThreadCallback
from kaa.weakref import weakref
+MAINTHREAD = 'main'
+
# get logging object
log = logging.getLogger('notifier')
-def execute_in_timer(timer, interval, type=''):
+def timed(timer, interval, type=''):
"""
Decorator to call the decorated function in a Timer. When calling the
function, a timer will be started with the given interval calling that
@@ -100,23 +103,34 @@
return decorator
-def execute_in_mainloop(async = False):
+def threaded(name=None, priority=0, async=True):
"""
- This decorator makes sure the function is called from the main loop. If
- async is True, any decorated function will return InProgress, whether the
- function is called in the main thread or another thread.
-
- If async is False and this function is called in the main thread, it
- behaves as a normal function call (as if it weren't decorated). But if the
- calling thread is not the main thread, it is blocked until the function
- finishes, and its return value is passed (or any exception is raised)
+ The decorator makes sure the function is always called in the thread
+ with the given name. The function will return an InProgress object if
+ async=True (default), otherwise it will cause invoking the decorated
+ function to block (the main loop is kept alive) and its result is
+ returned.
+
+ If name=kaa.MAINTHREAD, the decorated function will be invoked from
+ the main thread. (In this case, currently the priority kwarg is
+ ignored.)
"""
def decorator(func):
def newfunc(*args, **kwargs):
- if not async and is_mainthread():
- return func(*args, **kwargs)
- in_progress = MainThreadCallback(func)(*args, **kwargs)
+ if name == MAINTHREAD:
+ if not async and is_mainthread():
+ # Fast-path case: mainthread synchronous call from the
mainthread
+ return func(*args, **kwargs)
+ callback = MainThreadCallback(func)
+ elif name:
+ callback = NamedThreadCallback((name, priority), func)
+ else:
+ callback = ThreadCallback(func)
+ callback.wait_on_exit(False)
+
+ # callback will always return InProgress
+ in_progress = callback(*args, **kwargs)
if not async:
return in_progress.wait()
return in_progress
Modified: trunk/base/src/notifier/jobserver.py
==============================================================================
--- trunk/base/src/notifier/jobserver.py (original)
+++ trunk/base/src/notifier/jobserver.py Wed Feb 13 10:48:32 2008
@@ -29,7 +29,7 @@
#
# -----------------------------------------------------------------------------
-__all__ = [ 'execute_in_thread', 'NamedThreadCallback' ]
+__all__ = [ 'NamedThreadCallback' ]
# python imports
@@ -48,29 +48,6 @@
log = logging.getLogger('notifier.thread')
-def execute_in_thread(name=None, priority=0):
- """
- The decorator makes sure the function is always called in the thread
- with the given name. The function will return an InProgress object.
- """
- def decorator(func):
-
- def newfunc(*args, **kwargs):
- if name:
- return NamedThreadCallback((name, priority), func, *args,
**kwargs)()
- t = thread.ThreadCallback(func, *args, **kwargs)
- t.wait_on_exit(False)
- return t()
-
- try:
- newfunc.func_name = func.func_name
- except TypeError:
- pass
- return newfunc
-
- return decorator
-
-
class NamedThreadCallback(Callback):
"""
A callback to run a function in a thread. This class is used by
Modified: trunk/base/src/notifier/main.py
==============================================================================
--- trunk/base/src/notifier/main.py (original)
+++ trunk/base/src/notifier/main.py Wed Feb 13 10:48:32 2008
@@ -44,7 +44,7 @@
from popen import proclist as _proclist
from thread import is_mainthread, wakeup, set_as_mainthread
from jobserver import killall as kill_jobserver
-from decorators import execute_in_mainloop
+from decorators import threaded, MAINTHREAD
__all__ = [ 'run', 'stop', 'step', 'select_notifier', 'is_running', 'wakeup',
'set_as_mainthread', 'is_shutting_down' ]
@@ -128,7 +128,7 @@
# Ensure stop() is called from main thread.
[EMAIL PROTECTED](async = True)
[EMAIL PROTECTED](MAINTHREAD)
def stop():
"""
Shutdown notifier and kill all background processes.
Modified: trunk/base/src/notifier/sockets.py
==============================================================================
--- trunk/base/src/notifier/sockets.py (original)
+++ trunk/base/src/notifier/sockets.py Wed Feb 13 10:48:32 2008
@@ -37,7 +37,7 @@
import logging
import nf_wrapper as notifier
-from jobserver import execute_in_thread
+from decorators import threaded
from callback import Callback, Signal
from thread import MainThreadCallback, ThreadCallback, is_mainthread
@@ -188,7 +188,7 @@
return in_progress.wait()
- @execute_in_thread()
+ @threaded()
def _connect_thread(self):
if type(self._addr) == str:
# Unix socket, just connect.
Modified: trunk/base/src/notifier/thread.py
==============================================================================
--- trunk/base/src/notifier/thread.py (original)
+++ trunk/base/src/notifier/thread.py Wed Feb 13 10:48:32 2008
@@ -67,32 +67,10 @@
log = logging.getLogger('notifier')
class MainThreadCallback(Callback):
- def __init__(self, callback, *args, **kwargs):
- super(MainThreadCallback, self).__init__(callback, *args, **kwargs)
- self.lock = threading.Lock()
- self._sync_return = None
- self._sync_exception = None
- self._async = True
-
- def set_async(self, async = True):
- log.warning("set_async() is deprecated; use callback().wait()
instead.")
- self._async = async
-
- def _wakeup(self):
- # XXX: this function is called by _thread_notifier_run_queue(). It
- # is also deprecated.
- self.lock.acquire(False)
- self.lock.release()
-
def __call__(self, *args, **kwargs):
in_progress = InProgress()
if is_mainthread():
- if not self._async:
- # TODO: async flag is deprecated, caller should call wait() on
- # the inprogress instead.
- return super(MainThreadCallback, self).__call__(*args,
**kwargs)
-
try:
result = super(MainThreadCallback, self).__call__(*args,
**kwargs)
except:
@@ -102,19 +80,8 @@
return in_progress
- self.lock.acquire(False)
_thread_notifier_queue_callback(self, args, kwargs, in_progress)
- # TODO: this is deprecated, caller should use wait() on the InProgress
- # we return (when set_async(False) isn't called). This is also broken
- # because we share a single lock for multiple invocations of this
- # callback.
- if not self._async:
- # Synchronous execution: wait for main call us and collect
- # the return value.
- self.lock.acquire()
- return in_progress.get_result()
-
# Return an InProgress object which the caller can connect to
# or wait on.
return in_progress
@@ -299,13 +266,4 @@
except:
in_progress.throw(*sys.exc_info())
- # We must test if the in_progress is finished even though we called
- # finished() or throw() on it above, because if the callback returns
- # another InProgress object, in_progress is linked to it but it is
- # not finished, and so we mustn't wake the caller.
- # XXX: but this is needed only for deprecated functionality anyway
- # (set_async) and can be removed in the future.
- if in_progress.is_finished():
- callback._wakeup()
-
return True
Modified: trunk/base/src/notifier/yieldfunc.py
==============================================================================
--- trunk/base/src/notifier/yieldfunc.py (original)
+++ trunk/base/src/notifier/yieldfunc.py Wed Feb 13 10:48:32 2008
@@ -7,14 +7,14 @@
# This file contains a decorator usefull for functions that may need more
# time to execute and that needs more than one step to fullfill the task.
#
-# A caller of a function decorated with 'yield_execution' will either get the
+# A caller of a function decorated with 'coroutine' will either get the
# return value of the function call or an InProgress object in return. The
# first is similar to a normal function call, if an InProgress object is
# returned, this means that the function is still running. The object has a
# 'connect' function to connect a callback to get the results of the function
# call when it is done.
#
-# A function decorated with 'yield_execution' can't use 'return' to return the
+# A function decorated with 'coroutine' can't use 'return' to return the
# result of the function call. Instead it has to use yield to do this. Besides
# a normal return, the function can also return 'YieldContinue' in the yield
# statement. In that case, the function call continues at this point in the
@@ -27,7 +27,7 @@
# result of the async call. It is also possible to yield an InProgress object
# and call it later to get the results (or the exception).
#
-# The 'yield_execution' decorator has a parameter interval. This is the
+# The 'coroutine' decorator has a parameter interval. This is the
# interval used to schedule when the function should continue after a yield.
# The default value is 0, the first iteration is always called without a timer.
#
@@ -56,7 +56,7 @@
#
# -----------------------------------------------------------------------------
-__all__ = [ 'YieldContinue', 'YieldCallback', 'yield_execution',
+__all__ = [ 'YieldContinue', 'YieldCallback', 'coroutine',
'YieldFunction' ]
import sys
@@ -76,7 +76,7 @@
# XXX YIELD CHANGES NOTES
# XXX The deferrer stuff from Signal and InProgress won't work because
# XXX some parts connect interally to the InProgress object returned
-# by yield_execution and the deferrer only handles one connect!
+# by coroutine and the deferrer only handles one connect!
class YieldCallback(InProgress):
@@ -147,7 +147,8 @@
return async
-def yield_execution(interval = 0, synchronize = False):
+# TODO move this function to decorators.py
+def coroutine(interval = 0, synchronize = False):
"""
Functions with this decorator uses yield to break and to return the
results. Special yield values for break are YieldContinue or
@@ -171,7 +172,7 @@
if not hasattr(result, 'next'):
# Decorated function doesn't have a next attribute, which
# likyle means it didn't yield anything. There was no sense
- # in decorating that function with yield_execution, but on
+ # in decorating that function with coroutine, but on
# the other hand it's easy enough just to return the result.
return _wrap_result(result)
function = result
@@ -216,7 +217,7 @@
class YieldFunction(InProgress):
"""
InProgress class that runs a generator function. This is also the return
value
- for yield_execution if it takes some more time. status can be either None
+ for coroutine if it takes some more time. status can be either None
(not started yet), YieldContinue (iterate now) or InProgress (wait until
InProgress is done).
"""
@@ -227,13 +228,13 @@
self._interval = interval
self._async = None
if status == None:
- # No status from yield_execution, this means that the YieldFunction
+ # No status from coroutine, this means that the YieldFunction
# was created from the outside and the creator must call this
object
self._valid = False
return
self._valid = True
if status == YieldContinue:
- # yield_execution was stopped YieldContinue, start the step timer
+ # coroutine was stopped YieldContinue, start the step timer
self._timer.start(interval)
elif isinstance(status, InProgress):
# continue when InProgress is done
@@ -246,7 +247,7 @@
def __call__(self, *args, **kwargs):
"""
Call the YieldFunction to start it if it was not created by
- yield_execution.
+ coroutine.
"""
if not self._valid:
# The generator was not started yet
@@ -347,7 +348,7 @@
class YieldLock(YieldFunction):
"""
- YieldFunction for handling locked yield_execution functions.
+ YieldFunction for handling locked coroutine functions.
"""
def __init__(self, original_function, function, interval):
YieldFunction.__init__(self, function, interval)
Modified: trunk/base/test/asynctest.py
==============================================================================
--- trunk/base/test/asynctest.py (original)
+++ trunk/base/test/asynctest.py Wed Feb 13 10:48:32 2008
@@ -14,17 +14,17 @@
return x, kaa.is_mainthread()
@kaa.rpc.expose('test2')
- @kaa.execute_in_thread('yield')
+ @kaa.threaded('yield')
def test2(self, x):
return x, kaa.is_mainthread()
@kaa.rpc.expose('test3')
- @kaa.yield_execution()
+ @kaa.coroutine()
def test3(self, x):
yield kaa.YieldContinue
yield x
- @kaa.yield_execution()
+ @kaa.coroutine()
def _test4(self, x):
yield kaa.YieldContinue
yield x
@@ -49,11 +49,11 @@
def async(callback, *args, **kwargs):
kaa.OneShotTimer(callback, *args, **kwargs).start(0.1)
[EMAIL PROTECTED]('foo')
[EMAIL PROTECTED]('foo')
def thread(x):
return x + 1 - 1
[EMAIL PROTECTED]()
[EMAIL PROTECTED]()
def thread2(c, x):
# call rpc in thread using MainThreadCallback
cb = kaa.MainThreadCallback(c.rpc)
@@ -64,18 +64,18 @@
print x
return x + 1
[EMAIL PROTECTED]()
[EMAIL PROTECTED]()
def subyield():
print 3
yield kaa.YieldContinue
print 4
yield 5
[EMAIL PROTECTED]()
[EMAIL PROTECTED]()
def fast():
yield 2
[EMAIL PROTECTED]()
[EMAIL PROTECTED]()
def foo():
pid = os.fork()
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog