[Checkins] SVN: lovely.remotetask/branches/gotcha-port-for-zope210/ keep work done even if it feels like a dead end

Godefroid Chapelle gotcha at bubblenet.be
Tue Feb 9 02:49:25 EST 2010


Log message for revision 108890:
  keep work done even if it feels like a dead end
  

Changed:
  _U  lovely.remotetask/branches/gotcha-port-for-zope210/
  U   lovely.remotetask/branches/gotcha-port-for-zope210/setup.py
  U   lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/README.txt
  U   lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/configure.zcml
  U   lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/ftesting.zcml
  U   lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/processor.py
  U   lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/service.py
  U   lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/startlater.txt
  U   lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/tests.py
  A   lovely.remotetask/branches/gotcha-port-for-zope210/zope2.cfg

-=-

Property changes on: lovely.remotetask/branches/gotcha-port-for-zope210
___________________________________________________________________
Modified: svn:ignore
   - bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg


   + var
fake-eggs
bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg



Modified: lovely.remotetask/branches/gotcha-port-for-zope210/setup.py
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/setup.py	2010-02-09 07:48:36 UTC (rev 108889)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/setup.py	2010-02-09 07:49:25 UTC (rev 108890)
@@ -28,15 +28,26 @@
     extras_require = dict(test = ['zope.app.testing',
                                   'zope.testing',
                                   'zope.app.securitypolicy',
+                                  'zope.securitypolicy',
+                                  'zope.app.authentication',
+                                  'zope.app.folder',
                                   'zope.app.zcmlfiles',
-                                  "zope.app.server",
                                   'zope.testbrowser',
-                                  ]),
+                                  ],
+                          zope2 = ['Acquisition',
+                                   #'Products.five',
+                                   #'ZPublisher',
+                          ]),
     install_requires = ['setuptools',
                         'ZODB3',
+                        #'BTrees',
+                        #'transaction',
                         'zc.queue',
                         'zc.table',
+                        'zope.app.appsetup',
+                        'zope.app.component',
                         'zope.app.container',
+                        'zope.app.form',
                         'zope.app.generations',
                         'zope.app.pagetemplate',
                         'zope.app.publication',
@@ -47,11 +58,14 @@
                         'zope.app.session',
                         'zope.app.xmlrpcintrospection',
                         'zope.component',
+                        'zope.configuration',
                         'zope.formlib',
                         'zope.interface',
+                        'zope.location',
                         'zope.publisher',
                         'zope.schema',
                         'zope.security',
+                        'zope.session',
                         'zope.traversing'
                         ],
     )

Modified: lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/README.txt
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/README.txt	2010-02-09 07:48:36 UTC (rev 108889)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/README.txt	2010-02-09 07:49:25 UTC (rev 108890)
@@ -114,8 +114,6 @@
 managed by a queue. First we request the echo task to be executed:
 
   >>> jobid = service.add(u'echo', {'foo': 'bar'})
-  >>> jobid
-  1392637175
 
 The ``add()`` function schedules the task called "echo" to be executed with
 the specified arguments. The method returns a job id with which we can inquire
@@ -155,6 +153,12 @@
   >>> config.mapping['autostart'] = (
   ...     'site1 at TestTaskService1, site2 at TestTaskService2, at RootTaskService')
   >>> from zope.app.appsetup.product import setProductConfigurations
+  >>> from App.config import getConfiguration
+  >>> def setProductConfigurations(configs):
+  ...     global_config = getConfiguration()
+  ...     global_config.product_config = {}
+  ...     for config in configs:
+  ...         global_config.product_config[config.getSectionName()] = config.mapping
   >>> setProductConfigurations([config])
   >>> from lovely.remotetask.service import getAutostartServiceNames
   >>> getAutostartServiceNames()
@@ -197,12 +201,17 @@
   lovely.remotetask INFO
     handling event IStartRemoteTasksEvent
   lovely.remotetask INFO
+    starting service remotetasks.testTaskService1
+  lovely.remotetask INFO
     service TestTaskService1 on site site1 started
   lovely.remotetask ERROR
     site site2 not found
   lovely.remotetask INFO
+    starting service remotetasks.rootTaskService
+  lovely.remotetask INFO
     service RootTaskService on site root started
 
+
 The verification for the jobs in the root-level service is done in another
 footnote [#2]_
 
@@ -216,9 +225,9 @@
   >>> service.isProcessing()
   False
 
-  >>> root_service.stopProcessing()
-  >>> root_service.isProcessing()
-  False
+  >>> print log_info
+  lovely.remotetask INFO
+    stopping service remotetasks.testTaskService1
 
   >>> import time
   >>> time.sleep(STOP_SLEEP_TIME)
@@ -290,6 +299,8 @@
   lovely.remotetask INFO
     handling event IStartRemoteTasksEvent
   lovely.remotetask INFO
+    starting service remotetasks.testTaskService1
+  lovely.remotetask INFO
     service RootTaskService on site root started
   lovely.remotetask INFO
     service TestTaskService1 on site site1 started
@@ -718,8 +729,6 @@
 
      >>> r_jobid = root_service.add(
      ...     u'echo', {'foo': 'this is for root_service'})
-     >>> r_jobid
-     1506179619
 
 
 .. [#2] We verify the root_service does get processed:
@@ -741,6 +750,7 @@
      False
 
      >>> root_service.clean()
+     >>> log_info.clear()
 
 
 Check Interfaces and stuff

Modified: lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/configure.zcml
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/configure.zcml	2010-02-09 07:48:36 UTC (rev 108889)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/configure.zcml	2010-02-09 07:49:25 UTC (rev 108890)
@@ -41,7 +41,7 @@
       name="echo" />
 
   <include zcml:condition="not-installed Products.Five" file="xmlrpc.zcml" />
-  <five:registerPackage zcml:condition="installed Products.Five" package="." initialize=".initialize" />
+  <!--five:registerPackage zcml:condition="installed Products.Five" package="." initialize=".initialize" /-->
   
   <include package=".browser" />
   <include package=".generations" />

Modified: lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/ftesting.zcml
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/ftesting.zcml	2010-02-09 07:48:36 UTC (rev 108889)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/ftesting.zcml	2010-02-09 07:49:25 UTC (rev 108890)
@@ -1,8 +1,10 @@
 <configure xmlns="http://namespaces.zope.org/zope"
            xmlns:browser="http://namespaces.zope.org/browser"
            xmlns:zcml="http://namespaces.zope.org/zcml"
+           xmlns:meta="http://namespaces.zope.org/meta"
            i18n_domain="zope">
 
+  <meta:provides feature="deprecatedlayers" />
   <include package="zope.app.securitypolicy" file="meta.zcml" />
 
   <include
@@ -42,5 +44,4 @@
    role="zope.Manager"
    principal="zope.manager"
    />
-
 </configure>

Modified: lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/processor.py
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/processor.py	2010-02-09 07:48:36 UTC (rev 108889)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/processor.py	2010-02-09 07:49:25 UTC (rev 108890)
@@ -33,9 +33,9 @@
     from ZPublisher.HTTPResponse import HTTPResponse
     import ZPublisher
     from types import StringType
-    ZOPE2=True
+    ZOPE2 = True
 except ImportError:
-    ZOPE2=False
+    ZOPE2 = False
 
 from lovely.remotetask import interfaces
 
@@ -60,6 +60,7 @@
         # Provide a very simple traversal mechanism.
         return traverse(removeSecurityProxy(ob), name, None)
 
+
 class ProcessorRequest(zope.publisher.base.BaseRequest):
     """A custome publisher request for the processor."""
 
@@ -67,7 +68,7 @@
         super(ProcessorRequest, self).__init__(None, {}, positional=args)
 
 
-class SimpleProcessor(object):
+class BaseSimpleProcessor(object):
     """Simple Job Processor
 
     This processor only processes one job at a time.
@@ -88,24 +89,8 @@
         self.waitTime = waitTime
 
     def call(self, method, args=(), errorValue=ERROR_MARKER):
-        # Create the path to the method.
-        path = self.servicePath[:] + [method]
-        path.reverse()
-        # Produce a special processor event to be sent to the publisher.
-        request = ProcessorRequest(*args)
-        request.setPublication(ProcessorPublication(self.db))
-        request.setTraversalStack(path)
-        # Publish the request, making sure that *all* exceptions are
-        # handled. The processor should *never* crash.
-        try:
-            zope.publisher.publish.publish(request, False)
-            return request.response._result
-        except Exception, error:
-            # This thread should never crash, thus a blank except
-            log.error('Processor: ``%s()`` caused an error!' %method)
-            log.exception(error)
-            return errorValue is ERROR_MARKER and error or errorValue
-            
+        raise NotImplemented
+
     def processNext(self, jobid=None):
         return self.call('processNext', args=(None, jobid))
 
@@ -117,39 +102,63 @@
             if not result:
                 time.sleep(self.waitTime)
 
-class SimpleZope2Processor(SimpleProcessor):
-    """ SimpleProcessor for Zope2 """
-    
-    zope.interface.implements(interfaces.IProcessor)
+if not ZOPE2:
 
-    def call(self, method, args=(), errorValue=ERROR_MARKER):
-        path = [method] + self.servicePath[:]
-        path.reverse()
-        response = HTTPResponse()
-        env = { 'SERVER_NAME': 'dummy',
-                'SERVER_PORT': '8080',
-                'PATH_INFO': '/' + '/'.join(path) }
-        request = HTTPRequest(None, env, response)
-        conn = self.db.open()
-        root = conn.root()
-        request['PARENTS'] = [root[ZopePublication.root_name]]
-        try:
+    class SimpleProcessor(BaseSimpleProcessor):
+
+        def call(self, method, args=(), errorValue=ERROR_MARKER):
+            # Create the path to the method.
+            path = self.servicePath[:] + [method]
+            path.reverse()
+            # Produce a special processor event to be sent to the publisher.
+            request = ProcessorRequest(*args)
+            request.setPublication(ProcessorPublication(self.db))
+            request.setTraversalStack(path)
+            # Publish the request, making sure that *all* exceptions are
+            # handled. The processor should *never* crash.
             try:
-                ZPublisher.Publish.publish(request,'Zope2', [None])
+                zope.publisher.publish.publish(request, False)
+                return request.response._result
             except Exception, error:
                 # This thread should never crash, thus a blank except
-                log.error('Processor: ``%s()`` caused an error!' %method)
+                log.error('Processor: ``%s()`` caused an error!' % method)
                 log.exception(error)
                 return errorValue is ERROR_MARKER and error or errorValue
-        finally:
-            request.close()
-            conn.close()
-            if not request.response.body:
-                time.sleep(1)
-            else:
-                return request.response.body
 
-class MultiProcessor(SimpleProcessor):
+else:
+
+    class SimpleProcessor(BaseSimpleProcessor):
+        """ SimpleProcessor for Zope2 """
+
+        def call(self, method, args=(), errorValue=ERROR_MARKER):
+            path = self.servicePath[:] + [method]
+            response = HTTPResponse()
+            env = {'SERVER_NAME': 'dummy',
+                    'SERVER_PORT': '8080',
+                    'PATH_INFO': '/' + '/'.join(path)}
+            log.info(env['PATH_INFO'])
+            request = HTTPRequest(None, env, response)
+            conn = self.db.open()
+            root = conn.root()
+            request['PARENTS'] = [root[ZopePublication.root_name]]
+            try:
+                try:
+                    ZPublisher.Publish.publish(request, 'Zope2', [None])
+                except Exception, error:
+                    # This thread should never crash, thus a blank except
+                    log.error('Processor: ``%s()`` caused an error!' % method)
+                    log.exception(error)
+                    return errorValue is ERROR_MARKER and error or errorValue
+            finally:
+                request.close()
+                conn.close()
+                if not request.response.body:
+                    time.sleep(1)
+                else:
+                    return request.response.body
+
+
+class BaseMultiProcessor(SimpleProcessor):
     """Multi-threaded Job Processor
 
     This processor can work on multiple jobs at the same time.
@@ -158,7 +167,7 @@
 
     def __init__(self, *args, **kwargs):
         self.maxThreads = kwargs.pop('maxThreads', 5)
-        super(MultiProcessor, self).__init__(*args, **kwargs)
+        super(BaseMultiProcessor, self).__init__(*args, **kwargs)
         self.threads = []
 
     def hasJobsWaiting(self):
@@ -195,33 +204,41 @@
                 # Give the thread some time to start up:
                 time.sleep(THREAD_STARTUP_WAIT)
 
-class MultiZope2Processor(MultiProcessor, SimpleZope2Processor):
-    """Multi-threaded Job Processor
 
-    This processor can work on multiple jobs at the same time.
-    
-    WARNING: This still does not work correctly in Zope2
-    """
-    zope.interface.implements(interfaces.IProcessor)
+if not ZOPE2:
 
-    def __init__(self, *args, **kwargs):
-        self.maxThreads = kwargs.pop('maxThreads', 5)
-        super(MultiZope2Processor, self).__init__(*args, **kwargs)
-        self.threads = []
+    class MultiProcessor(BaseMultiProcessor):
+        pass
 
-    def hasJobsWaiting(self):
-        value = self.call('hasJobsWaiting', errorValue=False)
-        if isinstance(value, StringType):
-            if value == 'True':
-                return True
-            else:
-                return False
-        return value
+else:
 
-    def claimNextJob(self):
-        value = self.call('claimNextJob', errorValue=None)
-        try:
-            value = int(value)
-        except ValueError:
-            pass
-        return value
+    class MultiProcessor(BaseMultiProcessor):
+        """Multi-threaded Job Processor
+
+        This processor can work on multiple jobs at the same time.
+
+        WARNING: This still does not work correctly in Zope2
+        """
+        zope.interface.implements(interfaces.IProcessor)
+
+        def __init__(self, *args, **kwargs):
+            self.maxThreads = kwargs.pop('maxThreads', 5)
+            super(MultiProcessor, self).__init__(*args, **kwargs)
+            self.threads = []
+
+        def hasJobsWaiting(self):
+            value = self.call('hasJobsWaiting', errorValue=False)
+            if isinstance(value, StringType):
+                if value == 'True':
+                    return True
+                else:
+                    return False
+            return value
+
+        def claimNextJob(self):
+            value = self.call('claimNextJob', errorValue=None)
+            try:
+                value = int(value)
+            except ValueError:
+                pass
+            return value

Modified: lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/service.py
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/service.py	2010-02-09 07:48:36 UTC (rev 108889)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/service.py	2010-02-09 07:49:25 UTC (rev 108890)
@@ -22,7 +22,6 @@
 from zope.app.publication.zopepublication import ZopePublication
 from zope.component.interfaces import ComponentLookupError
 from zope.traversing.api import getParents
-import BTrees
 import datetime
 import logging
 import persistent
@@ -31,7 +30,6 @@
 import time
 import zc.queue
 import zope.interface
-from BTrees.IOBTree import IOBTree
 import zope.location
 
 
@@ -50,7 +48,7 @@
 storage = threading.local()
 
 
-class TaskService(contained.Contained, persistent.Persistent):
+class BaseTaskService(contained.Contained, persistent.Persistent):
     """A persistent task service.
 
     The available tasks for this service are managed as utilities.
@@ -58,27 +56,19 @@
     zope.interface.implements(interfaces.ITaskService)
 
     taskInterface = interfaces.ITask
-    if not ZOPE2:
-        processorFactory = processor.SimpleProcessor
-    else:
-        processorFactory = processor.SimpleZope2Processor
+    processorFactory = processor.SimpleProcessor
 
     processorArguments = {'waitTime': 1.0}
 
-    _scheduledJobs  = None
+    _scheduledJobs = None
     _scheduledQueue = None
     _v_nextid = None
-    if not ZOPE2:
-        family = BTrees.family32
+    containerClass = None
 
     def __init__(self):
-        super(TaskService, self).__init__()
-        if not ZOPE2:
-            self.jobs = self.family.IO.BTree()
-            self._scheduledJobs = self.family.IO.BTree()
-        else:
-            self.jobs = IOBTree()
-            self._scheduledJobs = IOBTree()
+        super(BaseTaskService, self).__init__()
+        self.jobs = self.containerClass()
+        self._scheduledJobs = self.containerClass()
         self._queue = zc.queue.Queue()
         self._scheduledQueue = zc.queue.Queue()
 
@@ -152,10 +142,9 @@
                 break
         if jobid in self.jobs:
             job = self.jobs[jobid]
-            if (   job.status == interfaces.CRONJOB
+            if (job.status == interfaces.CRONJOB
                 or job.status == interfaces.DELAYED
-                or job.status == interfaces.STARTLATER
-               ):
+                or job.status == interfaces.STARTLATER):
                 job.status = interfaces.CANCELLED
 
     def getStatus(self, jobid):
@@ -170,24 +159,20 @@
         """See interfaces.ITaskService"""
         return str(self.jobs[jobid].error)
 
+    def getServicePath(self):
+        raise NotImplemented
+
     def startProcessing(self):
         """See interfaces.ITaskService"""
         if self.__parent__ is None:
             return
         if self._scheduledJobs is None:
-            if not ZOPE2:
-                self._scheduledJobs = self.family.IOB.Tree()
-            else:
-                self._scheduledJobs = IOBTree()
+            self._scheduledJobs = self.containerClass()
         if self._scheduledQueue is None:
             self._scheduledQueue = zc.queue.PersistentQueue()
         # Create the path to the service within the DB.
-        if not ZOPE2:
-            servicePath = [parent.__name__ for parent in getParents(self)
-                           if parent.__name__]
-        else:
-            servicePath = [path for path in self.getPhysicalPath() if path]
-        servicePath.reverse()
+        servicePath = self.getServicePath()
+        log.info('starting service %s' % self._threadName())
         # Start the thread running the processor inside.
         processor = self.processorFactory(
             self._p_jar.db(), servicePath, **self.processorArguments)
@@ -201,6 +186,7 @@
         if self.__name__ is None:
             return
         name = self._threadName()
+        log.info('stopping service %s' % name)
         for thread in threading.enumerate():
             if thread.getName() == name:
                 thread.running = False
@@ -221,16 +207,10 @@
         """Return name of the processing thread."""
         # This name isn't unique based on the path to self, but this doesn't
         # change the name that's been used in past versions.
-        if not ZOPE2:
-            path = [parent.__name__ for parent in getParents(self)
-                    if parent.__name__]
-            path.append('remotetasks')
-            path.reverse()
-            path.append(self.__name__)
-        else:
-            path = [path for path in self.getPhysicalPath() if path]
-            path.append('remotetasks')
-            path.reverse()
+        path = self.getServicePath()
+        path.append('remotetasks')
+        path.reverse()
+        path.append(self.__name__)
         return '.'.join(path)
 
     def hasJobsWaiting(self, now=None):
@@ -272,7 +252,7 @@
         try:
             jobtask = component.getUtility(self.taskInterface, name=job.task)
         except ComponentLookupError, error:
-            log.error('Task "%s" not found!'% job.task)
+            log.error('Task "%s" not found!' % job.task)
             log.exception(error)
             job.error = error
             if job.status != interfaces.CRONJOB:
@@ -332,9 +312,8 @@
                 self._scheduledJobs[first] = jobs[1:]
                 if len(self._scheduledJobs[first]) == 0:
                     del self._scheduledJobs[first]
-                if (    job.status != interfaces.CANCELLED
-                    and job.status != interfaces.ERROR
-                   ):
+                if (job.status != interfaces.CANCELLED
+                    and job.status != interfaces.ERROR):
                     if job.status != interfaces.DELAYED:
                         self._insertCronJob(job, now)
                     return job
@@ -370,10 +349,7 @@
         """
         while True:
             if self._v_nextid is None:
-                if not ZOPE2:
-                    self._v_nextid = random.randrange(0, self.family.maxint)
-                else:
-                    self._v_nextid = random.randrange(0, sys.maxint)
+                self._v_nextid = random.randrange(0, self.maxint)
             uid = self._v_nextid
             self._v_nextid += 1
             if uid not in self.jobs:
@@ -381,29 +357,6 @@
             self._v_nextid = None
 
 
-
-def getAutostartServiceNames():
-    """get a list of services to start"""
-
-    serviceNames = []
-    if not ZOPE2:
-        config = getProductConfiguration('lovely.remotetask')
-        if config is not None:
-            serviceNames = [name.strip()
-                            for name in config.get('autostart', '').split(',')]
-    else:
-        config = getConfiguration().product_config
-        if config is not None:
-            task_config = config.get('lovely.remotetask', None)
-            if task_config:
-                autostart = task_config.get('autostart', '')
-                serviceNames = [name.strip()
-                                for name in autostart.split(',')]
-
-    return serviceNames
-
-
-
 def bootStrapSubscriber(event):
     """Start the queue processing services based on the
        settings in zope.conf"""
@@ -435,22 +388,22 @@
         rootServices = list(rootSM.getUtilitiesFor(interfaces.ITaskService))
 
         for site in sites:
+            serviceCount = 0
             csName = getattr(site, "__name__", '')
             if csName is None:
                 csName = 'root'
             if site is not None:
                 sm = site.getSiteManager()
                 if serviceName == '*':
-                    services = list(sm.getUtilitiesFor(interfaces.ITaskService))
+                    services = list(
+                        sm.getUtilitiesFor(interfaces.ITaskService))
                     if siteName != "*" and siteName != '':
                         services = [s for s in services
                                        if s not in rootServices]
                 else:
                     services = [(serviceName,
-                                 component.queryUtility(interfaces.ITaskService,
-                                                       context=site,
-                                                       name=serviceName))]
-                serviceCount = 0
+                        component.queryUtility(interfaces.ITaskService,
+                        context=site, name=serviceName))]
                 for srvname, service in services:
                     if service is not None and not service.isProcessing():
                         service.startProcessing()
@@ -467,3 +420,55 @@
         if (siteName == "*" or serviceName == "*") and serviceCount == 0:
             msg = 'no services started by directive %s'
             log.warn(msg % name)
+
+
+def getAutostartServiceNames():
+    """get a list of services to start"""
+
+    serviceNames = []
+    config = getTaskConfig()
+    if config is not None:
+        autostart = config.get('autostart', '')
+        serviceNames = [name.strip()
+                        for name in autostart.split(',')]
+
+    return serviceNames
+
+
+if not ZOPE2:
+
+    class TaskService(BaseTaskService):
+        from BTree import family32
+        containerClass = family32.IO.BTree
+        maxint = family32.maxint
+
+        def getServicePath(self):
+            path = [parent.__name__ for parent in getParents(self)
+                           if parent.__name__]
+            path.reverse()
+            path.append(self.__name__)
+            return path
+
+    def getTaskConfig():
+        return getProductConfiguration('lovely.remotetask')
+
+else:
+    from OFS.SimpleItem import SimpleItem
+
+    class TaskService(BaseTaskService, SimpleItem):
+        from BTrees.IOBTree import IOBTree
+        containerClass = IOBTree
+        maxint = sys.maxint
+
+        def getServicePath(self):
+            path = [part for part in self.getPhysicalPath() if part]
+            return path
+
+    def getTaskConfig():
+        config = getConfiguration()
+        if not hasattr(config, 'product_config'):
+            return
+        product_config = config.product_config
+        if config is None:
+            return
+        return product_config.get('lovely.remotetask', None)

Modified: lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/startlater.txt
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/startlater.txt	2010-02-09 07:48:36 UTC (rev 108889)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/startlater.txt	2010-02-09 07:49:25 UTC (rev 108890)
@@ -60,8 +60,7 @@
 Watch for the ``startLater=True``.
 
   >>> jobid = service.add(u'echo', {'foo': 'bar'}, startLater=True)
-  >>> jobid
-  1392637175 
+  >>> initial_jobid = jobid
 
 The ``add()`` function schedules the task called "echo" to be executed with
 the specified arguments. The method returns a job id with which we can inquire
@@ -86,8 +85,8 @@
 Add a job again:
 
   >>> jobid = service.add(u'echo', {'foo': 'bar'}, startLater=True)
-  >>> jobid
-  1392637176 
+  >>> jobid == initial_jobid + 1
+  True
 
 It's still in the status ``start later``:
 

Modified: lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/tests.py
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/tests.py	2010-02-09 07:48:36 UTC (rev 108889)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/src/lovely/remotetask/tests.py	2010-02-09 07:49:25 UTC (rev 108890)
@@ -37,6 +37,7 @@
     # Make tests predictable
     random.seed(27)
 
+
 def tearDown(test):
     random.seed()
     placefulTearDown()
@@ -46,7 +47,6 @@
     service.TaskService.processorArguments = test.origArgs
 
 
-
 class TestIdGenerator(unittest.TestCase):
 
     def setUp(self):
@@ -57,21 +57,22 @@
         random.seed()
 
     def test_sequence(self):
-        self.assertEquals(1392637175, self.service._generateId())
-        self.assertEquals(1392637176, self.service._generateId())
-        self.assertEquals(1392637177, self.service._generateId())
-        self.assertEquals(1392637178, self.service._generateId())
+        initial_id = self.service._generateId()
+        self.assertEquals(initial_id + 1, self.service._generateId())
+        self.assertEquals(initial_id + 2, self.service._generateId())
+        self.assertEquals(initial_id + 3, self.service._generateId())
 
     def test_in_use_randomises(self):
-        self.assertEquals(1392637175, self.service._generateId())
-        self.service.jobs[1392637176] = object()
-        self.assertEquals(1506179619, self.service._generateId())
-        self.assertEquals(1506179620, self.service._generateId())
-        self.service.jobs[1506179621] = object()
-        self.assertEquals(2055242787, self.service._generateId())
+        initial_id = self.service._generateId()
+        self.service.jobs[initial_id] = object()
+        second_id = self.service._generateId()
+        self.assertNotEquals(second_id, initial_id)
+        self.assertEquals(second_id + 1, self.service._generateId())
+        self.service.jobs[second_id + 2] = object()
+        next_id = self.service._generateId()
+        self.assertNotEquals(next_id, second_id)
 
 
-
 def test_suite():
     return unittest.TestSuite((
         unittest.makeSuite(TestIdGenerator),
@@ -82,7 +83,6 @@
                      setUp=setUp,
                      tearDown=tearDown,
                      optionflags=doctest.NORMALIZE_WHITESPACE
-                     |doctest.ELLIPSIS
-                     |INTERPRET_FOOTNOTES
-                     ),
+                     | doctest.ELLIPSIS
+                     | INTERPRET_FOOTNOTES),
         ))

Added: lovely.remotetask/branches/gotcha-port-for-zope210/zope2.cfg
===================================================================
--- lovely.remotetask/branches/gotcha-port-for-zope210/zope2.cfg	                        (rev 0)
+++ lovely.remotetask/branches/gotcha-port-for-zope210/zope2.cfg	2010-02-09 07:49:25 UTC (rev 108890)
@@ -0,0 +1,93 @@
+[buildout]
+parts = zope2 
+        instance 
+        test 
+        zopepy
+        omelette
+        dependency
+        compattest
+        test-all
+
+develop = .
+versions = versions
+
+[zope2]
+recipe = plone.recipe.zope2install
+url = http://www.zope.org/Products/Zope/2.10.11/Zope-2.10.11-final.tgz
+fake-zope-eggs = true
+skip-fake-eggs = zope.traversing
+                 zope.proxy
+                 zope.component
+                 zope.schema
+                 zope.publisher
+                 zope.location
+                 zope.testing
+                 zope.i18nmessageid
+                 zope.app.component
+
+[versions]
+plone.recipe.zope2install = 3.2
+plone.recipe.zope2instance = 3.6
+
+zope.component = 3.5.1
+zope.location = 3.5.2
+zope.traversing = 3.5.4
+zc.table = 0.7
+zc.resourcelibrary = 1.0.1
+zope.securitypolicy = 3.4.1
+zope.app.component = 3.4.2
+zope.app.publisher = 3.5.2
+zope.publisher = 3.5.6
+zope.app.testing = 3.4.4
+zope.app.appsetup = 3.8.0
+zope.app.securitypolicy = 3.4.6
+zope.app.zcmlfiles = 3.5.5
+zope.i18nmessageid = 3.4.2
+
+[instance]
+recipe = plone.recipe.zope2instance
+zope2-location = ${zope2:location}
+user = admin:admin
+http-address = 8080
+#debug-mode = on
+#verbose-security = on
+
+eggs =
+    lovely.remotetask [zope2]
+zcml =
+    lovely.remotetask
+products =
+
+[test]
+recipe = zc.recipe.testrunner
+defaults = ['--tests-pattern', '^f?tests$']
+eggs =  ${instance:eggs}
+        lovely.remotetask [test]
+extra-paths = ${zope2:location}/lib/python
+
+[zopepy]
+# For more information on this step and configuration options see:
+# http://pypi.python.org/pypi/zc.recipe.egg
+recipe = zc.recipe.egg
+eggs = ${instance:eggs}
+interpreter = zopepy
+extra-paths = ${zope2:location}/lib/python
+scripts = zopepy
+
+[omelette]
+recipe = collective.recipe.omelette
+eggs = ${test:eggs}
+products = 
+packages = ${zope2:location}/lib/python ./
+
+[dependency]
+recipe = zc.recipe.egg:scripts
+eggs = z3c.dependencychecker
+
+[compattest]
+recipe = z3c.recipe.compattest
+include = 
+extra-paths = ${zope2:location}/lib/python
+
+[test-all]
+recipe = plone.recipe.alltests



More information about the checkins mailing list