Author: dmeyer
Date: Fri Jan 18 16:58:26 2008
New Revision: 2983
Log:
Prepare yield_execution for some changes by adding a lot
of doc to that code to understand again how it works. There
are also some XXX notes for the future changes to consider.
The YieldInProgress class is gone, I hope it was not needed
and the changes I made still work.
Modified:
trunk/base/src/notifier/async.py
trunk/base/src/notifier/yieldfunc.py
Modified: trunk/base/src/notifier/async.py
==============================================================================
--- trunk/base/src/notifier/async.py (original)
+++ trunk/base/src/notifier/async.py Fri Jan 18 16:58:26 2008
@@ -177,12 +177,9 @@
The function will either return the result or raise the exception
provided to the exception function.
"""
- if not self.is_finished:
- raise RuntimeError('operation not finished')
- if self._exception:
- raise self._exception
- return self._result
-
+ # DEPRECATED!!!!!!!
+ return self.get_result()
+
def get_result(self):
"""
@@ -190,7 +187,11 @@
The function will either return the result or raise the exception
provided to the exception function.
"""
- return self()
+ if not self.is_finished:
+ raise RuntimeError('operation not finished')
+ if self._exception:
+ raise self._exception
+ return self._result
def _connect(self, callback, args = (), kwargs = {}, once = False,
Modified: trunk/base/src/notifier/yieldfunc.py
==============================================================================
--- trunk/base/src/notifier/yieldfunc.py (original)
+++ trunk/base/src/notifier/yieldfunc.py Fri Jan 18 16:58:26 2008
@@ -33,7 +33,7 @@
#
# -----------------------------------------------------------------------------
# kaa.notifier - Mainloop and callbacks
-# Copyright (C) 2006-2007 Dirk Meyer, Jason Tackaberry, et al.
+# Copyright (C) 2006-2008 Dirk Meyer, Jason Tackaberry, et al.
#
# First Version: Dirk Meyer <[EMAIL PROTECTED]>
# Maintainer: Dirk Meyer <[EMAIL PROTECTED]>
@@ -68,12 +68,21 @@
log = logging.getLogger('notifier.yield')
+# XXX YIELD CHANGES NOTES
+# XXX Not possible to remove that and replace it with None because a
+# XXX function may want to return None. Using return does not help here.
YieldContinue = object()
+# 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!
+
+
class YieldCallback(object):
"""
Callback class that can be used as a callback for a function that is
- async. Return this object using 'yield' and use the memeber function
+ async. Return this object using 'yield' and use the member function
'get' later to get the result.
"""
def __init__(self, func=None):
@@ -84,6 +93,10 @@
def __call__(self, *args, **kwargs):
+ """
+ Call the YieldCallback by the external function. This will resume
+ the calling YieldFunction.
+ """
self._args = args
self._kwargs = kwargs
self._callback()
@@ -92,6 +105,11 @@
def _connect(self, callback):
+ """
+ Connect a callback that will be called when the YieldCallback
+ function is called. This callback will resume the calling
+ YieldFunction.
+ """
self._callback = callback
@@ -124,6 +142,11 @@
results. Special yield values for break are YieldContinue or
YieldCallback or InProgress objects. In lock is True the function will
be locked against parallel calls. If locked the call will delayed.
+ A function decorated with this decorator will always return a
+ YieldFunction (which is an InProgress object) or the result.
+ XXX YIELD CHANGES NOTES
+ XXX This function will always return YieldFunction or an already
+ XXX finished InProgress object in the future.
"""
def decorator(func):
@@ -134,8 +157,11 @@
# likyle means it didn't yield anything. There was no sense
# in decorating that function with yield_execution, but on
# the other hand it's easy enough just to return the result.
+ # XXX YIELD CHANGES NOTES
+ # XXX Create InProgress object here and emit delayed
+ # XXX result After that, return that InProgress object
+ # XXX to always return an InProgress object.
return result
-
function = result.next
if lock and func._lock is not None and not func._lock.is_finished:
return YieldLock(func, function, interval)
@@ -143,15 +169,25 @@
result = function()
except StopIteration:
# no return with yield, but done, return None
+ # XXX YIELD CHANGES NOTES
+ # XXX Create InProgress object here and emit delayed
+ # XXX result After that, return that InProgress object
+ # XXX to always return an InProgress object.
return None
if not (result == YieldContinue or \
isinstance(result, (YieldCallback, InProgress))):
# everything went fine, return result
+ # XXX YIELD CHANGES NOTES
+ # XXX Create InProgress object here and emit delayed
+ # XXX result After that, return that InProgress object
+ # XXX to always return an InProgress object.
return result
# we need a step callback to finish this later
+ # result is one of YieldContinue, YieldCallback, InProgress
progress = YieldFunction(function, interval, result)
if lock:
func._lock = progress
+ # return the YieldFunction (InProgress)
return progress
func._lock = None
@@ -165,27 +201,12 @@
# Internal classes
# -----------------------------------------------------------------------------
-class YieldInProgress(object):
- """
- Internal function to handle InProgress returns from yield.
- """
- def __init__(self, in_progress):
- self._in_progress = in_progress
-
-
- def _connect(self, callback):
- self._in_progress.connect_both(callback, callback)
-
-
- def __call__(self, *args, **kwargs):
- r = self._in_progress()
- self._in_progress = None
- return r
-
-
class YieldFunction(InProgress):
"""
- InProgress class to continue function execution.
+ 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
+ (not started yet), YieldContinue (iterate now), YieldCallback (wait until
the
+ callback is called) or InProgress (wait until InProgress is done).
"""
def __init__(self, function, interval, status=None):
InProgress.__init__(self)
@@ -193,25 +214,44 @@
self._timer = Timer(self._step)
self._interval = interval
if status == None:
- # call function later
+ # No status from yield_execution, 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:
- return self._timer.start(interval)
- if isinstance(status, InProgress):
- status = YieldInProgress(status)
- status._connect(self._continue)
+ # yield_execution was stopped YieldContinue, start the step timer
+ self._timer.start(interval)
+ elif isinstance(status, InProgress):
+ # continue when InProgress is done
+ # XXX YIELD CHANGES NOTES
+ # XXX Be careful with already finished InProgress
+ # XXX Remember status for Python 2.5 to send back
+ status.connect_both(self._continue, self._continue)
+ elif isinstance(status, YieldCallback):
+ # Set _continue as callback to resume the generator when status is
done.
+ # XXX YIELD CHANGES NOTES
+ # XXX Be careful with already finished callbacks
+ # XXX Remember status for Python 2.5 to send back
+ status._connect(self._continue)
+ else:
+ raise RuntimeError('YieldFunction with bad status %s' % status)
def __call__(self, *args, **kwargs):
+ """
+ Call the YieldFunction to start it if it was not created by
+ yield_execution.
+ """
if not self._valid:
- # setup call
+ # The generator was not started yet
self._valid = True
self._yield__function = self._yield__function(*args, **kwargs).next
self._continue()
return True
- return InProgress.__call__(self, *args, **kwargs)
+ # return the result
+ # DEPRECATED!!!!!!!!!!!!!!!!!
+ return InProgress.get_result(self)
def _continue(self, *args, **kwargs):
@@ -219,6 +259,7 @@
Restart timer.
"""
if self._timer:
+ # continue calling _step
self._timer.start(self._interval)
@@ -226,24 +267,44 @@
"""
Call next step of the yield function.
"""
+ # XXX YIELD CHANGES NOTES
+ # XXX maybe send a return for Python 2.5 here
try:
result = self._yield__function()
except (SystemExit, KeyboardInterrupt):
+ self._timer.stop()
+ self._yield__function = None
sys.exit(0)
except StopIteration:
result = None
except Exception, e:
+ # YieldFunction is done with exception
e._exc_info = sys.exc_info()
+ self._timer.stop()
+ self._yield__function = None
self.throw(e)
return False
if result == YieldContinue:
+ # schedule next interation with the timer
return True
+ # We have to stop the timer because we either have a result
+ # or have to wait for an InProgress or YieldCallback
self._timer.stop()
if isinstance(result, InProgress):
- result = YieldInProgress(result)
- if isinstance(result, (YieldCallback, YieldInProgress)):
+ # continue when InProgress is done
+ # XXX YIELD CHANGES NOTES
+ # XXX Remember result for Python 2.5 to send back
+ # XXX Be careful with already finished InProgress
+ result.connect_both(self._continue, self._continue)
+ return False
+ if isinstance(result, YieldCallback):
+ # Set _continue as callback to resume the generator when result is
done.
+ # XXX YIELD CHANGES NOTES
+ # XXX Remember result for Python 2.5 to send back
+ # XXX Be careful with already finished callbacks
result._connect(self._continue)
return False
+ # YieldFunction is done
self._timer = None
self.finished(result)
self._yield__function = None
@@ -267,15 +328,16 @@
def __init__(self, original_function, function, interval):
YieldFunction.__init__(self, function, interval)
self._func = original_function
- status = YieldInProgress(self._func._lock)
- status._connect(self._try_again)
+ self._func._lock.connect_both(self._try_again, self._try_again)
def _try_again(self, result):
+ """
+ Try to start now.
+ """
if not self._func._lock.is_finished:
# still locked by a new call, wait again
- status = YieldInProgress(self._func._lock)
- status._connect(self._try_again)
+ self._func._lock.connect_both(self._try_again, self._try_again)
return
self._func._lock = self
self._continue()
-------------------------------------------------------------------------
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