This module implements Gmail’s undo/cancel features, using Pylons or some other web frameworks.
Here is a sample Pylons controller (called ‘th’, who knows why):
from pylons import request, response, session, tmpl_context as c
from YOURPROJECT.lib.base import BaseController, render
from routes import url_for
import webundo
class ThController(BaseController):
def index(self):
return render('th.mako')
def save(self):
# save the thing
req = request
def save():
print "Writing to file..."
open('/tmp/dump.txt', 'w').write(req.params.get('stuff'))
c.key = webundo.launch_cancelable_job(save, 3)
return render('saving.mako')
def cancel(self, id):
if webundo.cancel_job(id):
return "Thread cancelled successfully"
else:
return "Too late, thread finished already."
def publish(self):
req = request
def unpublish():
print "Oops, let's unpublish", req.params.get('stuff')
return "We're done"
c.key = webundo.launch_undoable_job(unpublish, 10)
c.published = request.params.get('stuff')
print "Published stuff", c.published
return render('publishing.mako')
def undo(self, id):
try:
ret = undo_job(id)
except webundo.ThreadLostError, e:
return "Thread was lost already"
return "Undone: %s" % ret
With th.mako being:
<p>Save something, with cancel support:</p>
<form action="${h.url_for(controller='th', action='save')}" id="" method="post">
<input type="text" name="stuff" value="somevalue" />
<input type="submit" name="" value="SEND" />
</form>
<p>Publish something, with undo support:</p>
<form action="${h.url_for(controller='th', action='publish')}" id="" method="post">
<input type="text" name="stuff" value="somevalue" />
<input type="submit" name="" value="SEND" />
</form>
This shows off a cancelable job and an undoable job. See the original blog post for more details.
Rewrite function with resolved closure references to proxy objects.
It works with objects like StackedObjectProxy from Paste, which have a _current_obj() method.
It could be extended to other frameworks or objects.
This function is called automatically by launch_cancelable_job and launch_undoable_job if the unproxy parameter is True.
Launch a new cancellable thread, and execute only after the timeout.
This means, if someone calls cancel_job, the function will never be executed.
If you’re using Pylons, it’s safer to keep unproxy to True, in case you close-in Pylons’ globals variables (request, response, app_globals, etc.). For other frameworks, it won’t hurt to leave it on, it’s a tiny overhead.
| Parameters: |
|
|---|---|
| Returns: | UUID-key for the launched job, use when calling cancel_job |
Launch a thread with an undo function. The function will be called only on request through a call to undo_job(), otherwise, it will vanish.
See notes on unproxy in doc. for launch_cancelable_job. Same applies here.
| Parameters: |
|
|---|---|
| Returns: | UUID-key of this job, use when calling undo_job. |
Cancel a job launched with launch_cancelable_job
| Parameter: | key – uuid returned by a previous call to launch_cancelable_job |
|---|---|
| Returns: | True if we could cancel the job, False if you were too late |
Launch the undo function waiting in the thread associated with key``and wait for that function's return value for ``timeout seconds.
If the other thread was timed out, the undo function will not be available to trigger anymore, and a ThreadLostError exception will be raised.
| Parameters: |
|
|---|---|
| Returns: | value returned by the function passed to launch_undoable_job. |
| Raises ThreadLostError: | |
if the timeout was elapsed, meaning you couldn’t undo anymore. |
|
Contents: