Log message for revision 122065: Removed various persistent product related code and options. The `enable-product-installation` `zope.conf` setting is now a no-op.
Changed: U Zope/trunk/doc/CHANGES.rst U Zope/trunk/src/App/ApplicationManager.py U Zope/trunk/src/App/FactoryDispatcher.py U Zope/trunk/src/App/Product.py U Zope/trunk/src/App/ProductContext.py D Zope/trunk/src/App/ProductRegistry.py D Zope/trunk/src/App/RefreshFuncs.py D Zope/trunk/src/App/dtml/readme.dtml D Zope/trunk/src/App/dtml/refresh.dtml D Zope/trunk/src/App/dtml/traceback.dtml U Zope/trunk/src/App/tests/test_ApplicationManager.py U Zope/trunk/src/OFS/Application.py U Zope/trunk/src/OFS/ObjectManager.py U Zope/trunk/src/OFS/tests/testProductInit.py U Zope/trunk/src/OFS/tests/test_registerpackage.py U Zope/trunk/src/Testing/ZopeTestCase/ZopeLite.py U Zope/trunk/src/Zope2/App/startup.py U Zope/trunk/src/Zope2/Startup/zopeschema.xml -=- Modified: Zope/trunk/doc/CHANGES.rst =================================================================== --- Zope/trunk/doc/CHANGES.rst 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/doc/CHANGES.rst 2011-07-02 18:08:30 UTC (rev 122065) @@ -33,6 +33,9 @@ Restructuring +++++++++++++ +- Removed various persistent product related code and options. The + `enable-product-installation` `zope.conf` setting is now a no-op. + - Changed the value for `default-zpublisher-encoding` and `management_page_charset` to `utf-8`. Modified: Zope/trunk/src/App/ApplicationManager.py =================================================================== --- Zope/trunk/src/App/ApplicationManager.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/ApplicationManager.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -254,7 +254,7 @@ -class ApplicationManager(Folder,CacheManager): +class ApplicationManager(Folder, CacheManager): """System management """ __roles__ = ('Manager',) Modified: Zope/trunk/src/App/FactoryDispatcher.py =================================================================== --- Zope/trunk/src/App/FactoryDispatcher.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/FactoryDispatcher.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -98,13 +98,7 @@ '__FactoryDispatcher__', FactoryDispatcher) - productfolder = self.aq_acquire('_getProducts')() - try: - product = productfolder._product(name) - except AttributeError: - # If we do not have a persistent product entry, return - product = Product(name) - + product = Product(name) dispatcher=dispatcher_class(product, self.aq_parent, REQUEST) return dispatcher.__of__(self) Modified: Zope/trunk/src/App/Product.py =================================================================== --- Zope/trunk/src/App/Product.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/Product.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -10,37 +10,9 @@ # FOR A PARTICULAR PURPOSE. # ############################################################################## -"""Product objects -""" -# The new Product model: -# -# Products may be defined in the Products folder or by placing directories -# in lib/python/Products. -# -# Products in lib/python/Products may have up to three sources of information: -# -# - Static information defined via Python. This information is -# described and made available via __init__.py. -# -# - Dynamic object data that gets copied into the Bobobase. -# This is contained in product.dat (which is obfuscated). -# -# - Static extensions supporting the dynamic data. These too -# are obfuscated. -# -# Products may be copied and pasted only within the products folder. -# -# If a product is deleted (or cut), it is automatically recreated -# on restart if there is still a product directory. - -import os - from AccessControl.class_init import InitializeClass from AccessControl.owner import UnownableOwner -from AccessControl.SecurityInfo import ClassSecurityInfo -from AccessControl.unauthorized import Unauthorized -from App.special_dtml import DTMLFile from OFS.Folder import Folder @@ -65,225 +37,3 @@ return 0 InitializeClass(ProductFolder) - - -class Product(Folder): - """Model a product that can be created through the web. - """ - - security = ClassSecurityInfo() - - meta_type='Product' - icon='p_/Product_icon' - version='' - configurable_objects_=() - import_error_=None - - manage_options = ( - (Folder.manage_options[0],) + - tuple(Folder.manage_options[2:]) - ) - - _properties = Folder._properties+( - {'id':'version', 'type': 'string'}, - ) - - _reserved_names=('Help',) - - def __init__(self, id, title): - from HelpSys.HelpSys import ProductHelp - - self.id = id - self.title = title - self._setObject('Help', ProductHelp('Help', id)) - - security.declarePublic('Destination') - def Destination(self): - "Return the destination for factory output" - return self - - security.declarePublic('DestinationURL') - def DestinationURL(self): - "Return the URL for the destination for factory output" - return self.REQUEST['BASE4'] - - - manage_traceback = DTMLFile('dtml/traceback', globals()) - manage_readme = DTMLFile('dtml/readme', globals()) - def manage_get_product_readme__(self): - for name in ('README.txt', 'README.TXT', 'readme.txt'): - path = os.path.join(self.home, name) - if os.path.isfile(path): - return open(path).read() - return '' - - def permissionMappingPossibleValues(self): - return self.possible_permissions() - - def getProductHelp(self): - """Returns the ProductHelp object associated with the Product. - """ - from HelpSys.HelpSys import ProductHelp - if not hasattr(self, 'Help'): - self._setObject('Help', ProductHelp('Help', self.id)) - return self.Help - - # - # Product refresh - # - - _refresh_dtml = DTMLFile('dtml/refresh', globals()) - - def _readRefreshTxt(self, pid=None): - import Products - refresh_txt = None - if pid is None: - pid = self.id - for productDir in Products.__path__: - found = 0 - for name in ('refresh.txt', 'REFRESH.txt', 'REFRESH.TXT'): - p = os.path.join(productDir, pid, name) - if os.path.exists(p): - found = 1 - break - if found: - try: - file = open(p) - text = file.read() - file.close() - refresh_txt = text - break - except: - # Not found here. - pass - return refresh_txt - - def manage_performRefresh(self, REQUEST=None): - """ Attempts to perform a refresh operation. - """ - from App.RefreshFuncs import performFullRefresh - if self._readRefreshTxt() is None: - raise Unauthorized, 'refresh.txt not found' - message = None - if performFullRefresh(self._p_jar, self.id): - from ZODB import Connection - Connection.resetCaches() # Clears cache in future connections. - message = 'Product refreshed.' - else: - message = 'An exception occurred.' - if REQUEST is not None: - return self.manage_refresh(REQUEST, manage_tabs_message=message) - - def manage_enableAutoRefresh(self, enable=0, REQUEST=None): - """ Changes the auto refresh flag for this product. - """ - from App.RefreshFuncs import enableAutoRefresh - if self._readRefreshTxt() is None: - raise Unauthorized, 'refresh.txt not created' - enableAutoRefresh(self._p_jar, self.id, enable) - if enable: - message = 'Enabled auto refresh.' - else: - message = 'Disabled auto refresh.' - if REQUEST is not None: - return self.manage_refresh(REQUEST, manage_tabs_message=message) - - def manage_selectDependentProducts(self, selections=(), REQUEST=None): - """ Selects which products to refresh simultaneously. - """ - from App.RefreshFuncs import setDependentProducts - if self._readRefreshTxt() is None: - raise Unauthorized, 'refresh.txt not created' - setDependentProducts(self._p_jar, self.id, selections) - if REQUEST is not None: - return self.manage_refresh(REQUEST) - -InitializeClass(Product) - - -def initializeProduct(productp, name, home, app): - # Initialize a persistent product - assert doInstall() - fver = '' - - if hasattr(productp, '__import_error__'): - ie = productp.__import_error__ - else: - ie = None - - # Retrieve version number from any suitable version.txt - for fname in ('version.txt', 'VERSION.txt', 'VERSION.TXT'): - try: - fpath = os.path.join(home, fname) - fhandle = open(fpath, 'r') - fver = fhandle.read().strip() - fhandle.close() - break - except IOError: - continue - - old = None - products = app.Control_Panel.Products - try: - if ihasattr(products, name): - old=getattr(products, name) - if ihasattr(old,'version') and old.version==fver: - if hasattr(old, 'import_error_') and \ - old.import_error_==ie: - # Version hasn't changed. Don't reinitialize. - return old - except: - pass - - f = fver and (" (%s)" % fver) - product=Product(name, 'Installed product %s%s' % (name, f)) - - if old is not None: - app._manage_remove_product_meta_type(product) - products._delObject(name) - for id, v in old.objectItems(): - try: - product._setObject(id, v) - except: - pass - - products._setObject(name, product) - product.home = home - - if ie: - product.import_error_=ie - product.title='Broken product %s' % name - product.icon='p_/BrokenProduct_icon' - product.manage_options=( - {'label':'Traceback', 'action':'manage_traceback'}, - ) - - for name in ('README.txt', 'README.TXT', 'readme.txt'): - path = os.path.join(home, name) - if os.path.isfile(path): - product.manage_options=product.manage_options+( - {'label':'README', 'action':'manage_readme'}, - ) - break - - # Ensure this product has a refresh tab. - found = 0 - for option in product.manage_options: - if option.get('label') == 'Refresh': - found = 1 - break - if not found: - product.manage_options = product.manage_options + ( - {'label':'Refresh', 'action':'manage_refresh'}, - ) - - return product - - -def ihasattr(o, name): - return hasattr(o, name) and o.__dict__.has_key(name) - - -def doInstall(): - from App.config import getConfiguration - return getConfiguration().enable_product_installation Modified: Zope/trunk/src/App/ProductContext.py =================================================================== --- Zope/trunk/src/App/ProductContext.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/ProductContext.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -190,9 +190,7 @@ # currently also required by the _verifyObjectPaste # method of CopyContainers like Folders. 'action': ('manage_addProduct/%s/%s' % (pid, name)), - # 'product': Used by ProductRegistry for TTW products and by - # OFS.Application for refreshing products. - # This key might not be available. + # 'product': No longer used 'product': pid, # 'permission': Guards the add action. 'permission': permission, Deleted: Zope/trunk/src/App/ProductRegistry.py =================================================================== --- Zope/trunk/src/App/ProductRegistry.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/ProductRegistry.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -1,131 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 Zope Foundation and Contributors. -# -# 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 -# -############################################################################## - -# Product registry and new product factory model. There will be a new -# mechanism for defining actions for meta types. If an action is of -# the form: -# -# manage_addProduct-name-factoryid -# -# Then the machinery that invokes an add-product form -# will return: -# ....what? - -class ProductRegistryMixin: - # This class implements a protocol for registering products that - # are defined through the web. - - # This class is a mix-in class for the top-level application object. - - def _manage_remove_product_meta_type(self, product, - id=None, meta_type=None): - r=[] - pid=product.id - for mt in self._getProductRegistryMetaTypes(): - if 'product' in mt: - if mt['product']==pid and ( - meta_type is None or meta_type==mt['name']): - continue - elif meta_type==mt['name']: continue - r.append(mt) - - self._setProductRegistryMetaTypes(tuple(r)) - - def _constructor_prefix_string(self, pid): - return 'manage_addProduct/%s/' % pid - - def _manage_add_product_meta_type(self, product, id, meta_type, - permission=''): - pid=product.id - - meta_types=self._getProductRegistryMetaTypes() - - for mt in meta_types: - if mt['name']==meta_type: - if 'product' not in mt: mt['product']=pid - if mt['product'] != pid: - raise ValueError, ( - 'The type <em>%s</em> is already defined.' % meta_type) - mt['action']='%s%s' % ( - self._constructor_prefix_string(pid), id) - if permission: mt['permission']=permission - return - - mt={ - 'name': meta_type, - 'action': ('%s%s' % ( - self._constructor_prefix_string(pid), id)), - 'product': pid - } - if permission: mt['permission']=permission - - self._setProductRegistryMetaTypes(meta_types+(mt,)) - - # HACK - sometimes an unwrapped App object seems to be passed as - # self to these methods, which means that they dont have an aq_aquire - # method. Until Jim has time to look into this, this aq_maybe method - # appears to be an effective work-around... - def aq_maybe(self, name): - if hasattr(self, name): - return getattr(self, name) - return self.aq_acquire(name) - - def _manage_add_product_data(self, type, product, id, **data): - values=filter( - lambda d, product=product, id=id: - not (d['product']==product and d['id']==id), - list(self.aq_maybe('_getProductRegistryData')(type)) - ) - - data['product']=product - data['id']=id - values.append(data) - - self.aq_maybe('_setProductRegistryData')(type, tuple(values)) - - def _manage_remove_product_data(self, type, product, id): - values=filter( - lambda d, product=product, id=id: - not (d['product']==product and d['id']==id), - self.aq_maybe('_getProductRegistryData')(type) - ) - - self.aq_maybe('_setProductRegistryData')(type, tuple(values)) - - -class ProductRegistry(ProductRegistryMixin): - # This class implements a protocol for registering products that - # are defined through the web. It also provides methods for - # getting hold of the Product Registry, Control_Panel.Products. - - # This class is a mix-in class for the top-level application object. - - def _getProducts(self): return self.Control_Panel.Products - - _product_meta_types=() - - def _getProductRegistryMetaTypes(self): - return self._product_meta_types - - def _setProductRegistryMetaTypes(self, v): - self._product_meta_types=v - - def _getProductRegistryData(self, name): - return getattr(self, '_product_%s' % name) - - def _setProductRegistryData(self, name, v): - name='_product_%s' % name - if hasattr(self, name): - return setattr(self, name, v) - else: - raise AttributeError, name Deleted: Zope/trunk/src/App/RefreshFuncs.py =================================================================== --- Zope/trunk/src/App/RefreshFuncs.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/RefreshFuncs.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -1,339 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 Zope Foundation and Contributors. -# -# 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 -# -############################################################################## -''' -Functions for refreshing products. -''' - -from logging import getLogger -import os -import sys -from time import time -from traceback import format_exception - -from ExtensionClass import Base -from Persistence import PersistentMapping - -LOG = getLogger('RefreshFuncs') -global_classes_timestamp = 0 -products_mod_times = {} - -_marker = [] # create a new marker object. - -refresh_exc_info = {} - -class dummyClass: - pass - -class dummyClass2(Base): - pass - -def dummyFunc(): - pass - -ClassTypes = (type(dummyClass), type(dummyClass2)) -ModuleType = type(sys) -FuncType = type(dummyFunc) - -next_auto_refresh_check = 0 -AUTO_REFRESH_INTERVAL = 2 # 2 seconds. - -# Functions for storing and retrieving the auto-refresh state for -# each product. - -def _getCentralRefreshData(jar, create=0): - root = jar.root() - if root.has_key('RefreshData'): - rd = root['RefreshData'] - else: - rd = PersistentMapping() - if create: - root['RefreshData'] = rd - return rd - -def isAutoRefreshEnabled(jar, productid): - rd = _getCentralRefreshData(jar) - ids = rd.get('auto', None) - if ids: - return ids.get(productid, 0) - else: - return 0 - -def enableAutoRefresh(jar, productid, enable): - productid = str(productid) - rd = _getCentralRefreshData(jar, 1) - ids = rd.get('auto', None) - if ids is None: - if enable: - rd['auto'] = ids = PersistentMapping() - else: - return - if enable: - ids[productid] = 1 - else: - if ids.has_key(productid): - del ids[productid] - -def listAutoRefreshableProducts(jar): - rd = _getCentralRefreshData(jar) - auto = rd.get('auto', None) - if auto: - ids = [] - for k, v in auto.items(): - if v: - ids.append(k) - return ids - else: - return () - -def getDependentProducts(jar, productid): - rd = _getCentralRefreshData(jar) - products = rd.get('products', None) - if products is None: - return () - product = products.get(productid, None) - if product is None: - return () - return product.get('dependent_products', ()) - -def setDependentProducts(jar, productid, dep_ids): - productid = str(productid) - rd = _getCentralRefreshData(jar, 1) - products = rd.get('products', None) - if products is None: - rd['products'] = products = PersistentMapping() - product = products.get(productid, None) - if product is None: - products[productid] = product = PersistentMapping() - product['dependent_products'] = tuple(map(str, dep_ids)) - - -# Functions for performing refresh. - -def getReloadVar(module): - reload_var = getattr(module, '__refresh_module__', _marker) - if reload_var is _marker: - reload_var = getattr(module, '__reload_module__', _marker) - if reload_var is _marker: - reload_var = 1 - return reload_var - -def listRefreshableModules(productid): - prefix = "Products.%s" % productid - prefixdot = prefix + '.' - lpdot = len(prefixdot) - rval = [] - for name, module in sys.modules.items(): - if module and (name == prefix or name[:lpdot] == prefixdot): - reload_var = getReloadVar(module) - if reload_var: - rval.append((name, module)) - return rval - -def logBadRefresh(productid): - exc = sys.exc_info() - try: - LOG.error('Exception while refreshing %s' % productid, exc_info=exc) - if hasattr(exc[0], '__name__'): - error_type = exc[0].__name__ - else: - error_type = str(exc[0]) - error_value = str(exc[1]) - info = ''.join(format_exception(exc[0], exc[1], exc[2], limit=200)) - refresh_exc_info[productid] = (error_type, error_value, info) - finally: - exc = None - -def performRefresh(jar, productid): - '''Attempts to perform a refresh operation. - ''' - refresh_exc_info[productid] = None - setupModTimes(productid) # Refresh again only if changed again. - - modlist = listRefreshableModules(productid) - former_modules = {} - try: - # Remove modules from sys.modules but keep a handle - # on the old modules in case there's a problem. - for name, module in modlist: - m = sys.modules.get(name, None) - if m is not None: - former_modules[name] = m - del sys.modules[name] - - # Reimport and reinstall the product. - from OFS import Application - Application.reimport_product(productid) - app = jar.root()['Application'] - Application.reinstall_product(app, productid) - return 1 - except: - # Couldn't refresh. Reinstate removed modules. - for name, module in former_modules.items(): - sys.modules[name] = module - raise - -def performSafeRefresh(jar, productid): - try: - LOG.info('Refreshing product %s' % productid) - if not performRefresh(jar, productid): - return 0 - except: - logBadRefresh(productid) - return 0 - else: - return 1 - -def performFullRefresh(jar, productid): - # Refresh dependent products also. - if performSafeRefresh(jar, productid): - dep_ids = getDependentProducts(jar, productid) - for dep_id in dep_ids: - if isAutoRefreshEnabled(jar, dep_id): - if not performSafeRefresh(jar, dep_id): - return 0 - else: - return 0 - return 1 - -def getLastRefreshException(productid): - return refresh_exc_info.get(productid, None) - -# Functions for quickly scanning the dates of product modules. - -def tryFindProductDirectory(productid): - import Products - path_join = os.path.join - isdir = os.path.isdir - exists = os.path.exists - - for products_dir in Products.__path__: - product_dir = path_join(products_dir, productid) - if not isdir(product_dir): continue - if not exists(path_join(product_dir, '__init__.py')): - if not exists(path_join(product_dir, '__init__.pyc')): - continue - return product_dir - return None - -def tryFindModuleFilename(product_dir, filename): - # Try different variations of the filename of a module. - path_join = os.path.join - isdir = os.path.isdir - exists = os.path.exists - - found = None - fn = path_join(product_dir, filename + '.py') - if exists(fn): - found = fn - if not found: - fn = fn + 'c' - if exists(fn): - found = fn - if not found: - fn = path_join(product_dir, filename) - if isdir(fn): - fn = path_join(fn, '__init__.py') - if exists(fn): - found = fn - else: - fn = fn + 'c' - if exists(fn): - found = fn - return found - -def setupModTimes(productid): - mod_times = [] - product_dir = tryFindProductDirectory(productid) - if product_dir is not None: - modlist = listRefreshableModules(productid) - - path_join = os.path.join - exists = os.path.exists - - for name, module in modlist: - splitname = name.split( '.')[2:] - if not splitname: - filename = '__init__' - else: - filename = apply(path_join, splitname) - found = tryFindModuleFilename(product_dir, filename) - - if found: - try: mtime = os.stat(found)[8] - except: mtime = 0 - mod_times.append((found, mtime)) - products_mod_times[productid] = mod_times - -def checkModTimes(productid): - # Returns 1 if there were changes. - mod_times = products_mod_times.get(productid, None) - if mod_times is None: - # Initialize the mod times. - setupModTimes(productid) - return 0 - for filename, mod_time in mod_times: - try: mtime = os.stat(filename)[8] - except: mtime = 0 - if mtime != mod_time: - # Something changed! - return 1 - return 0 - -# Functions for performing auto-refresh. - -def checkAutoRefresh(jar): - ''' - Returns the IDs of products that need to be auto-refreshed. - ''' - # Note: this function is NOT allowed to change the database! - global next_auto_refresh_check - now = time() - if next_auto_refresh_check and next_auto_refresh_check > now: - # Not enough time has passed. - return () - next_auto_refresh_check = now + AUTO_REFRESH_INTERVAL - - rd = _getCentralRefreshData(jar) - ids = rd.get('auto', None) - if not ids: - return () - auto_refresh_ids = [] - for productid in ids.keys(): - if checkModTimes(productid): - auto_refresh_ids.append(productid) - return auto_refresh_ids - -def finishAutoRefresh(jar, productids): - # This function is allowed to change the database. - for productid in productids: - performFullRefresh(jar, productid) - -def autoRefresh(jar): - # Must be called before there are any changes made - # by the connection to the database! - import transaction - auto_refresh_ids = checkAutoRefresh(jar) - if auto_refresh_ids: - finishAutoRefresh(jar, auto_refresh_ids) - from ZODB import Connection - Connection.resetCaches() - transaction.commit() - jar._resetCache() - transaction.begin() - -def setupAutoRefresh(jar): - # Install hook. - from App.ZApplication import connection_open_hooks - connection_open_hooks.append(autoRefresh) - # Init mod times. - checkAutoRefresh(jar) Deleted: Zope/trunk/src/App/dtml/readme.dtml =================================================================== --- Zope/trunk/src/App/dtml/readme.dtml 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/dtml/readme.dtml 2011-07-02 18:08:30 UTC (rev 122065) @@ -1,6 +0,0 @@ -<dtml-var manage_page_header> -<dtml-var manage_tabs> - -<dtml-var manage_get_product_readme__ fmt=structured-text> - -<dtml-var manage_page_footer> Deleted: Zope/trunk/src/App/dtml/refresh.dtml =================================================================== --- Zope/trunk/src/App/dtml/refresh.dtml 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/dtml/refresh.dtml 2011-07-02 18:08:30 UTC (rev 122065) @@ -1,116 +0,0 @@ -<dtml-comment> - Arguments for this method: - id, refresh_txt, error_type, error_value, error_tb, devel_mode, - auto_refresh_enabled, auto_refresh_other, dependent_products, - loaded_modules -</dtml-comment> -<dtml-let form_title="'Refresh product: ' + id"> -<dtml-if manage_page_header> - <dtml-var manage_page_header> -<dtml-else> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> - <html lang="en"> - <head> - <title>&dtml-form_title;</title> - </head> - <body bgcolor="#FFFFFF" link="#000099" vlink="#555555"> - <h3>&dtml-form_title;</h3> -</dtml-if> -</dtml-let> -<dtml-var manage_tabs> - -<dtml-if expr="refresh_txt == _.None"> - <p>The refresh function, designed to ease the development of Zope - products, is not currently enabled for this product. - To make it available, put a file named "refresh.txt" in the &dtml-id; - product directory. Please note that not all products are - compatible with the refresh function.</p> -<dtml-else> - - <dtml-if error_type> - <p><b>An exception occurred during the last refresh.</b><br /> - Exception type: <b>&dtml-error_type;</b> <br /> - Exception value: <b>&dtml-error_value;</b> - </p> - <pre>&dtml-error_tb;</pre> - <hr /> - </dtml-if> - - <form action="&dtml-absolute_url;" method="POST"> - <table border="0"> - <tr> - <td valign="top"> - - <dtml-if expr="_.string.strip(refresh_txt)"> - <p> - <b>Important information about refreshing this product:</b><br /> - <dtml-var refresh_txt fmt="structured-text"> - </p> - </dtml-if> - - <div align="center"><input type="submit" - name="manage_performRefresh:method" value="Refresh this product" /> - </div> - - <p> - <dtml-if auto_refresh_enabled> - <dtml-if devel_mode> - Auto refresh is enabled. Zope will repeatedly scan for - changes to the Python modules that make up this product and - execute a refresh when needed. - <dtml-else> - Although auto refresh is enabled, Zope is not in development - mode so auto refresh is not available. Use the "-D" argument - when starting Zope to enable development mode. - </dtml-if> - <dtml-else> - Auto refresh is disabled. Enable auto refresh - to cause Zope to frequently scan this product for changes. - Note that auto refresh can slow down Zope considerably - if enabled for more than a few products. - </dtml-if> - <br /> - <dtml-let checked="auto_refresh_enabled and 'checked' or ' '"> - <input type="checkbox" name="enable" value="1" &dtml-checked; /> - Auto refresh mode - <input type="submit" name="manage_enableAutoRefresh:method" - value="Change" /> - </dtml-let> - </p> - - <dtml-if auto_refresh_other> - <p>Select dependent auto-refreshable products to be refreshed - simultaneously.<br /> - <dtml-in auto_refresh_other sort> - <dtml-let checked="(_['sequence-item'] in dependent_products) and - 'checked' or ' '"> - <input type="checkbox" name="selections:list" - value="&dtml-sequence-item;" &dtml-checked; /> - </dtml-let> - </dtml-in> - <input type="submit" name="manage_selectDependentProducts:method" - value="Change" /> - </p> - </dtml-if> - - </td> - <td valign="top" class="row-hilite"> - - <p><b>Refreshable product modules:</b></p> - <ul> - <dtml-in loaded_modules sort> - <li>&dtml-sequence-item;</li> - </dtml-in> - </ul> - - </td> - </tr> - </table> - </form> -</dtml-if> - -<dtml-if manage_page_footer> - <dtml-var manage_page_footer> -<dtml-else> - </body></html> -</dtml-if> Deleted: Zope/trunk/src/App/dtml/traceback.dtml =================================================================== --- Zope/trunk/src/App/dtml/traceback.dtml 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/dtml/traceback.dtml 2011-07-02 18:08:30 UTC (rev 122065) @@ -1,8 +0,0 @@ -<dtml-var manage_page_header> -<dtml-var manage_tabs> - -<h3>Import Traceback</h3> - -<pre>&dtml-import_error_;</pre> - -<dtml-var manage_page_footer> Modified: Zope/trunk/src/App/tests/test_ApplicationManager.py =================================================================== --- Zope/trunk/src/App/tests/test_ApplicationManager.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/App/tests/test_ApplicationManager.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -350,11 +350,6 @@ am = self._makeOne() self.assertEqual(am.sys_platform(), sys.platform) - def test_ctor_initializes_Products(self): - from App.Product import ProductFolder - am = self._makeOne() - self.assertTrue(isinstance(am.Products, ProductFolder)) - def test__canCopy(self): am = self._makeOne() self.assertFalse(am._canCopy()) Modified: Zope/trunk/src/OFS/Application.py =================================================================== --- Zope/trunk/src/OFS/Application.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/OFS/Application.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -13,14 +13,11 @@ """Application support """ -import os, sys, traceback +import os, sys from logging import getLogger from cgi import escape -from StringIO import StringIO import Products -import App.Product -import App.ProductRegistry import transaction from AccessControl import ClassSecurityInfo from AccessControl.class_init import InitializeClass @@ -29,7 +26,6 @@ from App.ApplicationManager import ApplicationManager from App.config import getConfiguration from App import FactoryDispatcher -from App.Product import doInstall from DateTime import DateTime from HelpSys.HelpSys import HelpSys from OFS.metaconfigure import get_packages_to_initialize @@ -56,7 +52,6 @@ class Application(ApplicationDefaultPermissions, ZDOM.Root, Folder.Folder, - App.ProductRegistry.ProductRegistry, FindSupport, ): """Top-level system object""" @@ -292,7 +287,6 @@ global APP_MANAGER APP_MANAGER = ApplicationManager() APP_MANAGER._init() - APP_MANAGER.Products=App.Product.ProductFolder() app = self.getApp() app._p_activate() @@ -498,46 +492,33 @@ self.commit('Added virtual_hosting') def install_products(self): - app = self.getApp() - # this defers to a function for b/c reasons - return install_products(app) + return install_products() def install_standards(self): app = self.getApp() # this defers to a function for b/c reasons return install_standards(app) -def install_products(app): - # Install a list of products into the basic folder class, so - # that all folders know about top-level objects, aka products - +def install_products(app=None): folder_permissions = get_folder_permissions() - meta_types=[] - done={} - - debug_mode = getConfiguration().debug_mode - - transaction.get().note('Prior to product installs') - transaction.commit() - - products = get_products() - - for priority, product_name, index, product_dir in products: + meta_types = [] + done = {} + for priority, product_name, index, product_dir in get_products(): # For each product, we will import it and try to call the # intialize() method in the product __init__ module. If # the method doesnt exist, we put the old-style information # together and do a default initialization. - if done.has_key(product_name): + if product_name in done: continue - done[product_name]=1 + done[product_name] = 1 install_product(app, product_dir, product_name, meta_types, - folder_permissions, raise_exc=debug_mode) + folder_permissions) # Delayed install of packages-as-products for module, init_func in tuple(get_packages_to_initialize()): - install_package(app, module, init_func, raise_exc=debug_mode) + install_package(app, module, init_func) - Products.meta_types=Products.meta_types+tuple(meta_types) + Products.meta_types = Products.meta_types + tuple(meta_types) InitializeClass(Folder.Folder) def get_products(): @@ -564,68 +545,47 @@ products.sort() return products -def import_products(): - # Try to import each product, checking for and catching errors. - done={} - products = get_products() - debug_mode = getConfiguration().debug_mode - - for priority, product_name, index, product_dir in products: - if done.has_key(product_name): +def import_products(): + done = {} + for priority, product_name, index, product_dir in get_products(): + if product_name in done: LOG.warn('Duplicate Product name: ' 'After loading Product %s from %s, ' 'I skipped the one in %s.' % ( `product_name`, `done[product_name]`, `product_dir`) ) continue - done[product_name]=product_dir - import_product(product_dir, product_name, raise_exc=debug_mode) + done[product_name] = product_dir + import_product(product_dir, product_name) return done.keys() -def import_product(product_dir, product_name, raise_exc=0, log_exc=1): + +def import_product(product_dir, product_name, raise_exc=None): path_join=os.path.join isdir=os.path.isdir exists=os.path.exists - _st=type('') global_dict=globals() - silly=('__doc__',) modules=sys.modules - have_module=modules.has_key - try: - package_dir=path_join(product_dir, product_name) - if not isdir(package_dir): return - if not exists(path_join(package_dir, '__init__.py')): - if not exists(path_join(package_dir, '__init__.pyc')): - if not exists(path_join(package_dir, '__init__.pyo')): - return + package_dir = path_join(product_dir, product_name) + if not isdir(package_dir): + return - pname="Products.%s" % product_name - try: - product=__import__(pname, global_dict, global_dict, silly) - if hasattr(product, '__module_aliases__'): - for k, v in product.__module_aliases__: - if not have_module(k): - if type(v) is _st and have_module(v): v=modules[v] - modules[k]=v - except KeyboardInterrupt: - raise - except: - exc = sys.exc_info() - if log_exc: - LOG.error('Could not import %s' % pname, - exc_info=exc) - f=StringIO() - traceback.print_exc(100,f) - f=f.getvalue() - try: modules[pname].__import_error__=f - except: pass - if raise_exc: - raise exc[0], exc[1], exc[2] - finally: - exc = None + if not exists(path_join(package_dir, '__init__.py')): + if not exists(path_join(package_dir, '__init__.pyc')): + if not exists(path_join(package_dir, '__init__.pyo')): + return + pname = "Products.%s" % product_name + product = __import__(pname, global_dict, global_dict, ('__doc__', )) + if hasattr(product, '__module_aliases__'): + for k, v in product.__module_aliases__: + if k not in modules: + if isinstance(v, str) and v in modules: + v = modules[v] + modules[k] = v + def get_folder_permissions(): folder_permissions={} for p in Folder.Folder.__ac_permissions__: @@ -635,106 +595,57 @@ def install_product(app, product_dir, product_name, meta_types, - folder_permissions, raise_exc=0, log_exc=1): + folder_permissions, raise_exc=None): from App.ProductContext import ProductContext path_join=os.path.join isdir=os.path.isdir exists=os.path.exists global_dict=globals() - silly=('__doc__',) - if 1: # Preserve indentation for diff :-) - package_dir=path_join(product_dir, product_name) - __traceback_info__=product_name - if not isdir(package_dir): return - if not exists(path_join(package_dir, '__init__.py')): - if not exists(path_join(package_dir, '__init__.pyc')): - if not exists(path_join(package_dir, '__init__.pyo')): - return - try: - product=__import__("Products.%s" % product_name, - global_dict, global_dict, silly) + package_dir=path_join(product_dir, product_name) + __traceback_info__=product_name + if not isdir(package_dir): return + if not exists(path_join(package_dir, '__init__.py')): + if not exists(path_join(package_dir, '__init__.pyc')): + if not exists(path_join(package_dir, '__init__.pyo')): + return - # Install items into the misc_ namespace, used by products - # and the framework itself to store common static resources - # like icon images. - misc_=pgetattr(product, 'misc_', {}) - if misc_: - if isinstance(misc_, dict): - misc_=Misc_(product_name, misc_) - Application.misc_.__dict__[product_name]=misc_ + product=__import__("Products.%s" % product_name, + global_dict, global_dict, ('__doc__', )) - # Here we create a ProductContext object which contains - # information about the product and provides an interface - # for registering things like classes and help topics that - # should be associated with that product. Products are - # expected to implement a method named 'initialize' in - # their __init__.py that takes the ProductContext as an - # argument. - do_install = doInstall() - if do_install: - 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) + # Install items into the misc_ namespace, used by products + # and the framework itself to store common static resources + # like icon images. + misc_ = pgetattr(product, 'misc_', {}) + if misc_: + if isinstance(misc_, dict): + misc_=Misc_(product_name, misc_) + Application.misc_.__dict__[product_name]=misc_ - # Look for an 'initialize' method in the product. - initmethod = pgetattr(product, 'initialize', None) - if initmethod is not None: - initmethod(context) + productObject = FactoryDispatcher.Product(product_name) + context = ProductContext(productObject, None, product) - if do_install: - transaction.get().note('Installed product ' + product_name) - transaction.commit() + # Look for an 'initialize' method in the product. + initmethod = pgetattr(product, 'initialize', None) + if initmethod is not None: + initmethod(context) - except Exception: - if log_exc: - LOG.error('Couldn\'t install %s' % product_name, - exc_info=sys.exc_info()) - transaction.abort() - if raise_exc: - raise - -def install_package(app, module, init_func, raise_exc=False, log_exc=True): +def install_package(app, module, init_func, raise_exc=None): """Installs a Python package like a product.""" from App.ProductContext import ProductContext - try: - do_install = doInstall() - name = module.__name__ - if do_install: - product = App.Product.initializeProduct(module, - name, - module.__path__[0], - app) - else: - product = FactoryDispatcher.Product(name) - app = None + name = module.__name__ + product = FactoryDispatcher.Product(name) + product.package_name = name - product.package_name = name + if init_func is not None: + newContext = ProductContext(product, None, module) + init_func(newContext) - if init_func is not None: - newContext = ProductContext(product, app, module) - init_func(newContext) + package_initialized(module, init_func) - package_initialized(module, init_func) - if do_install: - transaction.get().note('Installed package %s' % module.__name__) - transaction.commit() - except Exception: - if log_exc: - LOG.error("Couldn't install %s" % module.__name__, - exc_info=True) - transaction.abort() - if raise_exc: - raise - - def install_standards(app): # Check to see if we've already done this before if getattr(app, '_standard_objects_have_been_added', 0): @@ -774,58 +685,16 @@ transaction.get().note('Installed standard objects') transaction.commit() -def reinstall_product(app, product_name): - folder_permissions = get_folder_permissions() - meta_types=[] - transaction.get().note('Prior to product reinstall') - transaction.commit() - - for product_dir in Products.__path__: - product_names=os.listdir(product_dir) - product_names.sort() - if product_name in product_names: - removeProductMetaTypes(product_name) - install_product(app, product_dir, product_name, meta_types, - folder_permissions, raise_exc=1, log_exc=0) - break - - Products.meta_types=Products.meta_types+tuple(meta_types) - InitializeClass(Folder.Folder) - - -def reimport_product(product_name): - for product_dir in Products.__path__: - product_names=os.listdir(product_dir) - product_names.sort() - if product_name in product_names: - import_product(product_dir, product_name, - raise_exc=1, log_exc=0) - break - - -def removeProductMetaTypes(pid): - """Unregisters the meta types registered by a product. - """ - meta_types = Products.meta_types - new_mts = [] - changed = 0 - for meta_type in meta_types: - if meta_type.get('product', None) == pid: - # Remove this meta type. - changed = 1 - else: - new_mts.append(meta_type) - if changed: - Products.meta_types = tuple(new_mts) - - def pgetattr(product, name, default=install_products, __init__=0): - if not __init__ and hasattr(product, name): return getattr(product, name) + if not __init__ and hasattr(product, name): + return getattr(product, name) if hasattr(product, '__init__'): product=product.__init__ - if hasattr(product, name): return getattr(product, name) + if hasattr(product, name): + return getattr(product, name) - if default is not install_products: return default + if default is not install_products: + return default - raise AttributeError, name + raise AttributeError(name) Modified: Zope/trunk/src/OFS/ObjectManager.py =================================================================== --- Zope/trunk/src/OFS/ObjectManager.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/OFS/ObjectManager.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -210,14 +210,6 @@ import Products external_candidates = [] - # Look at _product_meta_types, if there is one - _pmt=() - if hasattr(self, '_product_meta_types'): _pmt=self._product_meta_types - elif hasattr(self, 'aq_acquire'): - try: _pmt=self.aq_acquire('_product_meta_types') - except: pass - external_candidates.extend(list(_pmt)) - # Look at all globally visible meta types. for entry in getattr(Products, 'meta_types', ()): if ( (interfaces is not None) or (entry.get("visibility", None)=="Global") ): Modified: Zope/trunk/src/OFS/tests/testProductInit.py =================================================================== --- Zope/trunk/src/OFS/tests/testProductInit.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/OFS/tests/testProductInit.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -221,23 +221,11 @@ self.configure(cfg) app = getApp() from OFS.Application import install_products - install_products(app) + install_products() obids = app.Control_Panel.Products.keys() self.assertEquals(obids, []) - def test_install_products_enabled(self): - self.makeFakeProducts() - cfg2 = cfg + '\nenable-product-installation on' - self.configure(cfg2) - app = getApp() - from OFS.Application import install_products - install_products(app) - obids = app.Control_Panel.Products.keys() - for name in FAKEPRODUCTS: - self.assert_(name in obids) - - def test_suite(): suite = unittest.TestSuite() suite.addTest( unittest.makeSuite( TestProductInit ) ) Modified: Zope/trunk/src/OFS/tests/test_registerpackage.py =================================================================== --- Zope/trunk/src/OFS/tests/test_registerpackage.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/OFS/tests/test_registerpackage.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -51,9 +51,7 @@ >>> import Zope2 >>> from OFS.Application import install_products - - >>> app = Zope2.app() - >>> install_products(app) + >>> install_products() pythonproduct2 initialized Make sure it is registered: Modified: Zope/trunk/src/Testing/ZopeTestCase/ZopeLite.py =================================================================== --- Zope/trunk/src/Testing/ZopeTestCase/ZopeLite.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/Testing/ZopeTestCase/ZopeLite.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -176,11 +176,10 @@ if _patched and not _installedProducts.has_key(name): for priority, product_name, index, product_dir in get_products(): if product_name == name: - if not quiet: _print('Installing %s ... ' % product_name) - # We want to fail immediately if a product throws an exception - # during install, so we set the raise_exc flag. + if not quiet: + _print('Installing %s ... ' % product_name) install_product(_theApp, product_dir, product_name, meta_types, - get_folder_permissions(), raise_exc=1) + get_folder_permissions()) _installedProducts[product_name] = 1 Products.meta_types = Products.meta_types + tuple(meta_types) InitializeClass(Folder) @@ -207,10 +206,9 @@ if _patched and not _installedPackages.has_key(name): for module, init_func in get_packages_to_initialize(): if module.__name__ == name: - if not quiet: _print('Installing %s ... ' % module.__name__) - # We want to fail immediately if a package throws an exception - # during install, so we set the raise_exc flag. - install_package(_theApp, module, init_func, raise_exc=1) + if not quiet: + _print('Installing %s ... ' % module.__name__) + install_package(_theApp, module, init_func) _installedPackages[module.__name__] = 1 if not quiet: _print('done (%.3fs)\n' % (time.time() - start)) Modified: Zope/trunk/src/Zope2/App/startup.py =================================================================== --- Zope/trunk/src/Zope2/App/startup.py 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/Zope2/App/startup.py 2011-07-02 18:08:30 UTC (rev 122065) @@ -127,10 +127,6 @@ # Initialize the app object application = app() OFS.Application.initialize(application) - if getConfiguration().debug_mode: - # Set up auto-refresh. - from App.RefreshFuncs import setupAutoRefresh - setupAutoRefresh(application._p_jar) application._p_jar.close() # "Log off" as system user Modified: Zope/trunk/src/Zope2/Startup/zopeschema.xml =================================================================== --- Zope/trunk/src/Zope2/Startup/zopeschema.xml 2011-07-02 17:12:27 UTC (rev 122064) +++ Zope/trunk/src/Zope2/Startup/zopeschema.xml 2011-07-02 18:08:30 UTC (rev 122065) @@ -414,10 +414,7 @@ <key name="enable-product-installation" datatype="boolean" default="off"> <description> - If this directive is turned on, Zope performs 'product installation' - (the registration of Python modules in various Products directories) - at startup. Only turn this on if your code relies on the Products section - in the Control_Panel to be populated. + BBB: This directive has no effect anymore. </description> <metadefault>off</metadefault> </key> _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org https://mail.zope.org/mailman/listinfo/zope-checkins