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

Reply via email to