diff --git a/storage/pzope/base.py b/storage/pzope/base.py index 113df79..bf12424 100644 --- a/storage/pzope/base.py +++ b/storage/pzope/base.py @@ -92,7 +92,7 @@ class Adapter(object): self.address = getPath(persistent) else: if self.address is None: - self.address = address # lets + self.address = address else: address = self.address persistent = traverse(getSite(), address) diff --git a/util/defer.py b/util/defer.py new file mode 100644 index 0000000..5993fa6 --- /dev/null +++ b/util/defer.py @@ -0,0 +1,36 @@ +# +# Copyright (c) 2007 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +A simple Deferred implementation. + +$Id$ +""" + +class Deferred(object): + + def __init__(self): + self._callbacks = [] + + def callback(self, *args, **kw): + for f in self._callbacks: + f(*args, **kw) + + def addCallback(self, function): + self._callbacks.append(function) + return self diff --git a/util/defer.txt b/util/defer.txt new file mode 100644 index 0000000..54bcee9 --- /dev/null +++ b/util/defer.txt @@ -0,0 +1,59 @@ +================== +Deferred Execution +================== + +$Id$ + + >>> from cybertools.util.defer import Deferred + +To show what deferreds are about we need two classes. + +The first one will be doing some time-consuming work, or may be it waits +for some event - as in this case simulated by calling the `nowItsTime()` +method. As the function or object that calls the `work()` method +- let's call it the client should not have to wait, this method immediately +returns a Deferred object. + +Later on, when the work is finished, the Deferred's `callback()` +method will be called, thus notifying the client. + + >>> class Worker(object): + ... + ... def work(self): + ... self.deferred = Deferred() + ... print 'Worker: work started' + ... return self.deferred + ... + ... def nowItsTime(self): + ... self.deferred.callback('Work completed') + +The second class, the client, gives the worker object some work; +in order to get notified when the work is finished it registers a +callback method with the deferred object coming back from the +`work()` call. + + >>> class Client(object): + ... + ... def run(self, worker): + ... deferred = worker.work() + ... deferred.addCallback(self.showResult) + ... print 'Client: The worker seems to be working now...' + ... + ... def showResult(self, result): + ... print 'Result:', result + +So we now create a worker and a client, and let the client run: + + >>> w = Worker() + >>> client = Client() + >>> client.run(w) + Worker: work started + Client: The worker seems to be working now... + +Working, working,... + +Work will be completed when its time: + + >>> w.nowItsTime() + Result: Work completed + diff --git a/util/tests.py b/util/tests.py index 71de297..70833fd 100755 --- a/util/tests.py +++ b/util/tests.py @@ -19,6 +19,7 @@ def test_suite(): #unittest.makeSuite(Test), # we don't need this #doctest.DocTestSuite(cybertools.util.property, optionflags=flags), doctest.DocFileSuite('adapter.txt', optionflags=flags), + doctest.DocFileSuite('defer.txt', optionflags=flags), doctest.DocFileSuite('property.txt', optionflags=flags), ))