[Erp5-report] r12648 - in /erp5/trunk/products/ERP5Type: TM.py Tool/ClassTool.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Feb 13 13:54:20 CET 2007
Author: jp
Date: Tue Feb 13 13:54:17 2007
New Revision: 12648
URL: http://svn.erp5.org?rev=12648&view=rev
Log:
Now transactional to some extent.
Added:
erp5/trunk/products/ERP5Type/TM.py
Modified:
erp5/trunk/products/ERP5Type/Tool/ClassTool.py
Added: erp5/trunk/products/ERP5Type/TM.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/TM.py?rev=12648&view=auto
==============================================================================
--- erp5/trunk/products/ERP5Type/TM.py (added)
+++ erp5/trunk/products/ERP5Type/TM.py Tue Feb 13 13:54:17 2007
@@ -1,0 +1,90 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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
+#
+##############################################################################
+"""Provide support for linking an external transaction manager with Zope's
+"""
+
+
+class VTM:
+ """Mix-in class that provides transaction management support
+
+ A sub class should call self._register() whenever it performs any
+ transaction-dependent operations (e.g. sql statements).
+
+ The sub class will need to override _finish, to finalize work,
+ _abort, to roll-back work, and perhaps _begin, if any work is
+ needed at the start of a transaction.
+
+ A subclass that uses locking during transaction commit must
+ defined a sortKey() method.
+
+ The VTM variety can be mixed-in with persistent classes.
+ """
+
+ _v_registered=0
+ _v_finalize=0
+
+ def _begin(self): pass
+
+ def _register(self):
+ if not self._v_registered:
+ try:
+ get_transaction().register(Surrogate(self))
+ self._begin()
+ self._v_registered = 1
+ self._v_finalize = 0
+ except:
+ pass
+
+ def tpc_begin(self, *ignored): pass
+ commit=tpc_begin
+
+ def _finish(self):
+ raise NotImplementedError
+
+ def _abort(self):
+ raise NotImplementedError
+
+ def tpc_vote(self, *ignored):
+ self._v_finalize = 1
+
+ def tpc_finish(self, *ignored):
+ if self._v_finalize:
+ try:
+ self._finish()
+ finally:
+ self._v_registered=0
+ self._v_finalize=0
+
+ def abort(self, *ignored):
+ try:
+ self._abort()
+ finally:
+ self._v_registered=0
+ self._v_finalize=0
+
+ tpc_abort = abort
+
+ def sortKey(self, *ignored):
+ """ The sortKey method is used for recent ZODB compatibility which
+ needs to have a known commit order for lock acquisition. Most
+ DA's talking to RDBMS systems do not care about commit order, so
+ return the constant 1
+ """
+ return 1
+
+class Surrogate:
+
+ def __init__(self, db):
+ self._p_jar=db
+ self.__inform_commit__=db.tpc_finish
+ self.__inform_abort__=db.tpc_abort
Modified: erp5/trunk/products/ERP5Type/Tool/ClassTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Tool/ClassTool.py?rev=12648&r1=12647&r2=12648&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Tool/ClassTool.py (original)
+++ erp5/trunk/products/ERP5Type/Tool/ClassTool.py Tue Feb 13 13:54:17 2007
@@ -33,8 +33,9 @@
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass, DTMLFile
from App.config import getConfiguration
+from Products.ERP5Type.TM import VTM as TM
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
-import os
+import os, tempfile
from Products.ERP5Type import Permissions
from Products.ERP5Type import _dtmldir
@@ -65,14 +66,18 @@
ClassTool.
"""
+COPYRIGHT = "Copyright (c) 2002-2007 Nexedi SARL and Contributors. All Rights Reserved."
+LOCAL_DIRECTORY_LIST = ('Document', 'Extensions', 'Constraint', 'tests', 'PropertySheet')
+
if allowClassTool():
- class ClassTool(BaseTool):
+ class ClassTool(TM, BaseTool):
"""
This is the full-featured version of ClassTool.
"""
id = 'portal_classes'
meta_type = 'ERP5 Class Tool'
+ _use_TM = _transactions = 1
# Declarative Security
security = ClassSecurityInfo()
@@ -211,7 +216,7 @@
text = """\
##############################################################################
#
-# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
+# %s
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
@@ -258,8 +263,8 @@
, PropertySheet.XMLObject
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
- )""" % class_id
- writeLocalDocument(class_id, text)
+ )""" % (COPYRIGHT, class_id)
+ self.writeLocalDocument(class_id, text)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editDocumentForm?class_id=%s&message=Document+Created' % (self.absolute_url(), class_id))
@@ -269,7 +274,7 @@
Updates a Document with a new text
"""
previous_text = readLocalDocument(class_id)
- writeLocalDocument(class_id, text, create=0)
+ self.writeLocalDocument(class_id, text, create=0)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editDocumentForm?class_id=%s&message=Document+Saved' % (self.absolute_url(), class_id))
@@ -306,7 +311,7 @@
text = """\
##############################################################################
#
-# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
+# %s
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
@@ -344,8 +349,8 @@
)
-"""
- writeLocalPropertySheet(class_id, text)
+""" % COPYRIGHT
+ self.writeLocalPropertySheet(class_id, text)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editPropertySheetForm?class_id=%s&message=PropertySheet+Created' % (self.absolute_url(), class_id))
@@ -355,7 +360,7 @@
Updates a PropertySheet with a new text
"""
previous_text = readLocalPropertySheet(class_id)
- writeLocalPropertySheet(class_id, text, create=0)
+ self.writeLocalPropertySheet(class_id, text, create=0)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editPropertySheetForm?class_id=%s&message=PropertySheet+Saved' % (self.absolute_url(), class_id))
@@ -390,7 +395,7 @@
text = """\
##############################################################################
#
-# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
+# %s
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
@@ -417,8 +422,8 @@
def myExtensionMethod(self, param=None):
pass
-"""
- writeLocalExtension(class_id, text)
+""" % COPYRIGHT
+ self.writeLocalExtension(class_id, text)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editExtensionForm?class_id=%s&message=Extension+Created' % (self.absolute_url(), class_id))
@@ -428,7 +433,7 @@
Updates a Extension with a new text
"""
previous_text = readLocalExtension(class_id)
- writeLocalExtension(class_id, text, create=0)
+ self.writeLocalExtension(class_id, text, create=0)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editExtensionForm?class_id=%s&message=Extension+Saved' % (self.absolute_url(), class_id))
@@ -447,7 +452,7 @@
text = '''\
##############################################################################
#
-# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
+# %s
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
@@ -519,8 +524,8 @@
are defined in /usr/lib/python/unittest.py.
"""
self.assertEqual(0, 1)
-'''
- writeLocalTest(class_id, text)
+''' % COPYRIGHT
+ self.writeLocalTest(class_id, text)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editTestForm?class_id=%s&message=Test+Created' % (self.absolute_url(), class_id))
@@ -530,7 +535,7 @@
Updates a Test with a new text
"""
previous_text = readLocalTest(class_id)
- writeLocalTest(class_id, text, create=0)
+ self.writeLocalTest(class_id, text, create=0)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editTestForm?class_id=%s&message=Test+Saved' % (self.absolute_url(), class_id))
@@ -553,7 +558,7 @@
text = """\
##############################################################################
#
-# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
+# %s
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
@@ -597,8 +602,8 @@
# Do the job here
return errors
-"""
- writeLocalConstraint(class_id, text)
+""" % COPYRIGHT
+ self.writeLocalConstraint(class_id, text)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editConstraintForm?class_id=%s&message=Constraint+Created' % (self.absolute_url(), class_id))
@@ -608,7 +613,7 @@
Updates a Constraint with a new text
"""
previous_text = readLocalConstraint(class_id)
- writeLocalConstraint(class_id, text, create=0)
+ self.writeLocalConstraint(class_id, text, create=0)
if REQUEST is not None:
REQUEST.RESPONSE.redirect('%s/manage_editConstraintForm?class_id=%s&message=Constraint+Saved' % (self.absolute_url(), class_id))
@@ -696,7 +701,7 @@
text = '''\
##############################################################################
#
-# Copyright (c) 2006 Nexedi SARL and Contributors. All Rights Reserved.
+# %s
# Yoshinori Okuji <yo at nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
@@ -741,7 +746,7 @@
portal_tools = (),
content_constructors = (),
content_classes = ())
-'''
+''' % s
f = open(init, 'w')
try:
f.write(text)
@@ -840,6 +845,85 @@
dochelper.setStaticPropertyList(property_list)
return dochelper
+ # Transaction Management
+ def createTemporaryInstanceHome(self):
+ """
+ """
+ self._register()
+ # Make a new instance home
+ if not getattr(self, '_v_instance_home', None):
+ self._v_instance_home = tempfile.mkdtemp()
+ instance_home = self._v_instance_home
+ for name in LOCAL_DIRECTORY_LIST:
+ os.mkdir(os.sep.join((instance_home, name)))
+
+ def deleteTemporaryInstanceHome(self):
+ """
+ """
+ # Delete the whole instance home
+ if getattr(self, '_v_instance_home', None):
+ tmp_instance_home = self._v_instance_home
+ for name in LOCAL_DIRECTORY_LIST:
+ source_dir = os.sep.join((tmp_instance_home, name))
+ for fname in os.listdir(source_dir):
+ source_file = os.sep.join((source_dir,fname))
+ os.remove(source_file)
+ os.rmdir(source_dir)
+ os.rmdir(tmp_instance_home)
+ self._v_instance_home = None
+
+ def renameTemporaryInstanceHome(self):
+ """
+ """
+ # Delete temporary instance home
+ tmp_instance_home = self._v_instance_home
+ instance_home = getConfiguration().instancehome
+ for name in LOCAL_DIRECTORY_LIST:
+ source_dir = os.sep.join((tmp_instance_home, name))
+ destination_dir = os.sep.join((instance_home, name))
+ for fname in os.listdir(source_dir):
+ source_file = os.sep.join((source_dir,fname))
+ destination_file = os.sep.join((destination_dir,fname))
+ try:
+ os.remove(destination_file)
+ except OSError:
+ pass
+ os.rename(source_file, destination_file)
+ self.deleteTemporaryInstanceHome()
+
+ security.declareProtected( Permissions.ManageExtensions, 'writeLocalPropertySheet' )
+ def writeLocalPropertySheet(self, class_id, text, create=1):
+ self.createTemporaryInstanceHome()
+ writeLocalPropertySheet(class_id, text, create=create, instance_home=self._v_instance_home)
+
+ security.declareProtected( Permissions.ManageExtensions, 'writeLocalExtension' )
+ def writeLocalExtension(self, class_id, text, create=1):
+ self.createTemporaryInstanceHome()
+ writeLocalExtension(class_id, text, create=create, instance_home=self._v_instance_home)
+
+ security.declareProtected( Permissions.ManageExtensions, 'writeLocalTest' )
+ def writeLocalTest(self, class_id, text, create=1):
+ self.createTemporaryInstanceHome()
+ writeLocalTest(class_id, text, create=create, instance_home=self._v_instance_home)
+
+ security.declareProtected( Permissions.ManageExtensions, 'writeLocalDocument' )
+ def writeLocalDocument(self, class_id, text, create=1):
+ self.createTemporaryInstanceHome()
+ writeLocalDocument(class_id, text, create=create, instance_home=self._v_instance_home)
+
+ security.declareProtected( Permissions.ManageExtensions, 'writeLocalConstraint' )
+ def writeLocalConstraint(self, class_id, text, create=1):
+ self.createTemporaryInstanceHome()
+ writeLocalConstraint(class_id, text, create=create, instance_home=self._v_instance_home)
+
+ def _finish(self):
+ # Move all temp files we created
+ self.renameTemporaryInstanceHome()
+
+ def _abort(self):
+ # Delete all temp files we created
+ self.deleteTemporaryInstanceHome()
+
else:
class ClassTool(BaseTool):
@@ -856,3 +940,4 @@
manage_overview = DTMLFile( 'explainDummyClassTool', _dtmldir )
InitializeClass(ClassTool)
+
More information about the Erp5-report
mailing list