[Checkins] SVN: lovely.remotetask/trunk/src/lovely/remotetask/
Improve remote task jobs overview, implemented batching,
and sorting.
Roger Ineichen
roger at projekt01.ch
Sat Nov 18 11:26:22 EST 2006
Log message for revision 71181:
Improve remote task jobs overview, implemented batching, and sorting.
Update tests
TODO:
Make batching ans sorting working together.
Changed:
U lovely.remotetask/trunk/src/lovely/remotetask/README.txt
U lovely.remotetask/trunk/src/lovely/remotetask/browser/README.txt
U lovely.remotetask/trunk/src/lovely/remotetask/browser/configure.zcml
A lovely.remotetask/trunk/src/lovely/remotetask/browser/icons/
A lovely.remotetask/trunk/src/lovely/remotetask/browser/icons/ascending.gif
A lovely.remotetask/trunk/src/lovely/remotetask/browser/icons/decending.gif
A lovely.remotetask/trunk/src/lovely/remotetask/browser/job.py
U lovely.remotetask/trunk/src/lovely/remotetask/browser/jobs.pt
U lovely.remotetask/trunk/src/lovely/remotetask/browser/service.py
A lovely.remotetask/trunk/src/lovely/remotetask/browser/table_header.pt
U lovely.remotetask/trunk/src/lovely/remotetask/interfaces.py
U lovely.remotetask/trunk/src/lovely/remotetask/service.py
-=-
Modified: lovely.remotetask/trunk/src/lovely/remotetask/README.txt
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/README.txt 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/README.txt 2006-11-18 16:26:21 UTC (rev 71181)
@@ -129,6 +129,3 @@
>>> sorted([job.status for job in service.jobs.values()])
['queued']
-
-
-
Modified: lovely.remotetask/trunk/src/lovely/remotetask/browser/README.txt
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/browser/README.txt 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/browser/README.txt 2006-11-18 16:26:21 UTC (rev 71181)
@@ -27,7 +27,7 @@
By default there is an "echo" task:
- >>> '<li>echo</li>' in browser.contents
+ >>> '<div>echo</div>' in browser.contents
True
Below you see a table of all the jobs. Initially we have no jobs, so let's add
@@ -57,31 +57,36 @@
>>> browser.reload()
>>> print browser.contents
- <!DOCTYPE ...
+ <!DOCTYPE
...
+ <tbody>
<tr class="odd">
- <td>
+ <td class="">
<input type="checkbox" name="jobs:list" value="1">
</td>
- <td>
+ <td class="tableId">
1
</td>
- <td>
+ <td class="tableTask">
echo
</td>
- <td>
- queued
+ <td class="tableStatus">
+ <span class="status-queued">queued</span>
</td>
- <td>
+ <td class="tableDetail">
+ No input detail available
+ </td>
+ <td class="tableCreated">
...
</td>
- <td>
+ <td class="tableStart">
[not set]
</td>
- <td>
+ <td class="tableEnd">
[not set]
</td>
</tr>
+ </tbody>
...
You can cancel scheduled jobs:
@@ -97,6 +102,6 @@
You can also clean attic jobs:
- >>> browser.getControl('Clean').click()
+ >>> browser.getControl('Remove all').click()
>>> 'Cleaned 1 Jobs' in browser.contents
True
Modified: lovely.remotetask/trunk/src/lovely/remotetask/browser/configure.zcml
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/browser/configure.zcml 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/browser/configure.zcml 2006-11-18 16:26:21 UTC (rev 71181)
@@ -1,6 +1,11 @@
<configure
xmlns="http://namespaces.zope.org/browser">
+ <resourceDirectory
+ name="lovely-remotetask-icons"
+ directory="icons"
+ />
+
<addMenuItem
class="..service.TaskService"
title="Remote Task Service"
@@ -16,4 +21,11 @@
menu="zmi_views" title="Jobs"
/>
+ <page
+ for="..interfaces.IJob"
+ name="detail"
+ permission="zope.ManageContent"
+ class=".job.JobDetail"
+ />
+
</configure>
Added: lovely.remotetask/trunk/src/lovely/remotetask/browser/icons/ascending.gif
===================================================================
(Binary files differ)
Property changes on: lovely.remotetask/trunk/src/lovely/remotetask/browser/icons/ascending.gif
___________________________________________________________________
Name: svn:mime-type
+ image/gif
Added: lovely.remotetask/trunk/src/lovely/remotetask/browser/icons/decending.gif
===================================================================
(Binary files differ)
Property changes on: lovely.remotetask/trunk/src/lovely/remotetask/browser/icons/decending.gif
___________________________________________________________________
Name: svn:mime-type
+ image/gif
Added: lovely.remotetask/trunk/src/lovely/remotetask/browser/job.py
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/browser/job.py 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/browser/job.py 2006-11-18 16:26:21 UTC (rev 71181)
@@ -0,0 +1,27 @@
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Task detail view
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.publisher.browser import BrowserPage
+
+
+class JobDetail(BrowserPage):
+ """A simple task input detail view."""
+
+ def __call__(self):
+ return u'No input detail available'
Property changes on: lovely.remotetask/trunk/src/lovely/remotetask/browser/job.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: lovely.remotetask/trunk/src/lovely/remotetask/browser/jobs.pt
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/browser/jobs.pt 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/browser/jobs.pt 2006-11-18 16:26:21 UTC (rev 71181)
@@ -1,11 +1,87 @@
<html metal:use-macro="context/@@standard_macros/view"
i18n:domain="lovely.remotetask">
+<head metal:fill-slot="style_slot">
+<style type="text/css" media="all">
+
+.batch div {
+ font-size: 11px;
+ padding-top: 5px;
+ padding-right: 5px;
+ vertical-align: middle;
+ float: left;
+}
+.clear {
+ height: 1px;
+ clear: both;
+}
+table.list th {
+ font-size: 11px;
+ text-align: left;
+ font-weight: bold;
+ background-color: silver;
+}
+.tableId {
+ width: 24px;
+ font-size: 11px;
+}
+.tableTask {
+ font-size: 11px;
+}
+.tableStatus {
+ font-size: 11px;
+}
+.tableDetail {
+ font-size: 11px;
+}
+.tableCreated {
+ width: 100px;
+ font-size: 11px;
+}
+.tableStart {
+ width: 100px;
+ font-size: 11px;
+}
+.tableEnd {
+ width: 100px;
+ font-size: 11px;
+}
+.status-queued {
+ color: gray;
+}
+.status-processing {
+ color: orange;
+}
+.status-cancelled {
+ color: silver;
+}
+.status-error {
+ color: red;
+}
+.status-completed {
+ color: green;
+}
+input {
+ font-size: 10px;
+ padding: 0px;
+}
+#taskInfo {
+ font-size: 10px;
+}
+</style>
+</head>
<body>
<div metal:fill-slot="body">
<form action="" method="post"
- tal:attributes="action request/URL">
+ tal:attributes="action request/URL" tal:define="jobs view/jobs">
+ <div class="message"
+ tal:condition="view/status"
+ tal:content="view/status"
+ i18n:translate="">
+ Something happened.
+ </div>
+
<div class="row">
<div class="controls">
<input type="submit" class="button" name="STARTPROCESSING"
@@ -19,37 +95,71 @@
</div>
</div>
- <p i18n:translate="">
- Available Tasks:
- </p>
- <ul>
- <li tal:repeat="task view/getAvailableTasks"
- tal:content="task" />
- </ul>
-
- <div class="message"
- tal:condition="view/status"
- tal:content="view/status"
- i18n:translate="">
- Something happened.
- </div>
-
- <div class="row">
- <div class="controls">
- <input type="submit" class="button" name="CLEAN" value="Clean"
- i18n:attributes="value" />
+ <div class="batch" tal:condition="jobs/startNumber">
+ <div class="prev_batch" tal:define="prev jobs/prevBatch">
+ <a href=""
+ tal:condition="prev"
+ tal:attributes="href
+ string:./@@jobs.html?start=${prev/start}&size=${prev/size}"
+ i18n:translate="">
+ Previous
+ (<d tal:replace="prev/startNumber" i18n:name="start_number" /> to
+ <d tal:replace="prev/endNumber" i18n:name="end_number" />)
+ </a>
</div>
+ <div class="curr_batch" i18n:translate="">
+ <d tal:replace="jobs/startNumber" i18n:name="start_number"/> to
+ <d tal:replace="jobs/endNumber" i18n:name="end_number"/>
+ of <d tal:replace="jobs/total" i18n:name="batch_total_number"/> found
+ (<d tal:replace="view/numberOfItems" i18n:name="image_number"/> total)
+ </div>
+ <div class="next_batch" tal:define="next jobs/nextBatch">
+ <a href=""
+ tal:condition="next"
+ tal:attributes="href
+ string:./@@jobs.html?start=${next/start}&size=${next/size}"
+ i18n:translate="">
+ Next
+ (<d tal:replace="next/startNumber" i18n:name="start_number" /> to
+ <d tal:replace="next/endNumber" i18n:name="end_number" />)
+ </a>
+ </div>
+ <div class="clear"></div>
</div>
-
+ <input type="text" name="size" value=""
+ tal:attributes="value request/size|nothing" />
+ <input type="submit" class="button" name="SUBMIT_BATCH_SIZE" value="set batch size"
+ i18n:attributes="value" />
+ <div class="clear" />
<tal:block tal:replace="structure view/table" />
+
<div class="row">
<div class="controls">
- <input type="submit" class="button" name="CANCEL" value="Cancel"
+ <input type="submit" class="button" name="CLEAN_COMPLETED" value="Remove completed"
i18n:attributes="value" />
+ <input type="submit" class="button" name="CLEAN_CANCELLED" value="Remove cancelled"
+ i18n:attributes="value" />
+ <input type="submit" class="button" name="CLEAN_ERROR" value="Remove error"
+ i18n:attributes="value" />
+ <input type="submit" class="button" name="CLEAN_ALL" value="Remove all"
+ i18n:attributes="value" />
+
+ <input type="submit" class="button" name="CANCEL" value="Cancel selected"
+ i18n:attributes="value" />
</div>
</div>
+ <div id="taskInfo">
+ <p i18n:translate="">
+ Available Tasks:
+ </p>
+ <div id="availableTasks">
+ <div tal:repeat="task view/getAvailableTasks"
+ tal:content="task" />
+ </div>
+ </div>
+
</form>
</div>
Modified: lovely.remotetask/trunk/src/lovely/remotetask/browser/service.py
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/browser/service.py 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/browser/service.py 2006-11-18 16:26:21 UTC (rev 71181)
@@ -17,12 +17,125 @@
"""
__docformat__ = 'restructuredtext'
+from xml.sax.saxutils import quoteattr
+
import zope.interface
+import zope.component
+from zope.publisher.browser import BrowserPage
from zope.app.pagetemplate import ViewPageTemplateFile
-from zope.publisher.browser import BrowserPage
-from zc.table import column, table
+from zope.app.session.interfaces import ISession
+from zc.table import column, table, batching
from zc.table.interfaces import ISortableColumn
+from lovely.remotetask import interfaces
+SORTED_ON_KEY = 'lovely.remotetask.service.table.sorted-on'
+
+
+from zope.interface.common.mapping import IItemMapping
+
+class IBatch(IItemMapping):
+ """A Batch represents a sub-list of the full enumeration.
+
+ The Batch constructor takes a list (or any list-like object) of elements,
+ a starting index and the size of the batch. From this information all
+ other values are calculated.
+ """
+
+ def __len__():
+ """Return the length of the batch. This might be different than the
+ passed in batch size, since we could be at the end of the list and
+ there are not enough elements left to fill the batch completely."""
+
+ def __iter__():
+ """Creates an iterator for the contents of the batch (not the entire
+ list)."""
+
+ def __contains__(key):
+ """Checks whether the key (in our case an index) exists."""
+
+ def nextBatch(self):
+ """Return the next batch. If there is no next batch, return None."""
+
+ def prevBatch(self):
+ """Return the previous batch. If there is no previous batch, return
+ None."""
+
+ def first(self):
+ """Return the first element of the batch."""
+
+ def last(self):
+ """Return the last element of the batch."""
+
+ def total(self):
+ """Return the length of the list (not the batch)."""
+
+ def startNumber(self):
+ """Give the start **number** of the batch, which is 1 more than the
+ start index passed in."""
+
+ def endNumber(self):
+ """Give the end **number** of the batch, which is 1 more than the
+ final index."""
+
+
+class Batch(object):
+ zope.interface.implements(IBatch)
+
+ def __init__(self, list, start=0, size=20):
+ self.list = list
+ self.start = start
+ if len(list) == 0:
+ self.start = -1
+ elif start >= len(list):
+ raise IndexError('start index key out of range')
+ self.size = size
+ self.trueSize = size
+ if start+size >= len(list):
+ self.trueSize = len(list)-start
+ self.end = start+self.trueSize-1
+
+ def __len__(self):
+ return self.trueSize
+
+ def __getitem__(self, key):
+ if key >= self.trueSize:
+ raise IndexError('batch index out of range')
+ return self.list[self.start+key]
+
+ def __iter__(self):
+ return iter(self.list[self.start:self.end+1])
+
+ def __contains__(self, item):
+ return item in self.__iter__()
+
+ def nextBatch(self):
+ start = self.start + self.size
+ if start >= len(self.list):
+ return None
+ return Batch(self.list, start, self.size)
+
+ def prevBatch(self):
+ start = self.start - self.size
+ if start < 0:
+ return None
+ return Batch(self.list, start, self.size)
+
+ def first(self):
+ return self.list[self.start]
+
+ def last(self):
+ return self.list[self.end]
+
+ def total(self):
+ return len(self.list)
+
+ def startNumber(self):
+ return self.start+1
+
+ def endNumber(self):
+ return self.end+1
+
+
class CheckboxColumn(column.Column):
"""Provide a column to select applications."""
@@ -30,6 +143,30 @@
widget = (u'<input type="checkbox" name="jobs:list" value="%i">')
return widget %item.id
+
+class JobDetailColumn(column.Column):
+ """Provide a column of taks input detail view."""
+
+ def renderCell(self, item, formatter):
+ if not item.input:
+ return u'No input data given.'
+ view = zope.component.getMultiAdapter((item, formatter.request),
+ name='detail')
+ return view()
+
+
+class StatusColumn(column.GetterColumn):
+ zope.interface.implements(ISortableColumn)
+
+ def renderCell(self, item, formatter):
+ status = self.getter(item, formatter)
+ cssClass = 'status-' + status
+ return '<span class="%s">%s</span>' % (cssClass, status)
+
+ def getSortKey(self, item, formatter):
+ return self.getter(item, formatter)
+
+
class DatetimeColumn(column.GetterColumn):
zope.interface.implements(ISortableColumn)
@@ -39,6 +176,87 @@
'dateTime', 'short')
return date and dformat.format(date) or '[not set]'
+ def getSortKey(self, item, formatter):
+ return self.getter(item, formatter)
+
+class ListFormatter(table.SortingFormatterMixin,
+ table.AlternatingRowFormatter):
+ """Provides a width for each column."""
+
+ sortedHeaderTemplate = ViewPageTemplateFile('table_header.pt')
+ widths = None
+ columnCSS = None
+
+ def __init__(self, *args, **kw):
+ # Figure out sorting situation
+ kw['ignore_request'] = True
+
+ request = args[1]
+ prefix = kw.get('prefix')
+ session = ISession(request)[SORTED_ON_KEY]
+ if 'sort-on' in request:
+ name = request['sort-on']
+ if prefix and name.startswith(prefix):
+ name = name[len(prefix):]
+ oldName, oldReverse = session.get(prefix, (None, None))
+ if oldName == name:
+ session[prefix] = (name, not oldReverse)
+ else:
+ session[prefix] = (name, False)
+ # Now get the sort-on data from the session
+ if prefix in session:
+ kw['sort_on'] = [session[prefix]]
+
+ super(ListFormatter, self).__init__(*args, **kw)
+ self.columnCSS = {}
+
+ self.sortOn = (None, None)
+ if 'sort_on' in kw:
+ for name, reverse in kw['sort_on']:
+ self.columnCSS[name] = 'sorted-on'
+ self.sortOn = kw['sort_on'][0]
+
+ # sortable table support via session
+ def getHeader(self, column):
+ contents = column.renderHeader(self)
+ if (ISortableColumn.providedBy(column)):
+ contents = self._wrapInSortUI(contents, column)
+ return contents
+
+ def _wrapInSortUI(self, header, column):
+ name = column.name
+ if self.prefix:
+ name = self.prefix + name
+ isAscending = self.sortOn[0] == column.name and not self.sortOn[1]
+ isDecending = self.sortOn[0] == column.name and self.sortOn[1]
+ return self.sortedHeaderTemplate(
+ header=header, name=name,
+ isAscending=isAscending, isDecending=isDecending)
+
+ def renderHeader(self, column):
+ width = ''
+ if self.widths:
+ idx = list(self.visible_columns).index(column)
+ width = ' width="%i"' %self.widths[idx]
+ klass = self.cssClasses.get('tr', '')
+ if column.name in self.columnCSS:
+ klass += klass and ' ' or '' + self.columnCSS[column.name]
+ return ' <th%s class=%s>\n %s\n </th>\n' % (
+ width, quoteattr(klass), self.getHeader(column))
+
+
+ def renderCell(self, item, column):
+ klass = self.cssClasses.get('tr', '')
+ if column.name in self.columnCSS:
+ klass += klass and ' ' or '' + self.columnCSS[column.name]
+ return ' <td class=%s>\n %s\n </td>\n' % (
+ quoteattr(klass), self.getCell(item, column))
+
+ def renderExtra(self):
+ """Avoid use of resourcelibrary in original class."""
+ return ''
+
+
class JobsOverview(BrowserPage):
template = ViewPageTemplateFile('jobs.pt')
@@ -48,21 +266,50 @@
CheckboxColumn(u'Sel'),
column.GetterColumn(u'Id', lambda x, f: str(x.id), name='id'),
column.GetterColumn(u'Task', lambda x, f: x.task, name='task'),
- column.GetterColumn(u'Status', lambda x, f: x.status, name='status'),
- DatetimeColumn(u'Creation Date',
+ StatusColumn(u'Status', lambda x, f: x.status, name='status'),
+ JobDetailColumn(u'Detail', name='detail'),
+ DatetimeColumn(u'Creation',
lambda x, f: x.created, name='created'),
- DatetimeColumn(u'Start Date',
+ DatetimeColumn(u'Start',
lambda x, f: x.started, name='start'),
- DatetimeColumn(u'Completion Date',
- lambda x, f: x.completed, name='completed'),
+ DatetimeColumn(u'End',
+ lambda x, f: x.completed, name='end'),
)
def table(self):
- formatter = table.StandaloneFullFormatter(
- self.context, self.request, self.context.jobs.values(),
- prefix='jobs.', columns=self.columns)
+ formatter = ListFormatter(
+ self.context, self.request, self.jobs(),
+ prefix='zc.table', columns=self.columns)
+ formatter.widths=[25, 50, 150, 75, 250, 100, 100, 100]
+ formatter.cssClasses['table'] = 'list'
+ formatter.columnCSS['id'] = 'tableId'
+ formatter.columnCSS['task'] = 'tableTask'
+ formatter.columnCSS['status'] = 'tableStatus'
+ formatter.columnCSS['detail'] = 'tableDetail'
+ formatter.columnCSS['created'] = 'tableCreated'
+ formatter.columnCSS['start'] = 'tableStart'
+ formatter.columnCSS['end'] = 'tableEnd'
return formatter()
+ def jobs(self):
+ if hasattr(self, '_jobs'):
+ return self._jobs
+
+ start = int(self.request.get('start', 0))
+ sval = self.request.get('size', 10)
+ if sval:
+ size = int(sval)
+ else:
+ size = 10
+
+ jobs = list(self.context.jobs.values())
+ self._jobs = Batch(jobs, start, size)
+ return self._jobs
+
+ def numberOfItems(self):
+ jobs = list(self.context.jobs.values())
+ return len(jobs)
+
def getAvailableTasks(self):
return sorted(self.context.getAvailableTasks().keys())
@@ -78,11 +325,26 @@
self.status = 'Jobs were successfully cancelled.'
else:
self.status = u'No jobs were selected.'
- elif 'CLEAN' in self.request:
+ elif 'CLEAN_ALL' in self.request:
jobs = len(list(self.context.jobs.keys()))
self.context.clean()
cleaned = jobs - len(list(self.context.jobs.keys()))
self.status = u'Cleaned %r Jobs' % cleaned
+ elif 'CLEAN_ERROR' in self.request:
+ jobs = len(list(self.context.jobs.keys()))
+ self.context.clean(stati=[interfaces.ERROR])
+ cleaned = jobs - len(list(self.context.jobs.keys()))
+ self.status = u'Cleaned %r Jobs' % cleaned
+ elif 'CLEAN_CANCELLED' in self.request:
+ jobs = len(list(self.context.jobs.keys()))
+ self.context.clean(stati=[interfaces.CANCELLED])
+ cleaned = jobs - len(list(self.context.jobs.keys()))
+ self.status = u'Cleaned %r Jobs' % cleaned
+ elif 'CLEAN_COMPLETED' in self.request:
+ jobs = len(list(self.context.jobs.keys()))
+ self.context.clean(stati=[interfaces.COMPLETED])
+ cleaned = jobs - len(list(self.context.jobs.keys()))
+ self.status = u'Cleaned %r Jobs' % cleaned
def __call__(self):
self.update()
Added: lovely.remotetask/trunk/src/lovely/remotetask/browser/table_header.pt
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/browser/table_header.pt 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/browser/table_header.pt 2006-11-18 16:26:21 UTC (rev 71181)
@@ -0,0 +1,11 @@
+<html tal:omit-tag="">
+ <a href=""
+ tal:attributes="href string:${request/URL}?sort-on=${options/name}"
+ tal:content="options/header" />
+ <img src="" width="7" height="4" style="vertical-align: middle"
+ tal:condition="options/isAscending"
+ tal:attributes="src context/++resource++lovely-remotetask-icons/ascending.gif" />
+ <img src="" width="7" height="4" style="vertical-align: middle"
+ tal:condition="options/isDecending"
+ tal:attributes="src context/++resource++lovely-remotetask-icons/decending.gif" />
+</html>
Property changes on: lovely.remotetask/trunk/src/lovely/remotetask/browser/table_header.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: lovely.remotetask/trunk/src/lovely/remotetask/interfaces.py
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/interfaces.py 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/interfaces.py 2006-11-18 16:26:21 UTC (rev 71181)
@@ -45,9 +45,8 @@
arguments for the task.
"""
- def clean():
- """removes all jobs which are completed or canceled or have
- errors"""
+ def clean(stati=[CANCELLED, ERROR, COMPLETED]):
+ """removes all jobs which are completed or canceled or have errors."""
def cancel(jobid):
"""Cancel a particular job."""
Modified: lovely.remotetask/trunk/src/lovely/remotetask/service.py
===================================================================
--- lovely.remotetask/trunk/src/lovely/remotetask/service.py 2006-11-18 14:21:40 UTC (rev 71180)
+++ lovely.remotetask/trunk/src/lovely/remotetask/service.py 2006-11-18 16:26:21 UTC (rev 71181)
@@ -67,13 +67,17 @@
newjob.status = interfaces.QUEUED
return jobid
- def clean(self):
+ def clean(self, stati=[interfaces.CANCELLED, interfaces.ERROR,
+ interfaces.COMPLETED]):
"""See interfaces.ITaskService"""
+ allowed = [interfaces.CANCELLED, interfaces.ERROR,
+ interfaces.COMPLETED]
for key in list(self.jobs.keys()):
job = self.jobs[key]
- if job.status in [interfaces.CANCELLED,
- interfaces.ERROR,
- interfaces.COMPLETED]:
+ if job.status in stati:
+ if job.status not in allowed:
+ raise ValueError('Not allowed status for removing. %s' % \
+ job.status)
del self.jobs[key]
def cancel(self, jobid):
More information about the Checkins
mailing list