Commit 01beaca6 authored by Hanno Schlichting's avatar Hanno Schlichting

Changed product install so it won't write persistent changes only to abort...

Changed product install so it won't write persistent changes only to abort them. Instead we don't make any database changes in the first place.
parent c926c4fe
...@@ -18,6 +18,11 @@ Bugs Fixed ...@@ -18,6 +18,11 @@ Bugs Fixed
Features Added Features Added
++++++++++++++ ++++++++++++++
- Changed product install so it won't write persistent changes only to abort
them. Instead we don't make any database changes in the first place.
- Disabled persistent product installation in the default test configuration.
- Directly extend and use the Zope Toolkit KGS release 1.0dev-r113891 from - Directly extend and use the Zope Toolkit KGS release 1.0dev-r113891 from
http://download.zope.org/zopetoolkit/index/. http://download.zope.org/zopetoolkit/index/.
......
...@@ -23,6 +23,8 @@ from AccessControl.PermissionMapping import aqwrap ...@@ -23,6 +23,8 @@ from AccessControl.PermissionMapping import aqwrap
from Acquisition import Acquired from Acquisition import Acquired
from Acquisition import aq_base from Acquisition import aq_base
from Acquisition import Implicit from Acquisition import Implicit
from ExtensionClass import Base
def _product_packages(): def _product_packages():
"""Returns all product packages including the regularly defined """Returns all product packages including the regularly defined
...@@ -41,7 +43,7 @@ def _product_packages(): ...@@ -41,7 +43,7 @@ def _product_packages():
return packages return packages
class Product(object): class Product(Base):
"""Model a non-persistent product wrapper. """Model a non-persistent product wrapper.
""" """
......
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
import os import os
import transaction
from AccessControl.class_init import InitializeClass from AccessControl.class_init import InitializeClass
from AccessControl.owner import UnownableOwner from AccessControl.owner import UnownableOwner
from AccessControl.SecurityInfo import ClassSecurityInfo from AccessControl.SecurityInfo import ClassSecurityInfo
...@@ -204,13 +202,16 @@ InitializeClass(Product) ...@@ -204,13 +202,16 @@ InitializeClass(Product)
def initializeProduct(productp, name, home, app): def initializeProduct(productp, name, home, app):
# Initialize a levered product # Initialize a persistent product
assert doInstall()
import Globals # to set data import Globals # to set data
products = app.Control_Panel.Products
fver = '' fver = ''
if hasattr(productp, '__import_error__'): ie=productp.__import_error__ if hasattr(productp, '__import_error__'):
else: ie=None ie = productp.__import_error__
else:
ie = None
# Retrieve version number from any suitable version.txt # Retrieve version number from any suitable version.txt
for fname in ('version.txt', 'VERSION.txt', 'VERSION.TXT'): for fname in ('version.txt', 'VERSION.txt', 'VERSION.TXT'):
...@@ -223,32 +224,33 @@ def initializeProduct(productp, name, home, app): ...@@ -223,32 +224,33 @@ def initializeProduct(productp, name, home, app):
except IOError: except IOError:
continue continue
old=None old = None
products = app.Control_Panel.Products
try: try:
if ihasattr(products,name): if ihasattr(products, name):
old=getattr(products, name) old=getattr(products, name)
if ihasattr(old,'version') and old.version==fver: if ihasattr(old,'version') and old.version==fver:
if hasattr(old, 'import_error_') and \ if hasattr(old, 'import_error_') and \
old.import_error_==ie: old.import_error_==ie:
# Version hasn't changed. Don't reinitialize. # Version hasn't changed. Don't reinitialize.
return old return old
except: pass except:
pass
f = fver and (" (%s)" % fver) f = fver and (" (%s)" % fver)
product=Product(name, 'Installed product %s%s' % (name,f)) product=Product(name, 'Installed product %s%s' % (name, f))
if old is not None: if old is not None:
app._manage_remove_product_meta_type(product) app._manage_remove_product_meta_type(product)
products._delObject(name) products._delObject(name)
for id, v in old.objectItems(): for id, v in old.objectItems():
try: product._setObject(id, v) try:
except: pass product._setObject(id, v)
except:
pass
products._setObject(name, product) products._setObject(name, product)
product.icon='p_/InstalledProduct_icon' product.home = home
product.version=fver
product.home=home
product.thisIsAnInstalledProduct=1
if ie: if ie:
product.import_error_=ie product.import_error_=ie
...@@ -277,12 +279,9 @@ def initializeProduct(productp, name, home, app): ...@@ -277,12 +279,9 @@ def initializeProduct(productp, name, home, app):
{'label':'Refresh', 'action':'manage_refresh', {'label':'Refresh', 'action':'manage_refresh',
'help': ('OFSP','Product_Refresh.stx')},) 'help': ('OFSP','Product_Refresh.stx')},)
if not doInstall():
transaction.abort()
return product
return product return product
def ihasattr(o, name): def ihasattr(o, name):
return hasattr(o, name) and o.__dict__.has_key(name) return hasattr(o, name) and o.__dict__.has_key(name)
......
...@@ -24,7 +24,6 @@ from AccessControl.Permission import registerPermissions ...@@ -24,7 +24,6 @@ from AccessControl.Permission import registerPermissions
from AccessControl.PermissionRole import PermissionRole from AccessControl.PermissionRole import PermissionRole
from App.Common import package_home from App.Common import package_home
from App.ImageFile import ImageFile from App.ImageFile import ImageFile
from App.Product import doInstall
from DateTime.DateTime import DateTime from DateTime.DateTime import DateTime
from HelpSys import APIHelpTopic from HelpSys import APIHelpTopic
from HelpSys import HelpTopic from HelpSys import HelpTopic
...@@ -50,14 +49,15 @@ LOG = getLogger('ProductContext') ...@@ -50,14 +49,15 @@ LOG = getLogger('ProductContext')
class ProductContext: class ProductContext:
def __init__(self, product, app, package): def __init__(self, product, app, package):
self.__prod=product self.__prod = product
self.__app=app # app is None by default which signals disabled product installation
self.__pack=package self.__app = app
self.__pack = package
def registerClass(self, instance_class=None, meta_type='', def registerClass(self, instance_class=None, meta_type='',
permission=None, constructors=(), permission=None, constructors=(),
icon=None, permissions=None, legacy=(), icon=None, permissions=None, legacy=(),
visibility="Global",interfaces=_marker, visibility="Global", interfaces=_marker,
container_filter=None container_filter=None
): ):
"""Register a constructor """Register a constructor
...@@ -140,7 +140,7 @@ class ProductContext: ...@@ -140,7 +140,7 @@ class ProductContext:
else: else:
default = ('Manager',) default = ('Manager',)
pr=PermissionRole(permission,default) pr = PermissionRole(permission,default)
registerPermissions(((permission, (), default),)) registerPermissions(((permission, (), default),))
############################################################ ############################################################
...@@ -168,7 +168,7 @@ class ProductContext: ...@@ -168,7 +168,7 @@ class ProductContext:
else: else:
name = initial.__name__ name = initial.__name__
fd=getattr(pack, '__FactoryDispatcher__', None) fd = getattr(pack, '__FactoryDispatcher__', None)
if fd is None: if fd is None:
class __FactoryDispatcher__(FactoryDispatcher): class __FactoryDispatcher__(FactoryDispatcher):
"Factory Dispatcher for a Specific Product" "Factory Dispatcher for a Specific Product"
...@@ -231,6 +231,8 @@ class ProductContext: ...@@ -231,6 +231,8 @@ class ProductContext:
""" """
Returns the ProductHelp associated with the current Product. Returns the ProductHelp associated with the current Product.
""" """
if self.__app is None:
return self.__prod.getProductHelp()
return self.__prod.__of__(self.__app.Control_Panel.Products).getProductHelp() return self.__prod.__of__(self.__app.Control_Panel.Products).getProductHelp()
def registerHelpTopic(self, id, topic): def registerHelpTopic(self, id, topic):
...@@ -267,7 +269,7 @@ class ProductContext: ...@@ -267,7 +269,7 @@ class ProductContext:
.py -- APIHelpTopic .py -- APIHelpTopic
""" """
if not doInstall(): if not self.__app:
return return
help=self.getProductHelp() help=self.getProductHelp()
......
...@@ -30,6 +30,7 @@ from AccessControl.Permission import ApplicationDefaultPermissions ...@@ -30,6 +30,7 @@ from AccessControl.Permission import ApplicationDefaultPermissions
from Acquisition import aq_base from Acquisition import aq_base
from App.ApplicationManager import ApplicationManager from App.ApplicationManager import ApplicationManager
from App.config import getConfiguration from App.config import getConfiguration
from App import FactoryDispatcher
from App.Product import doInstall from App.Product import doInstall
from DateTime import DateTime from DateTime import DateTime
from HelpSys.HelpSys import HelpSys from HelpSys.HelpSys import HelpSys
...@@ -676,24 +677,26 @@ def install_product(app, product_dir, product_name, meta_types, ...@@ -676,24 +677,26 @@ def install_product(app, product_dir, product_name, meta_types,
# expected to implement a method named 'initialize' in # expected to implement a method named 'initialize' in
# their __init__.py that takes the ProductContext as an # their __init__.py that takes the ProductContext as an
# argument. # argument.
productObject = App.Product.initializeProduct( do_install = doInstall()
product, product_name, package_dir, app) if do_install:
context = ProductContext(productObject, app, product) productObject = App.Product.initializeProduct(
product, product_name, package_dir, app)
context = ProductContext(productObject, app, product)
else:
# avoid any persistent connection
productObject = FactoryDispatcher.Product(product_name)
context = ProductContext(productObject, None, product)
# Look for an 'initialize' method in the product. # Look for an 'initialize' method in the product.
initmethod = pgetattr(product, 'initialize', None) initmethod = pgetattr(product, 'initialize', None)
if initmethod is not None: if initmethod is not None:
initmethod(context) initmethod(context)
if not doInstall(): if do_install:
transaction.abort()
else:
transaction.get().note('Installed product ' + product_name) transaction.get().note('Installed product ' + product_name)
transaction.commit() transaction.commit()
except KeyboardInterrupt: except Exception:
raise
except:
if log_exc: if log_exc:
LOG.error('Couldn\'t install %s' % product_name, LOG.error('Couldn\'t install %s' % product_name,
exc_info=sys.exc_info()) exc_info=sys.exc_info())
...@@ -706,23 +709,27 @@ def install_package(app, module, init_func, raise_exc=False, log_exc=True): ...@@ -706,23 +709,27 @@ def install_package(app, module, init_func, raise_exc=False, log_exc=True):
"""Installs a Python package like a product.""" """Installs a Python package like a product."""
from App.ProductContext import ProductContext from App.ProductContext import ProductContext
try: try:
product = App.Product.initializeProduct(module, do_install = doInstall()
module.__name__, name = module.__name__
module.__path__[0], if do_install:
app) product = App.Product.initializeProduct(module,
product.package_name = module.__name__ name,
module.__path__[0],
app)
else:
product = FactoryDispatcher.Product(name)
app = None
product.package_name = name
if init_func is not None: if init_func is not None:
newContext = ProductContext(product, app, module) newContext = ProductContext(product, app, module)
init_func(newContext) init_func(newContext)
if not doInstall(): if do_install:
transaction.abort()
else:
transaction.get().note('Installed package %s' % module.__name__) transaction.get().note('Installed package %s' % module.__name__)
transaction.commit() transaction.commit()
except KeyboardInterrupt: except Exception:
raise
except:
if log_exc: if log_exc:
LOG.error("Couldn't install %s" % module.__name__, LOG.error("Couldn't install %s" % module.__name__,
exc_info=True) exc_info=True)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment