Skip to content

/ Zope / gocept svn checkins / Archive / 2005 / 2005-06 / SVN: r2993 - lms/trunk

[ << ] [ >> ]

[ SVN: r2976 - in AlphaFlow/trunk: . adapters ... ] [ SVN: r2996 - Formulon/tags/Formulon-0_3_6-release ... ]

SVN: r2993 - lms/trunk
Christian Zagrodnick <cz(at)gocept.com>
2005-06-09 15:39:45 [ FULL ]
Author: zagy
Date: Thu Jun  9 15:42:39 2005
New Revision: 2993

Added:
   lms/trunk/COPYRIGHT.txt   (contents, props changed)
   lms/trunk/LICENSE.txt   (contents, props changed)
Log:
added zpl license


Added: lms/trunk/COPYRIGHT.txt
==============================================================================
--- (empty file)
+++ lms/trunk/COPYRIGHT.txt	Thu Jun  9 15:42:39 2005
(at)(at) -0,0 +1,9 (at)(at)
+Copyright (c) 2004-2005 gocept gmbh & co. kg 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. 

Added: lms/trunk/LICENSE.txt
==============================================================================
--- (empty file)
+++ lms/trunk/LICENSE.txt	Thu Jun  9 15:42:39 2005
(at)(at) -0,0 +1,44 (at)(at)
+Zope Public License (ZPL) Version 2.1
+
+A copyright notice accompanies this license document that identifies the
+copyright holders.
+
+This license has been certified as open source. It has also been designated as
+GPL compatible by the Free Software Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions in source code must retain the accompanying copyright
+notice, this list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying copyright
+notice, this list of conditions, and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to endorse or promote
+products derived from this software without prior written permission from the
+copyright holders.
+
+4. The right to distribute this software or to use it for any purpose does not
+give you the right to use Servicemarks (sm) or Trademarks (tm) of the
copyright
+holders. Use of them is covered by separate agreement with the copyright
+holders.
+
+5. If any files are modified, you must cause the modified files to carry
+prominent notices stating that you changed the files and the date of any
+change.
+
+Disclaimer
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+

SVN: r2995 - in glome/trunk: . tests
Christian Theune <ct(at)gocept.com>
2005-06-10 09:36:12 [ FULL ]
Author: ctheune
Date: Fri Jun 10 09:38:57 2005
New Revision: 2995

Added:
   glome/trunk/numberrange.py
   glome/trunk/tests/test_numberrange.py
Modified:
   glome/trunk/interfaces.py
Log:
 - Module: numberrange.py -- Verwaltung von Nummernkreisen.


Modified: glome/trunk/interfaces.py
==============================================================================
--- glome/trunk/interfaces.py	(original)
+++ glome/trunk/interfaces.py	Fri Jun 10 09:38:57 2005
(at)(at) -145,3 +145,31 (at)(at)
                  ),
     ))
 
+
+# Number ranges
+
+class INumberRangeTool(Interface):
+    """Number range management.
+    
+    This tool can manage multiple number ranges identified by
<range_name>.
+
+    Each range has 'pools' for managing multiple sources of numbers. A pool is
+    a range of numbers given by <start> and <end> (inclusive).
+    """
+
+    def getNumber(range_name):
+        """Return a number from an active pool of <range_name>,
+        and reserve it from the active pool.
+
+        Numbers are retrieved continuously within a single pool.
+        
+        Raises KeyError if no number is left in the pool and no 
+        inactive pool is available.
+
+        If the active pool has no number left, a new pool will be activated
+        if available.
+        """
+
+    def registerNumberRange(range_name, begin, end):
+        """Add a new number range for <range_name> and mark it
'inactive'."""
+

Added: glome/trunk/numberrange.py
==============================================================================
--- (empty file)
+++ glome/trunk/numberrange.py	Fri Jun 10 09:38:57 2005
(at)(at) -0,0 +1,88 (at)(at)
+# -*- coding: latin1 -*-
+# Copyright (c) 2004-2005 gocept. All rights reserved.
+# See also LICENSE.txt
+# $Id: interfaces.py 2964 2005-05-30 12:19:19Z mac $
+
+# Python imports
+from threading import Lock
+
+# Zope imports
+from OFS.SimpleItem import SimpleItem
+from Persistence import Persistent
+from ZODB.PersistentList import PersistentList
+from ZODB.PersistentMapping import PersistentMapping
+
+# CMF imports
+from Products.CMFCore.utils import UniqueObject
+
+# Sibling imports
+from Products.glome.interfaces import INumberRangeTool
+
+class NumberPools(Persistent):
+
+    _accessLock = Lock()
+    begin = 0
+    end = 0
+    current = 0
+
+    old_pools = None
+    new_pools = None
+
+    def __init__(self, begin, end):
+        self.begin = begin
+        self.end = end
+        self.current = begin-1
+
+        self.old_pools = PersistentList()
+        self.new_pools = PersistentList()
+
+    def getNumber(self):
+        """Get a number from the current pool.
+        
+        See INumberRangeTool.getNumber.
+        """
+        self._accessLock.acquire()
+        try:
+            self.current += 1
+
+            if self.current <= self.end:  # Got a valid number
+                return self.current
+
+            # Pool was empty. Try to get a new one.
+            if not self.new_pools:
+                raise KeyError, "Out of range, no new pool available."
+
+            self.old_pools.append((self.begin, self.end))
+
+            self.begin, self.end = self.new_pools.pop(0)
+            self.current = self.begin
+        finally:
+            self._accessLock.release()
+        return self.current
+
+    def registerNumberRange(self, begin, end):
+        """Register a new number range for future use."""
+        self.new_pools.append((begin, end))
+    
+class NumberRangeTool(UniqueObject, SimpleItem):
+    """Number range management."""
+
+    __implements__ = (INumberRangeTool,)
+
+    def __init__(self):
+        #NumberRangeTool.inheritedAttribute('__init__')(self)
+        self.pools = PersistentMapping()
+
+    def getNumber(self, range_name):
+        """Return a number from an active pool of <range_name>, and
reserve it
+        from the active pool.  
+        """
+        return self.pools[range_name].getNumber()
+
+    def registerNumberRange(self, range_name, begin, end):
+        """Add a new number range for <range_name> and mark it
'inactive'."""
+        if not self.pools.has_key(range_name):
+            self.pools[range_name] = NumberPools(begin, end)
+        else:
+            self.pools[range_name].registerNumberRange(begin, end)
+        

Added: glome/trunk/tests/test_numberrange.py
==============================================================================
--- (empty file)
+++ glome/trunk/tests/test_numberrange.py	Fri Jun 10 09:38:57 2005
(at)(at) -0,0 +1,73 (at)(at)
+# -*- coding: latin1 -*-
+# Copyright (c) 2004-2005 gocept gmbh & co. kg
+# See also LICENSE.txt
+# $Id: test_tool.py 2969 2005-06-01 09:14:14Z zagy $
+
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import common
+import unittest
+
+from GlomeTestCase import GlomeTestCase
+
+from Products.CMFCore.utils import getToolByName
+
+from Products.glome.interfaces import INumberRangeTool
+from Products.glome.numberrange import NumberRangeTool
+
+class NumberRangeTest(GlomeTestCase):
+
+    interfaces_to_test = [
+        (INumberRangeTool, NumberRangeTool),
+    ]
+
+    def _setup_rangetool(self):
+        self.loginAsPortalOwner()
+        portal = self.getPortal()
+
+        tool = NumberRangeTool()
+        portal._setOb('portal_numberrange', tool)
+
+        return getToolByName(portal, 'portal_numberrange')
+
+    def test_nr(self):
+        nr = self._setup_rangetool()
+        self.failUnless(INumberRangeTool.isImplementedBy(nr))
+
+        nr.registerNumberRange('orderid', 1, 5)
+        self.assertEquals(1, nr.getNumber('orderid'))
+        self.assertEquals(2, nr.getNumber('orderid'))
+        self.assertEquals(3, nr.getNumber('orderid'))
+        self.assertEquals(4, nr.getNumber('orderid'))
+        self.assertEquals(5, nr.getNumber('orderid'))
+
+        self.assertRaises(KeyError, nr.getNumber, 'orderid')
+        self.assertRaises(KeyError, nr.getNumber, 'norange')
+
+        nr.registerNumberRange('otherrange', 10, 12)
+        nr.registerNumberRange('orderid', 10, 12)
+        nr.registerNumberRange('orderid', 15, 17)
+        self.assertEquals(10, nr.getNumber('orderid'))
+        self.assertEquals(11, nr.getNumber('orderid'))
+        self.assertEquals(12, nr.getNumber('orderid'))
+        self.assertEquals(15, nr.getNumber('orderid'))
+        self.assertEquals(16, nr.getNumber('orderid'))
+        self.assertEquals(17, nr.getNumber('orderid'))
+        self.assertRaises(KeyError, nr.getNumber, 'orderid')
+        
+        self.assertEquals(10, nr.getNumber('otherrange'))
+        self.assertEquals(11, nr.getNumber('otherrange'))
+        self.assertEquals(12, nr.getNumber('otherrange'))
+        self.assertRaises(KeyError, nr.getNumber, 'otherrange')
+        
+        
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(NumberRangeTest))
+    return suite
+
+if __name__ == '__main__':
+    framework()

SVN: r2997 - glome/trunk
Christian Theune <ct(at)gocept.com>
2005-06-10 14:20:55 [ FULL ]
Author: ctheune
Date: Fri Jun 10 14:23:43 2005
New Revision: 2997

Modified:
   glome/trunk/glometool.py
Log:
 - Fixed typo that broke security declaration


Modified: glome/trunk/glometool.py
==============================================================================
--- glome/trunk/glometool.py	(original)
+++ glome/trunk/glometool.py	Fri Jun 10 14:23:43 2005
(at)(at) -111,7 +111,7 (at)(at)
     ) + ActionProviderBase.manage_options
 
     security.declareProtected(CMFCorePermissions.ManagePortal,
-                              'manager_overview')
+                              'manage_overview')
     manage_overview = PageTemplateFile('www/explainTool', globals(),
                                        __name__='manage_overview')

SVN: r3038 - AlphaFlow/trunk/doc
Christian Theune <ct(at)gocept.com>
2005-06-21 11:43:29 [ FULL ]
Author: ctheune
Date: Tue Jun 21 11:44:59 2005
New Revision: 3038

Modified:
   AlphaFlow/trunk/doc/manual.tex
Log:
 - going on with the tutorial


Modified: AlphaFlow/trunk/doc/manual.tex
==============================================================================
--- AlphaFlow/trunk/doc/manual.tex	(original)
+++ AlphaFlow/trunk/doc/manual.tex	Tue Jun 21 11:44:59 2005
(at)(at) -30,8 +30,6 (at)(at)
 				% \version macro
 
 \makeindex			% tell \index to actually write the .idx file
-\makemodindex			% If this contains a lot of module sections.
-
 
 \begin{document}
 
(at)(at) -42,8 +40,6 (at)(at)
 \chapter*{Front Matter\label{front}}
 \fi
 
-%\input{copyright}
-
 \begin{abstract}
 
 \noindent
(at)(at) -68,25 +64,265 (at)(at)
 
 \chapter{AlphaFlow architecture}
 
-    \section{Activity-based and Document-centric}
-    \section{Specialised Activities}
+    \section{Activity-based}
+
+        \subsection{Specialised Activities}
+        \subsection{Work Items}
+        \subsubsection{Actions}
+        \subsection{Configuration}
+
+    \section{Document-centric}
 
+        \ldots the subject of a process instance is called the "`content
object"'. This can be a Plone Content Type.
     \section{Security}
 
-\chapter{Creating Process Definitions}
+\chapter{Tutorial: Music Review}
+
+    When you are implementing a workflow application on the basis of Plone
most
+    likely you are implementing some kind of review process for content. Of
+    course AlphaFlow can be used for more than that, but to introduce you into
+    the basics of using AlphaFlow, we decided to create an example application
+    on the basis of content approval.
+    
+    The application we are going to develop is a basic music review
+    application. It implements a site where some people can create a music
+    review, ask an editor to write a CD review, check the review and publish
+    it. Later on we will show you that using AlphaFlow you can extend your
+    application easily when business rules change and add an optional review
+    level for quality management to allow taking samples in the review process
+        
+    \begin{notice}
+        All code examples from this tutorial can be found in the
\file{AlphaFlow/doc/examples/MusicReview} directory.
+    \end{notice}
+    
+    \section{Prerequisites and Installation}
+
+    First you need a freshly installed Plone site. This involves having a
+    running Zope server and a current Plone (2.0.5). Additionally you need
+    Archetypes (1.3.3). 
+    
+    \begin{enumerate}
+        \item Create a new Plone site
+        \item Install Archetypes via QuickInstaller
+        \item Install AlphaFlow via QuickInstaller
+    \end{enumerate}
+
+    \begin{notice}
+        After successfully installing AlphaFlow you will find two new objects
in your Plone
+        site: the \samp{workflow\_manager} and \samp{workflow\_editor}.
+        Additionally, AlphaFlow has added the skin layer \samp{alphaflow} that
customizes Plone's templates
+        for the AlphaFlow user interface.
+    \end{notice}
+
+    \section{Creating the MusicReview object}
+
+    \begin{notice}
+        The creation of new content types for Plone is beeing automated fairly
well by Archetypes. Therefore we rely 
+        on some knowledge about Archetypes and how to set up a basic
Archetypes product. For easier readability we did kept the amount of files in
the product low, although the product should be re-organized if used in a real
application.
+    \end{notice}
+
+    The MusicReview object will be the content object that the review workflow
will be attached to. Therefore we create a basic Archetype in
\file{musicreview.py}:
+
+    % XXX update
+\begin{verbatim}
+# Plone imports
+from Products.Archetypes import public as atapi
+
+# Project imports
+from Products.AlphaFlow.workflowedobject import AlphaFlowed
+from Products.MusicReview import config, interfaces
+
+class MusicReview(AlphaFlowed, atapi.BaseContent):
+    """The MusicReview content class."""
+
+    portal_type = archetype_name = meta_type = 'MusicReview'
+
+    __implements__ = (atapi.BaseContent.__implements__ +
+        AlphaFlowed.__implements__)
+
+    schema = atapi.BaseSchema + atapi.Schema((
+        atapi.FloatField("price"),
+        atapi.IntegerField("year"),
+        atapi.StringField("genre",
+                    vocabulary=config.genreVocabulary,
+                    widget=atapi.SelectionWidget(label="Genre")),
+        atapi.TextField("review",
+                    widget=atapi.TextAreaWidget(label="Review")),
+        atapi.IntegerField("rating",
+                    vocabulary=config.ratingVocabulary,
+                    widget=atapi.SelectionWidget(label="Rating")),
+    ))
+\end{verbatim}
+
+    Let us look at the few details that are relevant to AlphaFlow in this
code:
+
+    \begin{enumerate}
+        \item The \class{MusicReview} class inherits from \class{AlphaFlowed}.
Every object that shall be associated with an AlphaFlow process has to inherit
from \class{AlphaFlowed}.
+        \item Also, \class{AlphaFlowed} must be the left-most class that any
object inherits from.
+        \item \member{\_\_implements\_\_} must merge the interfaces from all
base classes. AlphaFlow does not work if content objects do not declare the
correct interfaces.
+    \end{enumerate}
+
+    These are the three rules for making your content objects
+    AlphaFlow-aware. 
+
+    \subsection{DCWorkflow compatibility}
+
+    Our content object still is a full Plone content object. Therefore it is
+    beeing associated with the default DCWorkflow. As we do not need this,
+    and it might confuse status displays, permissions and the user interface
+    we replace the default workflow by a replacement called
+    \samp{alphaflow\_fake}. This workflow has no transitions and doesn't
+    manage any permissions. But it allows for AlphaFlow to emulate some of
+    the default Workflow behaviour of Plone.
+
+    \subsection{Installing the MusicReview type}
+     
+    The installation of your new type requires you to configure a couple of
+    switches in CMF and Plone. The example product already contains a full
+    fledged installer to use with Plone`s QuickInstaller.
+
+    After installing the type, you should be able to create new MusicReview
+    objects. Let us continue with defining our process.
+    
+    \section{The review process definition}
+
+    The review process will involve two users:
+
+    \begin{enumerate}
+        \item Peter has the role \strong{Owner} creates a \class{MusicReview}
object in the site.
+        \item Peter selects the MusicReview workflow to start and selects Paul
(who is a Member in the site) as the Editor.
+        \item After starting the Workflow, Paul has the task to write the
review for the CD as stated by Peter in the workflow configuration.
+        \item When Paul completes the task, Peter has to decide wether the
quality of Paul's review is acceptable or not. If not, Paul will have to
rewrite his review. If the review is ok, it will be published.
+    \end{enumerate}
+    
+    Notice that we refer to a new role, that already appeared in the
+    \class{MusicReview} class and is installed by the automatic installer. If
+    your site does not have the \strong{Editor} role yet, create it in the
+    Plone site now.
+
+    Let us look at how the workflow is assembled in the process definition.
+
+    \subsection{Create a new workflow definition}
+
+    Workflow definitions are written in an XML syntax called ALF. The new and
+    almost empty workflow definition for our review looks like this:
+
+\begin{verbatim}
+<?xml version="1.0" encoding="iso-8859-1"?>
+<workflow id="review"
+          title="Create a new music review"
+          description="A new music review is requested and reviewed."
+          startActivity=""
+          onlyAllowRoles="Manager Owner">
+</workflow>
+\end{verbatim}
+
+    Some comments about the anatomy of this file:
+
+    \begin{enumerate}
+        \item ALF files always have the root element \member{workflow}.
+        \item To suggest an object id for this workflow definition, the
\member{id} attribute can be set.
+        \item \member{title} and \member{description} are used in the user
interface to allow users to distinguish multiple processes.
+        \item \member{startActivity} names the activities that are used when
starting the workflow.
+        \item \member{onlyAllowRoles} restricts the usage of this workflow to
users having at least one of the given roles.
+    \end{enumerate}
+            
+    \subsection{Using the task to delegate responsibility}
+
+    The first workflow activity we look at is the task for Paul to
+    write the review. Therefore we add a \member{task} element in to the
definition:
+
+\begin{verbatim}
+<task id="write_review"
+    title="Write a music review"
+    completion_activity="review_review dc_pending"
+    content_roles="Editor">
+    <assignees kind="possible" roles="Member" />
+</task>
+\end{verbatim}
+
+    This element describes a single task activity within the process. It has
+    a single child that configures who can be an assignee.
 
-    \section{Visual Editor}
+    The \strong{id} of an activity is used within the definition to tie
+    multiple activities together. The \strong{title} is used within the user
+    interface. The \strong{completion\_activity} is special to the task and
+    shows what activities will be started after the assigned user marks the
+    task as complete. The \strong{content\_roles} attribute is a list of
+    local roles that will be assigned on the content object to the user who
+    is responsible for the task. These roles are available to the user only
+    while the task is active and assigned to him.
 
-    \section{ALF files}
+    \subsection{Using a decision to implement a review}
+
+\begin{verbatim}
+<decision id="review_review"
+    decision_notice=""
+    title="Check review for spelling and bad language."
+    accept_activity="dc_public"
+    reject_activity="write_review"
+    decision_modus="all_yes">
+    <assignees kind="actual"
expression="python:[object.owner_info()['id']]"/>
+</decision>
+\end{verbatim}
 
-\chapter{Using an AlphaFlow Process}
+    \subsection{Using a configuration to allow choosing the editor}
 
-\section{Selecting a Process}
+\begin{verbatim}
+<configuration
+    id="configure"
+    title="Select author"
+    configures="write_review"
+    continue_activity="write_review"
+    >
+      <assignees kind="actual"
expression="python:[object.owner_info()['id']]"/>
+</configuration>
+\end{verbatim}
 
-\section{Working with the Process}
+    \subsection{Emulating DCWorkflow states for better UI support}
 
+\begin{verbatim}
+    <dcworkflow id="dc_private" status="private"
+        title="Label as private"/>
+    <dcworkflow id="dc_pending" status="pending"
+        title="Label as pending"/>
+    
+    <dcworkflow id="dc_public" status="public"
+        title="Label as public"/>
+\end{verbatim}
+
+    Look at \file{AlphaFlow/doc/examples/MusicReview/workflows/review.alf} to
+    see how the final version of the process definition looks like.
+
+    \section{Using the MusicReview workflow}
+
+    \subsection{Importing the process definition}
+
+    
+    - creating a cd object
+    
+    - selecting the workflow and assigning the task
+
+    \section{Extending the workflow for sampling}
+
+    - adding a ``milestone'' for random sampling of reviews
+    within 24 hours
+    
 \chapter{Administering AlphaFlow}
 
+    \section{Managing Process Definitions}
+
+    \section{Controlling active Instances}
+
+    \subsection{Handling Exception Situations}
+
+\chapter{AlphaFlowable Objects}
+
+\chapter{Creating Custom Activities}
+
+\chapter{The ALF file format}
+
+\appendix
 \chapter{Activities}
 
 As AlphaFlow processes are assembled from a variety of specialised activities
(at)(at) -138,32 +374,43 (at)(at)
 to do. After completing the task, they select \guilabel{Complete} from the
 workflow menu.
 
-\begin{classdesc}{TaskActivity}{}
-
-\end{classdesc}
-
-\begin{classdesc}{TaskWorkItem}{}
-
-\end{classdesc}
-
 ALF Example:
 
 \begin{verbatim}
 <task id="write_document"
       title="Write document"
-      continue_activity="review">
+      completion_activity="review">
       <assignees kind="actual" expression="object/Creator" />
 </task>
 \end{verbatim}
 
+Activity configuration
+
+ completion\_activity
+ assignees
+
+Instance configuration
+
+ assignees \ldots if assignees is set to ``possible''.
+ task \ldots the specific task the user should perform
+
+Work Item actions
+
+ complete \ldots 
+
 \subsubsection{WorkItem API}
 
+\begin{classdesc}{TaskWorkItem}{BaseAssignableWorkItem}
 
 \begin{funcdesc}{complete}{comment}
     \function{Complete} is the only action \module{Task} supports. It is the
signal that the user 
     has performed the required activity. Additionally a comment can be
provided by the user.
 \end{funcdesc}
 
+\end{classdesc}
+
+
+
 \subsection{NTask}
 
 \subsection{Configuration}
(at)(at) -194,7 +441,6 (at)(at)
 
 \section{Activity and Workitem}
 
-\appendix
 \chapter{Reporting Bugs}
 
 \chapter{Getting Support}

SVN: r3039 - AlphaFlow/trunk
Michael Howitz <mh(at)gocept.com>
2005-06-21 13:08:53 [ FULL ]
Author: mac
Date: Tue Jun 21 13:10:38 2005
New Revision: 3039

Modified:
   AlphaFlow/trunk/interfaces.py
Log:
removed self attributes in method declarations


Modified: AlphaFlow/trunk/interfaces.py
==============================================================================
--- AlphaFlow/trunk/interfaces.py	(original)
+++ AlphaFlow/trunk/interfaces.py	Tue Jun 21 13:10:38 2005
(at)(at) -164,7 +164,7 (at)(at)
 
            Returns the imported process definition.
         """
-    def validateALF(self, xmlfile):
+    def validateALF(xmlfile):
         """validates the process definition against a RelaxNG schema"""
 
     def pingCronItems():
(at)(at) -236,15 +236,15 (at)(at)
     def listActivityIds():
         """Return a list of all activity ids used in this process
definition."""
 
-    def addActivity(self, id, activity_type):
+    def addActivity(id, activity_type):
         """Add a new activity to this process definition by type.
 
            Returns the new activity.
         """
-    def acquireProcess(self):
+    def acquireProcess():
         """returns the process instance from the acquisition chain"""
 
-    def renderGraph(self):
+    def renderGraph():
         """returns the rendered Graph
          pass additional keyword arguments for 
             
(at)(at) -252,11 +252,12 (at)(at)
             format
             REQUEST
         """
-    def getProcessDOM(self):
+    def getProcessDOM():
         """returns XML for self as dom node"""
     
-    def getProcessXML(self, REQUEST=None):
+    def getProcessXML(REQUEST=None):
         """returns XML as a string containing editor information"""
+
 
 class IActivity(IDOMConfigurable):
     """A workflow activity.
(at)(at) -275,7 +276,7 (at)(at)
         """Return a list of all ids of activities that can be instantiated as
            successors by instances of this activity."""
 
-    def getConfigurationSchema(self, content):
+    def getConfigurationSchema(content):
         """Return the configuration schema. XXX of what?
 
            This also allows for different activities to have programmatic
(at)(at) -287,9 +288,6 (at)(at)
     def getXML():
         """returns the AlphaFlow XML for this activity"""
 
-    def getProperties():
-        """returns the properties of the activity"""
-
     def graphGetPossibleChildren():
         """Return a list of possible successor activities as dictionaries.
 
(at)(at) -453,7 +451,7 (at)(at)
     def getGraphVizGif():
         """Return a graph definition in DOT format."""
 
-    def renderGraph(self, **kwargs):
+    def renderGraph(**kwargs):
         """returns the rendered Graph
          pass additional keyword arguments for 
             
(at)(at) -539,7 +537,7 (at)(at)
     def listRelevantUsers():
         """Return a list of relevant user ids."""
 
-    def isChildOf(self, workitem_id=None, workitem=None):
+    def isChildOf(workitem_id=None, workitem=None):
         """Return whether the given work item is a predecessor of this work
item
            in terms of generation.
 
(at)(at) -563,7 +561,7 (at)(at)
     def getActivity():
         """Return the activity this is an instance of."""
 
-    def getActivityConfiguration(self, field):
+    def getActivityConfiguration(field):
         """Return the configuration for this activity in the context of this
            process instance.
         """
(at)(at) -592,7 +590,7 (at)(at)
     def onFallout():
         """Trigger that gets called after the work item fell out."""
 
-    def beforeCreationItems(self, items, parent):
+    def beforeCreationItems(items, parent):
         """Trigger that gets called before new work items get active.
 
            Other work items can veto on the creation of those items and
(at)(at) -694,7 +692,7 (at)(at)
 class ITalesWorkItem(IAutomaticWorkItem):
     """WorkItem which uses TALES-Expression."""
 
-    def evaluate(self):
+    def evaluate():
         "Evaluate the TALES-Expression."

SVN: r3046 - lms/trunk/lib/python/lms
Christian Theune <ct(at)gocept.com>
2005-06-22 10:25:07 [ FULL ]
Author: ctheune
Date: Wed Jun 22 10:26:41 2005
New Revision: 3046

Modified:
   lms/trunk/lib/python/lms/utils.py
Log:
 - whitespace and verbose comments


Modified: lms/trunk/lib/python/lms/utils.py
==============================================================================
--- lms/trunk/lib/python/lms/utils.py	(original)
+++ lms/trunk/lib/python/lms/utils.py	Wed Jun 22 10:26:41 2005
(at)(at) -1,6 +1,6 (at)(at)
 # Copyright (c) 2005 gocept. All rights reserved.
 # See also LICENSE.txt
-# $Id: utils.py,v 1.5 2005/04/07 15:13:20 zagy Exp $
+# $Id$
 
 # python imports
 import os
(at)(at) -21,10 +21,10 (at)(at)
 STATES = [STATE_UNKNOWN, STATE_OK, STATE_TEMPORARY, STATE_UNAVAILABLE]
 
 CHECK_INTERVAL = {
-    STATE_UNKNOWN: 60*60,
-    STATE_OK: 12*60*60,
-    STATE_TEMPORARY: 5*60,
-    STATE_UNAVAILABLE: 3*60*60,
+    STATE_UNKNOWN: 60*60,       # 1 hour
+    STATE_OK: 12*60*60,         # 12 hours
+    STATE_TEMPORARY: 5*60,      # 5 minutes
+    STATE_UNAVAILABLE: 3*60*60, # 3 hours
 }
 
 def getShelf(name):
(at)(at) -32,7 +32,6 (at)(at)
     path = os.path.join(config.DATABASE_PATH, "%s.shelf" % name)
     if not os.path.exists(path):
         os.makedirs(path, 0700)
-    
     return dirdbm.Shelf(path)

SVN: r3047 - lms/trunk/lib/python/lms
Christian Theune <ct(at)gocept.com>
2005-06-22 10:26:00 [ FULL ]
Author: ctheune
Date: Wed Jun 22 10:27:41 2005
New Revision: 3047

Modified:
   lms/trunk/lib/python/lms/config.py
Log:
 - the customconfig must be available! hiding the import error 
   is too troublesome for debugging.


Modified: lms/trunk/lib/python/lms/config.py
==============================================================================
--- lms/trunk/lib/python/lms/config.py	(original)
+++ lms/trunk/lib/python/lms/config.py	Wed Jun 22 10:27:41 2005
(at)(at) -1,6 +1,6 (at)(at)
 # Copyright (c) 2005 gocept. All rights reserved.
 # See also LICENSE.txt
-# $Id: config.py,v 1.10 2005/05/03 07:15:42 zagy Exp $
+# $Id$
 
 # This file contains default values. DO NOT CHANGE. All changes are made in
 # customconfig.py where you can override all variables as you like!
(at)(at) -94,8 +94,5 (at)(at)
 #### no user configuration parts below here ####
 
 # import custom values
-try:
-    from customconfig import *
-except ImportError:
-    pass
-
+from customconfig import *
+

SVN: r3048 - lms/trunk/lib/python/lms
Christian Theune <ct(at)gocept.com>
2005-06-22 10:30:09 [ FULL ]
Author: ctheune
Date: Wed Jun 22 10:31:49 2005
New Revision: 3048

Modified:
   lms/trunk/lib/python/lms/linkdatabase.py
Log:
 - Ignoring storage errors ...


Modified: lms/trunk/lib/python/lms/linkdatabase.py
==============================================================================
--- lms/trunk/lib/python/lms/linkdatabase.py	(original)
+++ lms/trunk/lib/python/lms/linkdatabase.py	Wed Jun 22 10:31:49 2005
(at)(at) -1,6 +1,6 (at)(at)
 # Copyright (c) 2005 gocept gmbh & co. kg
 # See also LICENSE.txt
-# $Id: linkdatabase.py,v 1.10 2005/02/02 12:17:18 zagy Exp $
+# $Id$
 
 # Python imports
 import md5
(at)(at) -26,9 +26,12 (at)(at)
     def registerLink(self, url, client):
         """Register a URL as a link with an interested client."""
         id = self.getId(url)
-        if self.db.has_key(id):
+        try:
             link = self.db[id]
-        else:
+        except: # NOTICE: DirDBM sometimes looses data (EOFError).
+                # We silently ignore that and create it again.
+                # Due to refactoring this also happens when the link
+                # didn't exist yet.
             link = LinkInformation(url)
             self.db[id] = link
             # delay scheduling for 5 seconds to give clients time to be able
(at)(at) -67,7 +70,10 (at)(at)
     def getLinkIterator(self):
         keys = self.db.keys()
         for key in keys:
-            link = self.db.get(key)
+            try:
+                link = self.db.get(key)
+            except:
+                link = None
             if link is None:
                 # link must have been removed meanwhile
                 continue

SVN: r3049 - in lms/trunk: . bin var
Christian Theune <ct(at)gocept.com>
2005-06-22 10:31:23 [ FULL ]
Author: ctheune
Date: Wed Jun 22 10:32:53 2005
New Revision: 3049

Added:
   lms/trunk/bin/
   lms/trunk/bin/lms.tac
      - copied, changed from r3043, lms/trunk/lms.tac
   lms/trunk/bin/lmsCommand
      - copied, changed from r3043, lms/trunk/lmsCommand.sh
   lms/trunk/bin/lmsCommand.py
      - copied, changed from r3043, lms/trunk/lmsCommand.py
   lms/trunk/bin/registerClient
      - copied, changed from r3043, lms/trunk/registerClient.sh
   lms/trunk/bin/registerClient.py
      - copied, changed from r3043, lms/trunk/registerClient.py
   lms/trunk/bin/restart
   lms/trunk/bin/runlms
      - copied, changed from r3043, lms/trunk/runlms.sh
   lms/trunk/bin/stop
   lms/trunk/bin/test
      - copied unchanged from r3043, lms/trunk/test.sh
   lms/trunk/common.sh
   lms/trunk/var/
Removed:
   lms/trunk/lms.tac
   lms/trunk/lmsCommand.py
   lms/trunk/lmsCommand.sh
   lms/trunk/registerClient.py
   lms/trunk/registerClient.sh
   lms/trunk/runlms.sh
   lms/trunk/test.sh
Log:
 - moving the server utilities a bit, cleaning stuff


Copied: lms/trunk/bin/lms.tac (from r3043, lms/trunk/lms.tac)
==============================================================================
--- lms/trunk/lms.tac	(original)
+++ lms/trunk/bin/lms.tac	Wed Jun 22 10:32:53 2005
(at)(at) -1,6 +1,6 (at)(at)
 # Copyright (c) 2005 gocept gmbh & co. kg
 # See also LICENSE.txt
-# $Id: lms.tac,v 1.8 2005/03/30 09:11:22 zagy Exp $
+# $Id$
 
 # twisted imports
 from twisted.application import service, internet

Copied: lms/trunk/bin/lmsCommand (from r3043, lms/trunk/lmsCommand.sh)
==============================================================================
--- lms/trunk/lmsCommand.sh	(original)
+++ lms/trunk/bin/lmsCommand	Wed Jun 22 10:32:53 2005
(at)(at) -1,5 +1,4 (at)(at)
 #!/bin/sh
-export PYTHONPATH=`pwd`/lib/python
-
-python2.3 lmsCommand.py "$(at)"
+. common.sh
+python2.3 $LMS_ROOT/bin/lmsCommand.py "$(at)"
 

Copied: lms/trunk/bin/lmsCommand.py (from r3043, lms/trunk/lmsCommand.py)
==============================================================================
--- lms/trunk/lmsCommand.py	(original)
+++ lms/trunk/bin/lmsCommand.py	Wed Jun 22 10:32:53 2005
(at)(at) -1,7 +1,7 (at)(at)
 #!/usr/bin/env python
 # Copyright (c) 2005 gocept. All rights reserved.
 # See also LICENSE.txt
-# $Id: lmsCommand.py,v 1.2 2005/04/08 07:50:11 zagy Exp $
+# $Id$
 
 import sys
 from pprint import pprint
(at)(at) -15,7 +15,26 (at)(at)
             'updateClient': True,
             'setClientNotifications': False,
             }
-            
+ 
+if len(sys.argv) < 2:
+    print """Usage: lmsCommand <command> [arguments]...
+Perfom a command on the lms. 
+
+Known commands are:
+
+    registerClient      Registers a new client with the lms.
+        Arguments:  <clientid> <callback-url> <administrator
name> <administrator email>
+
+    listClients         Return a list of all registered clients.
+        Arguments:  none
+
+    updateClient        XXX
+        Arguments:  XXX
+
+    setClientNotifications XXX
+        Arguments: XXX
+    """
+    raise SystemExit, 1
 
 url = 'http://localhost:%d' % LMS_PORT
 s = ServerProxy(url)

Copied: lms/trunk/bin/registerClient (from r3043, lms/trunk/registerClient.sh)
==============================================================================
--- lms/trunk/registerClient.sh	(original)
+++ lms/trunk/bin/registerClient	Wed Jun 22 10:32:53 2005
(at)(at) -1,4 +1,4 (at)(at)
 #!/bin/sh
-export PYTHONPATH=`pwd`/lib/python
-python registerClient.py "$(at)"
+. common.sh
+python $LMS_ROOT/bin/registerClient.py "$(at)"
 

Copied: lms/trunk/bin/registerClient.py (from r3043,
lms/trunk/registerClient.py)
==============================================================================
--- lms/trunk/registerClient.py	(original)
+++ lms/trunk/bin/registerClient.py	Wed Jun 22 10:32:53 2005
(at)(at) -1,7 +1,7 (at)(at)
 #!/usr/bin/env python
 # Copyright (c) 2005 gocept. All rights reserved.
 # See also LICENSE.txt
-# $Id: registerClient.py,v 1.2 2005/04/08 07:08:00 zagy Exp $
+# $Id$
 
 import sys
 from xmlrpclib import ServerProxy

Added: lms/trunk/bin/restart
==============================================================================
--- (empty file)
+++ lms/trunk/bin/restart	Wed Jun 22 10:32:53 2005
(at)(at) -0,0 +1,3 (at)(at)
+#!/bin/sh
+. common.sh
+kill `cat $LMS_ROOT/var/lms.pid`

Copied: lms/trunk/bin/runlms (from r3043, lms/trunk/runlms.sh)
==============================================================================
--- lms/trunk/runlms.sh	(original)
+++ lms/trunk/bin/runlms	Wed Jun 22 10:32:53 2005
(at)(at) -1,3 +1,3 (at)(at)
 #!/bin/sh
-export PYTHONPATH=`pwd`/lib/python
-twistd -y lms.tac $(at)
+. common.sh
+twistd -y $LMS_ROOT/bin/lms.tac --pidfile $LMS_ROOT/var/lms.pid $(at)

Added: lms/trunk/bin/stop
==============================================================================
--- (empty file)
+++ lms/trunk/bin/stop	Wed Jun 22 10:32:53 2005
(at)(at) -0,0 +1,5 (at)(at)
+#!/bin/sh
+. common.sh
+$LMS_ROOT/bin/stop
+$LMS_ROOT/bin/start
+

Added: lms/trunk/common.sh
==============================================================================
--- (empty file)
+++ lms/trunk/common.sh	Wed Jun 22 10:32:53 2005
(at)(at) -0,0 +1,3 (at)(at)
+#!/bin/sh
+export LMS_ROOT=`pwd`
+export PYTHONPATH=`pwd`/lib/python:`pwd`

SVN: r3050 - lms/trunk/bin
Christian Theune <ct(at)gocept.com>
2005-06-22 10:32:33 [ FULL ]
Author: ctheune
Date: Wed Jun 22 10:34:10 2005
New Revision: 3050

Added:
   lms/trunk/bin/start
      - copied unchanged from r3049, lms/trunk/bin/runlms
Removed:
   lms/trunk/bin/runlms
Log:
 renamed in correspondence with other utilities

SVN: r3052 - AlphaFlow/trunk
Michael Howitz <mh(at)gocept.com>
2005-06-22 10:54:45 [ FULL ]
Author: mac
Date: Wed Jun 22 10:56:17 2005
New Revision: 3052

Modified:
   AlphaFlow/trunk/activity.py
Log:
The title should not get encoded as utf-8 because this breakes the export


Modified: AlphaFlow/trunk/activity.py
==============================================================================
--- AlphaFlow/trunk/activity.py	(original)
+++ AlphaFlow/trunk/activity.py	Wed Jun 22 10:56:17 2005
(at)(at) -44,7 +44,7 (at)(at)
         has = node.hasAttribute
         get = node.getAttribute
         if has("title"):
-            self.title = get('title')#.encode("utf-8")
+            self.title = get('title') # XXX needed? .encode("utf-8") (breaks
WF export)
         if has("sort"):
             pri = get('sort')
             try:

SVN: r3053 - AlphaFlow/trunk/tests
Michael Howitz <mh(at)gocept.com>
2005-06-22 10:55:41 [ FULL ]
Author: mac
Date: Wed Jun 22 10:57:14 2005
New Revision: 3053

Modified:
   AlphaFlow/trunk/tests/test_definition.py
   AlphaFlow/trunk/tests/test_editor.py
Log:
- repaired editor test
- added test for changing something between import and export


Modified: AlphaFlow/trunk/tests/test_definition.py
==============================================================================
--- AlphaFlow/trunk/tests/test_definition.py	(original)
+++ AlphaFlow/trunk/tests/test_definition.py	Wed Jun 22 10:57:14 2005
(at)(at) -84,7 +84,8 (at)(at)
         alf = getToolByName(portal, "workflow_manager")
         test = alf.getProcess('test')
 
-    def test_xml_export(self):
+
+    def _check_DOM_equality(self, exp_dom, got_dom, wf_name):
         def _tags_equal(tag1, tag2):
             if tag1.getAttribute('id') != tag2.getAttribute('id'):
                 return False
(at)(at) -109,8 +110,41 (at)(at)
             for pot_tag in pot_tags:
                 if _tags_equal(pot_tag, tag):
                     return pot_tag
-                
 
+
+        got_elems = got_dom.getElementsByTagName("*")
+        exp_elems = exp_dom.getElementsByTagName("*")
+        self.assertEqual(len(exp_elems),
+                         len(got_elems),
+                         "%s:\nexp: %s\ngot: %s" % (wf_name, exp_elems,
got_elems))
+        for got_tag in got_dom.getElementsByTagName("*"):
+            exp_tag = _find_in_dom(exp_dom, got_tag)
+            self.failIf(exp_tag is None)
+            self.assertEqual(exp_tag.parentNode.nodeName,
+                             got_tag.parentNode.nodeName)
+            if exp_tag.parentNode.ownerDocument is not None: # no Document
+                self.assertEqual(exp_tag.parentNode.getAttribute('id'),
+                                 got_tag.parentNode.getAttribute('id'))
+            else:
+                self.failUnless(got_tag.parentNode.ownerDocument is None)
+            self.assertEqual(len(exp_tag.attributes),
+                             len(got_tag.attributes),
+                             "%s:\nexp: %s\ngot: %s" % (wf_name,
+                                                       
exp_tag.attributes.items(),
+                                                       
got_tag.attributes.items())
+                             )
+                                 
+            got_attribs_keys = got_tag.attributes.keys()
+            exp_attribs_keys = exp_tag.attributes.keys()
+            got_attribs_keys.sort()
+            exp_attribs_keys.sort()
+            self.assertEqual(exp_attribs_keys, got_attribs_keys)
+            for key in got_attribs_keys:
+                self.assertEqual(exp_tag.getAttribute(key),
+                                 got_tag.getAttribute(key))
+
+
+    def test_xml_export(self):
         portal = self.getPortal()
         alf = getToolByName(portal, "workflow_manager")
         wf_dir = os.path.join(os.path.dirname(__file__), "workflows")
(at)(at) -119,7 +153,7 (at)(at)
             if not wf_name.endswith('.alf'):
                 continue
             wf_file = file(os.path.join(wf_dir, wf_name))
-            print wf_name
+#             print wf_name
             try:
                 alf.importWorkflowFromXML("test", wf_file)
             except ConfigurationError:
(at)(at) -129,38 +163,39 (at)(at)
             test = alf.getProcess('test')
             got_dom = minidom.parseString(test.exportAsXML().encode('utf-8'))
             exp_dom = minidom.parseString(wf_file.read())
-            got_elems = got_dom.getElementsByTagName("*")
-            exp_elems = exp_dom.getElementsByTagName("*")
-            self.assertEqual(len(exp_elems),
-                             len(got_elems),
-                             "%s:\nexp: %s\ngot: %s" % (wf_name, exp_elems,
got_elems))
-            for got_tag in got_dom.getElementsByTagName("*"):
-                exp_tag = _find_in_dom(exp_dom, got_tag)
-                self.failIf(exp_tag is None)
-                self.assertEqual(exp_tag.parentNode.nodeName,
-                                 got_tag.parentNode.nodeName)
-                if exp_tag.parentNode.ownerDocument is not None: # no Document
-                    self.assertEqual(exp_tag.parentNode.getAttribute('id'),
-                                     got_tag.parentNode.getAttribute('id'))
-                else:
-                    self.failUnless(got_tag.parentNode.ownerDocument is None)
-                self.assertEqual(len(exp_tag.attributes),
-                                 len(got_tag.attributes),
-                                 "%s:\nexp: %s\ngot: %s" % (wf_name,
-                                                          
exp_tag.attributes.items(),
-                                                          
got_tag.attributes.items())
-                                 )
-                                 
-                got_attribs_keys = got_tag.attributes.keys()
-                exp_attribs_keys = exp_tag.attributes.keys()
-                got_attribs_keys.sort()
-                exp_attribs_keys.sort()
-                self.assertEqual(exp_attribs_keys, got_attribs_keys)
-                for key in got_attribs_keys:
-                    self.assertEqual(exp_tag.getAttribute(key),
-                                     got_tag.getAttribute(key))
+            self._check_DOM_equality(exp_dom, got_dom, wf_name)
             alf.deleteProcess('test')
-        
+
+
+    def test_export_after_changes(self):
+        portal = self.getPortal()
+        self.loginAsPortalOwner()
+        alf = getToolByName(portal, "workflow_manager")
+        wf_file = file(os.path.join(os.path.join(os.path.dirname(__file__),
+                                                 "workflows"),
+                                    'email.alf'))
+        alf.importWorkflowFromXML("test", wf_file)
+        wf_file.seek(0)
+        test = alf.getProcess('test')
+        # do some changes in process
+        task1 = test['task1']
+        task1.completion_activity = ('make_public', )
+        public = test.addActivity('make_public', 'dcworkflow')
+        public.title = 'Public'
+        public.status = 'public'
+        # do same changes in dom
+        exp_dom = minidom.parseString(wf_file.read())
+        task1 = exp_dom.getElementsByTagName("task")[0]
+        task1.setAttribute('completion_activity', 'make_public')
+        workflow = exp_dom.getElementsByTagName("workflow")[0]
+        public = workflow.appendChild(exp_dom.createElement('dcworkflow'))
+        public.setAttribute('id', 'make_public')
+        public.setAttribute('title', 'Public')
+        public.setAttribute('status', 'public')
+        # export dom and check equality
+        got_dom = minidom.parseString(test.exportAsXML().encode('utf-8'))
+        self._check_DOM_equality(exp_dom, got_dom, "email.alf")
+                
         
     def test_definition(self):
         # Creates a simple workflow

Modified: AlphaFlow/trunk/tests/test_editor.py
==============================================================================
--- AlphaFlow/trunk/tests/test_editor.py	(original)
+++ AlphaFlow/trunk/tests/test_editor.py	Wed Jun 22 10:57:14 2005
(at)(at) -71,13 +71,11 (at)(at)
                              'accept_activity':"public",
                              'reject_activity':"private",
                              'decision_modus':'all_yes',
-                             'title': '',
                              }
         xml = editor.processes.test.deci_n.getXML()
         xml = minidom.parseString(xml)
 
         el = xml.getElementsByTagName('decision')[0]
-        
         self.assertEqual(len(el.attributes), len(decision_expected), 
                          "The 'decision' element has not the amount of"\
                          " expected attributes.")

SVN: r3057 - lms/trunk/bin
Christian Theune <ct(at)gocept.com>
2005-06-22 12:24:43 [ FULL ]
Author: ctheune
Date: Wed Jun 22 12:26:17 2005
New Revision: 3057

Modified:
   lms/trunk/bin/restart
   lms/trunk/bin/start
   lms/trunk/bin/stop
Log:
 - tuning of start/stop scripts


Modified: lms/trunk/bin/restart
==============================================================================
--- lms/trunk/bin/restart	(original)
+++ lms/trunk/bin/restart	Wed Jun 22 12:26:17 2005
(at)(at) -1,3 +1,4 (at)(at)
 #!/bin/sh
 . common.sh
-kill `cat $LMS_ROOT/var/lms.pid`
+$LMS_ROOT/bin/stop
+$LMS_ROOT/bin/start

Modified: lms/trunk/bin/start
==============================================================================
--- lms/trunk/bin/start	(original)
+++ lms/trunk/bin/start	Wed Jun 22 12:26:17 2005
(at)(at) -1,3 +1,4 (at)(at)
 #!/bin/sh
 . common.sh
+echo "Starting lms ..."
 twistd -y $LMS_ROOT/bin/lms.tac --pidfile $LMS_ROOT/var/lms.pid $(at)

Modified: lms/trunk/bin/stop
==============================================================================
--- lms/trunk/bin/stop	(original)
+++ lms/trunk/bin/stop	Wed Jun 22 12:26:17 2005
(at)(at) -1,5 +1,6 (at)(at)
 #!/bin/sh
 . common.sh
-$LMS_ROOT/bin/stop
-$LMS_ROOT/bin/start
-
+PID=`cat $LMS_ROOT/var/lms.pid`
+kill $PID
+echo "Waiting for lms to stop ..."
+sleep 10

SVN: r3059 - lms/trunk/lib/python/lms
Christian Theune <ct(at)gocept.com>
2005-06-22 12:29:33 [ FULL ]
Author: ctheune
Date: Wed Jun 22 12:31:12 2005
New Revision: 3059

Modified:
   lms/trunk/lib/python/lms/checker.py
Log:
   - Fixed finding of next class


Modified: lms/trunk/lib/python/lms/checker.py
==============================================================================
--- lms/trunk/lib/python/lms/checker.py	(original)
+++ lms/trunk/lib/python/lms/checker.py	Wed Jun 22 12:31:12 2005
(at)(at) -1,6 +1,6 (at)(at)
 # Copyright (c) 2005 gocept gmbh & co. kg
 # See also LICENSE.txt
-# $Id: checker.py,v 1.9 2005/02/04 16:42:48 zagy Exp $
+# $Id$
 
 # Python imports
 import urllib
(at)(at) -87,7 +87,7 (at)(at)
         queue = self.queue
         now = time.time()
         if queue:
-            candidate = min(self.queue.values())
+            candidate = min(queue.values())
             if now - candidate.lastChecked < 1:
                 # the *oldest* class was checked less than a second ago
                 log.debug('No class is checkable right now ...')
(at)(at) -112,9 +112,9 (at)(at)
         self.classification = classification
         self.lastChecked = 0  # never / long ago
    
-    def __cmp__(self, other):
-        return cmp(self.lastChecked, other.lastChecked)
-
+    def __lt__(self, other):
+        return self.lastChecked < other.lastChecked
+   
     def append(self, item):
         if item not in self:
             list.append(self, item)

SVN: r3060 - lms/trunk/doc
Christian Theune <ct(at)gocept.com>
2005-06-22 12:35:03 [ FULL ]
Author: ctheune
Date: Wed Jun 22 12:36:44 2005
New Revision: 3060

Modified:
   lms/trunk/doc/HISTORY.txt
Log:
 - Documented last changes


Modified: lms/trunk/doc/HISTORY.txt
==============================================================================
--- lms/trunk/doc/HISTORY.txt	(original)
+++ lms/trunk/doc/HISTORY.txt	Wed Jun 22 12:36:44 2005
(at)(at) -2,6 +2,16 (at)(at)
 Link Monitoring Server History
 ==============================
 
+0.3
+===
+
+* Fix: determining the order of links to check was broken, so 
+    a) a link class would be checked multiple times
+    b) some classes would never be checked
+* Fix: The DirDBM module of twisted sometimes looses data causing
+    some links never to be scheduled because the iterator wouldn't get
+    past them.
+    
 0.2
 ===

SVN: r3064 - lms/trunk/lib/python/lms
Christian Theune <ct(at)gocept.com>
2005-06-22 13:22:49 [ FULL ]
Author: ctheune
Date: Wed Jun 22 13:24:24 2005
New Revision: 3064

Modified:
   lms/trunk/lib/python/lms/scheduler.py
   lms/trunk/lib/python/lms/server.py
Log:
 - optimized reactor timings


Modified: lms/trunk/lib/python/lms/scheduler.py
==============================================================================
--- lms/trunk/lib/python/lms/scheduler.py	(original)
+++ lms/trunk/lib/python/lms/scheduler.py	Wed Jun 22 13:24:24 2005
(at)(at) -23,8 +23,8 (at)(at)
     def start(self):
         log.debug("Scheduling links for checking ...")
         links = linkdb.getLinkIterator()
-        reactor.callLater(0, self._check, links)
-        reactor.callLater(60, self.start)
+        reactor.callLater(0.01, self._check, links)
+        reactor.callLater(60*15, self.start) # Reschedule only every 15
minutes
 
     def _check(self, links):
         try:
(at)(at) -33,7 +33,7 (at)(at)
             return
         if self._needs_checking(link):
             self.checker.scheduleLink(link)
-        reactor.callLater(0.00000001, self._check, links)
+        reactor.callLater(0.01, self._check, links)
 
     def _needs_checking(self, link):
         now = time.time()

Modified: lms/trunk/lib/python/lms/server.py
==============================================================================
--- lms/trunk/lib/python/lms/server.py	(original)
+++ lms/trunk/lib/python/lms/server.py	Wed Jun 22 13:24:24 2005
(at)(at) -21,7 +21,7 (at)(at)
     def xmlrpc_unregisterLink(self, url, client_id):
         log.debug("Removing link %r" % url)
         client = self._get_client(client_id)
-        reactor.callLater(0, linkdatabase.links.unregisterLink, url, client)
+        reactor.callLater(0.01, linkdatabase.links.unregisterLink, url,
client)
         # we basicly don't care if the links was actually registered
         return "OK"

SVN: r3074 - lms/trunk/doc
Christian Theune <ct(at)gocept.com>
2005-06-22 15:55:32 [ FULL ]
Author: ctheune
Date: Wed Jun 22 15:57:09 2005
New Revision: 3074

Modified:
   lms/trunk/doc/INSTALL.txt
Log:
 fixed installation instructions


Modified: lms/trunk/doc/INSTALL.txt
==============================================================================
--- lms/trunk/doc/INSTALL.txt	(original)
+++ lms/trunk/doc/INSTALL.txt	Wed Jun 22 15:57:09 2005
(at)(at) -8,10 +8,9 (at)(at)
 Copyright (c) 2003-2005 gocept gmbh & co. kg
 See also LICENSE.txt
 
-:Valid for:  lms 0.2
+:Valid for:  lms 0.3
 :Author:     Christian Zagrodnick <cz(at)gocept.com>
-:CVS:        $Id: INSTALL.txt,v 1.1 2005/04/19 06:22:16 zagy Exp $
-
+:CVS:        $Id$
 
 
 Prerequisites
(at)(at) -47,7 +46,7 (at)(at)
 
 3. Edit ``lib/python/lms/customconfig.py`` (see Configuration_)
 
-4. **After** configuring lms, start it ./runlms.sh
+4. **After** configuring lms, start it with 'bin/start'
 
 5. Next, you can register clients, (see Administration_)
 
(at)(at) -70,10 +69,10 (at)(at)
 ==============
 
 The main command to issue administrative commands to the lms is
-``lmsCommand.sh``.
+``bin/lmsCommand``.
 
 Registring Clients::
 
- ./lmsCommand.sh registerClient client_id callback_url "Full Name"
email(at)address
+ bin/lmsCommand.sh registerClient client_id callback_url "Full Name"
email(at)address

SVN: r3090 - lms/trunk/doc
Christian Zagrodnick <cz(at)gocept.com>
2005-06-24 13:05:54 [ FULL ]
Author: zagy
Date: Fri Jun 24 13:01:08 2005
New Revision: 3090

Modified:
   lms/trunk/doc/HISTORY.txt
Log:
updated history


Modified: lms/trunk/doc/HISTORY.txt
==============================================================================
--- lms/trunk/doc/HISTORY.txt	(original)
+++ lms/trunk/doc/HISTORY.txt	Fri Jun 24 13:01:08 2005
(at)(at) -3,13 +3,12 (at)(at)
 ==============================
 
 LMS 0.3 (2005-05-22)
-
-    * Optimized reactor timings a bit.
-
-    * Fix: determining the order of links to check was broken, so 
+    
+    - Various performance optimisations (reactor timings, etc.)
+    - Fix: determining the order of links to check was broken, so 
         a) a link class would be checked multiple times
         b) some classes would never be checked
-    * Fix: The DirDBM module of twisted sometimes looses data causing
+    - Fix: The DirDBM module of twisted sometimes looses data causing
         some links never to be scheduled because the iterator wouldn't get
         past them.

SVN: r3102 - AlphaFlow/trunk
Michael Howitz <mh(at)gocept.com>
2005-06-28 08:53:52 [ FULL ]
Author: mac
Date: Tue Jun 28 08:48:51 2005
New Revision: 3102

Modified:
   AlphaFlow/trunk/activity.py
   AlphaFlow/trunk/importexport.py
   AlphaFlow/trunk/interfaces.py
Log:
- moved configureFromXML from BaseActivity to DOMImporter
- added Interface for this method


Modified: AlphaFlow/trunk/activity.py
==============================================================================
--- AlphaFlow/trunk/activity.py	(original)
+++ AlphaFlow/trunk/activity.py	Tue Jun 28 08:48:51 2005
(at)(at) -85,13 +85,6 (at)(at)
             schema = schema.copy()
         return schema
 
-    security.declareProtected(config.EDIT_WORKFLOW, "configureFromXML")
-    def configureFromXML(self, REQUEST):
-        """saves the properties to the activity"""
-        xmlstr = REQUEST.xml
-        node = minidom.parseString(xmlstr)
-        self.configureFromDOMNode(node.documentElement)
-
     def getPossibleChildren(self):
         """Return a list of all ids of activities that can be instantiated as
         successors by instances of this activity."""
(at)(at) -101,6 +94,10 (at)(at)
         "Return a list of possible successor activities as dictionaries."
         return [] # to be overwritten by subclasses
 
+
+    #########
+    # private
+
     security.declarePrivate('_attr_export_activities_list')
     def _attr_export_activities_list(self, attr, node):
         "Export for editor specific attributes."

Modified: AlphaFlow/trunk/importexport.py
==============================================================================
--- AlphaFlow/trunk/importexport.py	(original)
+++ AlphaFlow/trunk/importexport.py	Tue Jun 28 08:48:51 2005
(at)(at) -78,6 +78,12 (at)(at)
         "Constructor"
         self.id = id
 
+    security.declareProtected(config.EDIT_WORKFLOW, "configureFromXML")
+    def configureFromXML(self, REQUEST):
+        """Saves the properties to the activity."""
+        xmlstr = REQUEST.get('xml')
+        node = minidom.parseString(xmlstr)
+        self.configureFromDOMNode(node.documentElement)
 
     security.declareProtected(config.MANAGE_WORKFLOW, 'configureFromDOMNode')
     def configureFromDOMNode(self, node):

Modified: AlphaFlow/trunk/interfaces.py
==============================================================================
--- AlphaFlow/trunk/interfaces.py	(original)
+++ AlphaFlow/trunk/interfaces.py	Tue Jun 28 08:48:51 2005
(at)(at) -15,6 +15,15 (at)(at)
         id ... id for the object
         """
 
+    def configureFromXML(REQUEST):
+        """Saves the properties to the object.
+
+        REQUEST ... HTTPRequest object which must have property 'xml'
+                    This property must be an XML-File containing the node of
the
+                    object as documentElement.
+        """
+
+
     def configureFromDOMNode(node):
         """Configures the object from the given DOM node.

SVN: r3105 - AlphaFlow/trunk/doc
Michael Howitz <mh(at)gocept.com>
2005-06-28 10:18:38 [ FULL ]
Author: mac
Date: Tue Jun 28 10:12:50 2005
New Revision: 3105

Modified:
   AlphaFlow/trunk/doc/manual.tex
Log:
hints what to document for creating custom activities


Modified: AlphaFlow/trunk/doc/manual.tex
==============================================================================
--- AlphaFlow/trunk/doc/manual.tex	(original)
+++ AlphaFlow/trunk/doc/manual.tex	Tue Jun 28 10:12:50 2005
(at)(at) -14,22 +14,22 (at)(at)
 % Please at least include a long-lived email address;
 % the rest is at your discretion.
 \authoraddress{
-	gocept GmbH \& Co. KG\\
-	Schalaunische Str. 6 \\
+    gocept GmbH \& Co. KG\\
+    Schalaunische Str. 6 \\
     06366 Koethen, Germany\\
-	Email: \email{ct(at)gocept.com}
+    Email: \email{ct(at)gocept.com}
 }
 
-\date{17 June 2006}		% update before release!
-				% Use an explicit date so that reformatting
-				% doesn't cause a new date to be used.  Setting
-				% the date to \today can be used during draft
-				% stages to make it easier to handle versions.
+\date{17 June 2006}     % update before release!
+                % Use an explicit date so that reformatting
+                % doesn't cause a new date to be used.  Setting
+                % the date to \today can be used during draft
+                % stages to make it easier to handle versions.
 
-\release{1.0}			% release version; this is used to define the
-				% \version macro
+\release{1.0}           % release version; this is used to define the
+                % \version macro
 
-\makeindex			% tell \index to actually write the .idx file
+\makeindex          % tell \index to actually write the .idx file
 
 \begin{document}
 
(at)(at) -320,6 +320,18 (at)(at)
 
 \chapter{Creating Custom Activities}
 
+- Usage of WorklowAttributes
+
+- registering custom activites
+
+- the different registries (activities_registry,
+  workflow_attributes_registry, notify_registry) + own registries for
+  own child tags in attributes
+
+- Mixin classes DOMExporter, DOMImporter
+
+- Things the editor needs to work with custom activity
+
 \chapter{The ALF file format}
 
 \appendix
(at)(at) -462,11 +474,11 (at)(at)
 %begin{latexonly}
 \renewcommand{\indexname}{Module Index}
 %end{latexonly}
-\input{mod\jobname.ind}		% Module Index
+\input{mod\jobname.ind}     % Module Index
 
 %begin{latexonly}
 \renewcommand{\indexname}{Index}
 %end{latexonly}
-\input{\jobname.ind}			% Index
+\input{\jobname.ind}            % Index
 
 \end{document}

SVN: r3109 - AlphaFlow/trunk
Michael Howitz <mh(at)gocept.com>
2005-06-28 11:02:56 [ FULL ]
Author: mac
Date: Tue Jun 28 10:57:48 2005
New Revision: 3109

Modified:
   AlphaFlow/trunk/activity.py
   AlphaFlow/trunk/workflowattr.py
Log:
removed unnecessary comments


Modified: AlphaFlow/trunk/activity.py
==============================================================================
--- AlphaFlow/trunk/activity.py	(original)
+++ AlphaFlow/trunk/activity.py	Tue Jun 28 10:57:48 2005
(at)(at) -345,7 +345,6 (at)(at)
 
 #############################
 # Registry for all activities
-# Registry keys should be class.nodeName
 activity_registry = Registry()
 
 def registerActivity(activity):

Modified: AlphaFlow/trunk/workflowattr.py
==============================================================================
--- AlphaFlow/trunk/workflowattr.py	(original)
+++ AlphaFlow/trunk/workflowattr.py	Tue Jun 28 10:57:48 2005
(at)(at) -78,7 +78,6 (at)(at)
 #######################################################################
 # Registry for classes having WorkflowAttributes which are not in other
 # registries.
-# Registry keys should be class.nodeName
 workflow_attributes_registry = Registry()
 
 def InitializeWorkflowAttributes(klass,
registry=workflow_attributes_registry):

MailBoxer