[Checkins] SVN: z3ext.product/ initial import
Nikolay Kim
fafhrd at datacom.kz
Tue Mar 25 14:41:11 EDT 2008
Log message for revision 84940:
initial import
Changed:
A z3ext.product/
A z3ext.product/branches/
A z3ext.product/tags/
A z3ext.product/trunk/
A z3ext.product/trunk/AUTHOR.txt
A z3ext.product/trunk/CHANGES.txt
A z3ext.product/trunk/LICENSE.txt
A z3ext.product/trunk/bootstrap.py
A z3ext.product/trunk/buildout.cfg
A z3ext.product/trunk/setup.py
A z3ext.product/trunk/src/
A z3ext.product/trunk/src/z3ext/
A z3ext.product/trunk/src/z3ext/__init__.py
A z3ext.product/trunk/src/z3ext/product/
A z3ext.product/trunk/src/z3ext/product/README.txt
A z3ext.product/trunk/src/z3ext/product/__init__.py
A z3ext.product/trunk/src/z3ext/product/browser.zcml
A z3ext.product/trunk/src/z3ext/product/configure.zcml
A z3ext.product/trunk/src/z3ext/product/i18n.py
A z3ext.product/trunk/src/z3ext/product/installer.py
A z3ext.product/trunk/src/z3ext/product/interfaces.py
A z3ext.product/trunk/src/z3ext/product/meta.zcml
A z3ext.product/trunk/src/z3ext/product/product.py
A z3ext.product/trunk/src/z3ext/product/product_icon.gif
A z3ext.product/trunk/src/z3ext/product/registry.py
A z3ext.product/trunk/src/z3ext/product/tests.py
A z3ext.product/trunk/src/z3ext/product/utils.py
A z3ext.product/trunk/src/z3ext/product/view.pt
A z3ext.product/trunk/src/z3ext/product/view.py
A z3ext.product/trunk/src/z3ext/product/zcml.py
-=-
Property changes on: z3ext.product/trunk
___________________________________________________________________
Name: svn:ignore
+ bin
coverage
develop-eggs
eggs
parts
.installed.cfg
Added: z3ext.product/trunk/AUTHOR.txt
===================================================================
--- z3ext.product/trunk/AUTHOR.txt (rev 0)
+++ z3ext.product/trunk/AUTHOR.txt 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1 @@
+Nikolay Kim (fafhrd91 <at> gmail <dot> com)
Added: z3ext.product/trunk/CHANGES.txt
===================================================================
--- z3ext.product/trunk/CHANGES.txt (rev 0)
+++ z3ext.product/trunk/CHANGES.txt 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,47 @@
+=======
+CHANGES
+=======
+
+1.0.0 (2008-03-26)
+------------------
+
+- Tests added
+
+- Code moved to svn.zope.org
+
+
+0.11.1 (2008-03-04)
+-------------------
+
+- Added 'broken' base registry in case product not available.
+
+
+0.11 (2008-02-28)
+-----------------
+
+- Use z3c.baseregistry
+
+- Use z3c.autoinclude
+
+- Create components registry for each product.
+ now it's possible to use <registerIn registry="z3ext.product.productName'/>
+ for registering product adapters and utulities.
+
+
+0.10.2 (2008-02-18)
+------------------
+
+- Don't show 'Products Management' configlet
+ if there are no installable products
+
+
+0.10.1 (2008-02-01)
+------------------
+
+- Removed `grant` directives
+
+
+0.10 (2008-02-01)
+------------------
+
+- Initial release
Added: z3ext.product/trunk/LICENSE.txt
===================================================================
--- z3ext.product/trunk/LICENSE.txt (rev 0)
+++ z3ext.product/trunk/LICENSE.txt 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,54 @@
+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.
Added: z3ext.product/trunk/bootstrap.py
===================================================================
--- z3ext.product/trunk/bootstrap.py (rev 0)
+++ z3ext.product/trunk/bootstrap.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 1839 2008-03-25 13:28:26Z fafhrd91 $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+ ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+ cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+ os.P_WAIT, sys.executable, sys.executable,
+ '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+ dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)
Added: z3ext.product/trunk/buildout.cfg
===================================================================
--- z3ext.product/trunk/buildout.cfg (rev 0)
+++ z3ext.product/trunk/buildout.cfg 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,18 @@
+[buildout]
+develop = .
+parts = test coverage-test coverage-report
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3ext.product [test]
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = z3ext.product [test]
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')
Added: z3ext.product/trunk/setup.py
===================================================================
--- z3ext.product/trunk/setup.py (rev 0)
+++ z3ext.product/trunk/setup.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,77 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""Setup for z3ext.product package
+
+$Id: setup.py 1842 2008-03-25 16:41:22Z fafhrd91 $
+"""
+import sys, os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+ return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+version = '1.0.0dev'
+
+
+setup(name='z3ext.product',
+ version=version,
+ description="Implementation of product (add-on) concept.",
+ long_description=(
+ 'Detailed Documentation\n' +
+ '======================\n'
+ + '\n\n' +
+ read('src', 'z3ext', 'product', 'README.txt')
+ + '\n\n' +
+ read('CHANGES.txt')
+ ),
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Zope Public License',
+ 'Programming Language :: Python',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Framework :: Zope3'],
+ author='Nikolay Kim',
+ author_email='fafhrd91 at gmail.com',
+ url='http://z3ext.net/',
+ license='ZPL 2.1',
+ packages=find_packages('src'),
+ package_dir = {'':'src'},
+ namespace_packages=['z3ext'],
+ install_requires = ['setuptools',
+ 'ZODB3',
+ 'zope.schema',
+ 'zope.component',
+ 'zope.interface',
+ 'zope.security',
+ 'zope.i18nmessageid',
+ 'zope.lifecycleevent',
+ 'zope.configuration',
+ 'zope.app.component',
+ 'z3c.baseregistry',
+ 'z3c.configurator',
+ 'z3c.autoinclude',
+ 'z3ext.layout',
+ 'z3ext.controlpanel',
+ 'z3ext.statusmessage',
+ ],
+ extras_require = dict(test=['zope.app.testing',
+ 'zope.testing',
+ ]),
+ include_package_data = True,
+ zip_safe = False
+ )
Property changes on: z3ext.product/trunk/setup.py
___________________________________________________________________
Name: svn:executable
+ *
Added: z3ext.product/trunk/src/z3ext/__init__.py
===================================================================
--- z3ext.product/trunk/src/z3ext/__init__.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/__init__.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,6 @@
+# namespace package boilerplate
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError, e:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
Added: z3ext.product/trunk/src/z3ext/product/README.txt
===================================================================
--- z3ext.product/trunk/src/z3ext/product/README.txt (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/README.txt 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,274 @@
+=================
+Products (Add-on)
+=================
+
+Products system based on z3c.baseregistry package. This package
+simplify creating and managing registries.
+
+Loading zcml configuration
+
+ >>> import z3ext.product
+ >>> from zope.configuration import xmlconfig
+ >>> context = xmlconfig.string("""
+ ... <configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
+ ... xmlns="http://namespaces.zope.org/zope" i18n_domain="z3ext">
+ ... <include package="z3ext.controlpanel" file="meta.zcml" />
+ ... <include package="z3ext.product" file="meta.zcml" />
+ ... <include package="zope.security" file="meta.zcml" />
+ ... <include package="z3c.baseregistry" file="meta.zcml" />
+ ...
+ ... <permission
+ ... id="z3ext.ManageProducts"
+ ... title="Manage products" />
+ ...
+ ... <z3ext:configlet
+ ... name="product"
+ ... schema="z3ext.product.interfaces.IProductInstaller"
+ ... title="Products management"
+ ... description="This is the Add-on Products install section."
+ ... class="z3ext.product.installer.ProductsInstaller"
+ ... permission="z3ext.ManageProducts" />
+ ...
+ ... </configure>""")
+
+ >>> from zope import component
+ >>> from z3ext.controlpanel.interfaces import IConfiglet
+
+ >>> installer = component.getUtility(IConfiglet, 'product')
+ >>> installer.keys()
+ ()
+
+ >>> installer.isAvailable()
+ False
+
+ >>> from zope import schema, interface
+
+ >>> class IMyProduct(interface.Interface):
+ ... """ Basic product """
+ ...
+ ... email = schema.TextLine(
+ ... title=u"E-mail Address",
+ ... description=u"E-mail Address used to send notifications")
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns:z3ext="http://namespaces.zope.org/z3ext" i18n_domain="test">
+ ...
+ ... <z3ext:product
+ ... name="my-product"
+ ... title="My product"
+ ... configurable="true"
+ ... schema="z3ext.product.README.IMyProduct" />
+ ...
+ ... </configure>''', context)
+
+After registration we can get product declaration by it's schema.
+
+ >>> from z3ext.product.interfaces import IProduct
+
+ >>> product = component.getUtility(IMyProduct)
+ >>> product
+ <z3ext.controlpanel.configlettype.Configlet<product.my-product> ...>
+
+ >>> product.__title__
+ u'My product'
+
+ >>> IMyProduct.providedBy(product)
+ True
+
+Or we can get product by it's name
+
+ >>> component.getUtility(IProduct, 'my-product') is product
+ True
+
+But product is also is configlet, configlet name is 'product.' prefix
+and product name
+
+ >>> configlet = component.getUtility(IConfiglet, 'product.my-product')
+ >>> configlet
+ <z3ext.controlpanel.configlettype.Configlet<product.my-product> ...>
+
+ >>> configlet is product
+ True
+
+
+Product manipulation
+--------------------
+
+instalation status
+
+ >>> product.isInstalled()
+ False
+
+or
+
+ >>> product.__installed__
+ False
+
+instalation
+
+ >>> product.install()
+ >>> product.__installed__
+ True
+
+ >>> product.install()
+ Traceback (most recent call last):
+ ...
+ ProductAlreadyInstalledError: Product already installed.
+
+
+updateing product
+
+ >>> product.update()
+
+uninstall
+
+ >>> product.uninstall()
+ >>> product.__installed__
+ False
+
+we can't uninstall or update not installed product
+
+ >>> product.uninstall()
+ Traceback (most recent call last):
+ ...
+ ProductNotInstalledError: Product not installed.
+
+ >>> product.update()
+ Traceback (most recent call last):
+ ...
+ ProductNotInstalledError: Product not installed.
+
+
+Product extension
+-----------------
+
+We can create product extension
+
+ >>> class IMyProductExtension(interface.Interface):
+ ... """Basic User Preferences"""
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns:z3ext="http://namespaces.zope.org/z3ext" i18n_domain="test">
+ ...
+ ... <z3ext:product
+ ... name="my-product.ext"
+ ... title="Product extension"
+ ... schema="z3ext.product.README.IMyProductExtension" />
+ ...
+ ... </configure>''', context)
+
+ >>> ext = component.getUtility(IMyProductExtension)
+ >>> ext
+ <z3ext.controlpanel.configlettype.Configlet<product.my-product.ext> ...>
+
+ >>> ext.__installed__
+ False
+
+ >>> ext.isInstalled()
+ False
+
+ >>> component.getUtility(IProduct, 'my-product.ext') is ext
+ True
+
+ >>> component.getUtility(IConfiglet, 'product.my-product.ext') is ext
+ True
+
+We have to install product first, then we can install product extension
+
+ >>> ext.install()
+ Traceback (most recent call last):
+ ...
+ ProductNotInstalledError: my-product
+
+ >>> ext.update()
+ Traceback (most recent call last):
+ ...
+ ProductNotInstalledError: my-product
+
+ >>> product.install()
+ >>> ext.install()
+
+ >>> ext = component.getUtility(IMyProductExtension)
+ >>> ext.__installed__
+ True
+
+ >>> ext.isInstalled()
+ True
+
+ >>> ext.update()
+
+ >>> ext.uninstall()
+ >>> ext.__installed__
+ False
+
+If we uninstall product, extension will uninstall also
+
+ >>> ext.install()
+ >>> product.uninstall()
+ >>> ext.__installed__
+ False
+
+ >>> product.listExtensions()
+ [u'ext']
+
+
+Component registry
+------------------
+
+When we register product, system automaticly creates component registry
+
+ >>> registry = z3ext.product.registries['my-product']
+
+ >>> print registry
+ Product: My product
+
+ >>> repr(registry)
+ '<Product: My product>'
+
+ >>> component.interfaces.IComponents.providedBy(registry)
+ True
+
+When we install product, product's component registry automaticly
+added to current site manager bases.
+
+ >>> component.getSiteManager().__bases__
+ (<BaseGlobalComponents base>,)
+
+ >>> product.install()
+
+ >>> component.getSiteManager().__bases__
+ (<Product: My product>, <BaseGlobalComponents base>)
+
+ >>> product.uninstall()
+ >>> component.getSiteManager().__bases__
+ (<BaseGlobalComponents base>,)
+
+With z3c.baseregistry it's possible to use <registerIn />
+directive. For example:
+
+<registerIn registry="z3ext.product.my-product>
+ ... various declarations
+</registerIn>
+
+
+Product configlet
+-----------------
+
+ >>> installer = component.getUtility(IConfiglet, 'product')
+ >>> installer.keys()
+ (u'my-product',)
+
+ >>> installer.isAvailable()
+ True
+
+ >>> installer['my-product'] is product
+ True
+
+ >>> product.isAvailable()
+ False
+
+ >>> product.install()
+ >>> product.isAvailable()
+ True
Added: z3ext.product/trunk/src/z3ext/product/__init__.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/__init__.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/__init__.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,5 @@
+# This file is necessary to make this directory a package.
+
+registries = {}
+
+from z3ext.product.product import Product, ProductExtension
Added: z3ext.product/trunk/src/z3ext/product/browser.zcml
===================================================================
--- z3ext.product/trunk/src/z3ext/product/browser.zcml (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/browser.zcml 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,40 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:z3ext="http://namespaces.zope.org/z3ext"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="z3ext.product">
+
+ <browser:icon
+ name="zmi_icon"
+ title="Product"
+ for=".interfaces.IProduct"
+ file="product_icon.gif" />
+
+ <browser:icon
+ name="zmi_icon"
+ title="Products management"
+ for=".interfaces.IProductInstaller"
+ file="product_icon.gif" />
+
+ <browser:icon
+ name="zmi_icon"
+ title="Product extension"
+ for=".interfaces.IProductExtension"
+ file="product_icon.gif" />
+
+ <z3ext:pagelet
+ name="index.html"
+ for=".interfaces.IProductInstaller"
+ template="view.pt"
+ class=".view.InstallerView"
+ permission="z3ext.ManageProducts" />
+
+ <browser:menuItem
+ for=".interfaces.IProductInstaller"
+ menu="zmi_views"
+ title="Products management"
+ action="@@index.html"
+ permission="z3ext.ManageProducts"
+ order="1" />
+
+</configure>
Added: z3ext.product/trunk/src/z3ext/product/configure.zcml
===================================================================
--- z3ext.product/trunk/src/z3ext/product/configure.zcml (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/configure.zcml 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,23 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:zcml="http://namespaces.zope.org/zcml"
+ xmlns:z3ext="http://namespaces.zope.org/z3ext"
+ i18n_domain="z3ext.product">
+
+ <autoinclude package="z3ext.product" />
+
+ <permission
+ id="z3ext.ManageProducts"
+ title="Manage products" />
+
+ <z3ext:configlet
+ name="product"
+ schema=".interfaces.IProductInstaller"
+ title="Products management"
+ description="This is the Add-on Products install section."
+ class=".installer.ProductsInstaller"
+ permission="z3ext.ManageProducts" />
+
+ <include file="browser.zcml" />
+
+</configure>
Added: z3ext.product/trunk/src/z3ext/product/i18n.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/i18n.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/i18n.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,19 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id: interfaces.py 860 2008-01-09 08:48:08Z fafhrd91 $
+"""
+from zope.i18nmessageid import MessageFactory
+_ = MessageFactory('z3ext')
Added: z3ext.product/trunk/src/z3ext/product/installer.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/installer.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/installer.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id: installer.py 1472 2008-02-18 11:35:13Z fafhrd91 $
+"""
+from zope import interface
+from z3ext.controlpanel.interfaces import IConfiglet
+
+
+class ProductsInstaller(object):
+
+ def isAvailable(self):
+ if not len(self):
+ return False
+
+ return super(ProductsInstaller, self).isAvailable()
Added: z3ext.product/trunk/src/z3ext/product/interfaces.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/interfaces.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/interfaces.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,116 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+""" z3ext.product interfaces
+
+$Id: interfaces.py 1843 2008-03-25 18:39:00Z fafhrd91 $
+"""
+from zope import schema, interface
+
+
+class ProductError(Exception):
+ """ base error class for product management """
+
+
+class ProductNotInstalledError(ProductError):
+ """ """
+
+
+class ProductAlreadyInstalledError(ProductError):
+ """ """
+
+
+class InvalidProduct(ProductError):
+ """ """
+
+
+class ProductWarningError(ProductError):
+ """ dependencies error """
+
+
+class IProduct(interface.Interface):
+ """ product information """
+
+ __product_name__ = schema.TextLine(
+ title = u'Product name',
+ required = True)
+
+ __installed__ = schema.Bool(
+ title = u'Installed',
+ description = u'Is product installed.',
+ default = False,
+ required = False)
+
+ def install():
+ """ install and configure product """
+
+ def uninstall():
+ """ uninstall product """
+
+ def update():
+ """ update product """
+
+ def isInstalled():
+ """ is product installed """
+
+ def listExtensions():
+ """ list IProductExtension for this product """
+
+
+class IProductExtension(interface.Interface):
+ """ product extension """
+
+
+class IProductInstaller(interface.Interface):
+ """ installer for external products """
+
+
+class IAbstractProductEvent(interface.Interface):
+ """ base event interface """
+
+ id = schema.TextLine(
+ title = u'Product id',
+ required = True)
+
+ product = interface.Attribute('IProduct object')
+
+
+class IProductInstalledEvent(IAbstractProductEvent):
+ """ new product installed """
+
+
+class IProductUninstalledEvent(IAbstractProductEvent):
+ """ product uninstalled """
+
+
+class IProductUpdatedEvent(IAbstractProductEvent):
+ """ product updated """
+
+
+class AbstractProductEvent(object):
+
+ def __init__(self, id, product):
+ self.id = id
+ self.product = product
+
+
+class ProductInstalledEvent(AbstractProductEvent):
+ interface.implements(IProductInstalledEvent)
+
+
+class ProductUninstalledEvent(AbstractProductEvent):
+ interface.implements(IProductUninstalledEvent)
+
+
+class ProductUpdatedEvent(AbstractProductEvent):
+ interface.implements(IProductUpdatedEvent)
Added: z3ext.product/trunk/src/z3ext/product/meta.zcml
===================================================================
--- z3ext.product/trunk/src/z3ext/product/meta.zcml (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/meta.zcml 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,21 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:meta="http://namespaces.zope.org/meta">
+
+ <meta:directives namespace="http://namespaces.zope.org/z3ext">
+ <meta:complexDirective
+ name="product"
+ schema=".zcml.IProductDirective"
+ handler=".zcml.ProductDirective">
+
+ <meta:subdirective
+ name="allow"
+ schema="zope.app.component.metadirectives.IAllowSubdirective" />
+
+ <meta:subdirective
+ name="require"
+ schema="zope.app.component.metadirectives.IRequireSubdirective" />
+ </meta:complexDirective>
+ </meta:directives>
+
+</configure>
Added: z3ext.product/trunk/src/z3ext/product/product.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/product.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/product.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,124 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id: product.py 1843 2008-03-25 18:39:00Z fafhrd91 $
+"""
+from BTrees.OOBTree import OOBTree
+
+from zope import interface, event
+from zope.component import getSiteManager
+from zope.component import getUtility, queryUtility, getUtilitiesFor
+
+from z3c.configurator import configure
+
+import z3ext.product
+from z3ext.controlpanel.configlettype import ConfigletProperty
+
+from z3ext.product.i18n import _
+from z3ext.product import interfaces
+from z3ext.product.interfaces import IProduct, IProductExtension
+
+
+class Product(object):
+ """ base product class """
+ interface.implements(IProduct)
+
+ __installed__ = ConfigletProperty(IProduct['__installed__'])
+
+ def install(self):
+ if self.__installed__:
+ raise interfaces.ProductAlreadyInstalledError(
+ _('Product already installed.'))
+
+ self.__installed__ = True
+ self.update()
+
+ sm = getSiteManager()
+
+ registry = getattr(z3ext.product, self.__product_name__)
+ if registry not in sm.__bases__:
+ sm.__bases__ = (registry,) + sm.__bases__
+
+ event.notify(interfaces.ProductInstalledEvent(self.__product_name__, self))
+
+ def update(self):
+ if not self.__installed__:
+ raise interfaces.ProductNotInstalledError(
+ _('Product not installed.'))
+
+ configure(self, {})
+
+ site = getSiteManager()
+ registry = getattr(z3ext.product, self.__product_name__)
+ if registry not in site.__bases__:
+ site.__bases__ = (registry,) + site.__bases__
+
+ event.notify(interfaces.ProductUpdatedEvent(
+ self.__product_name__, self))
+
+ def uninstall(self):
+ for name, ext in self.items():
+ if IProductExtension.providedBy(ext) and ext.__installed__:
+ ext.uninstall()
+
+ if not self.__installed__:
+ raise interfaces.ProductNotInstalledError(
+ _('Product not installed.'))
+
+ self.__installed__ = False
+
+ site = getSiteManager()
+ registry = getattr(z3ext.product, self.__product_name__)
+
+ if registry in site.__bases__:
+ bases = list(site.__bases__)
+ bases.remove(registry)
+ site.__bases__ = tuple(bases)
+
+ event.notify(interfaces.ProductUninstalledEvent(
+ self.__product_name__, self))
+
+ def isInstalled(self):
+ return self.__installed__
+
+ def listExtensions(self):
+ exts = []
+ for name, ext in self.items():
+ if IProductExtension.providedBy(ext):
+ exts.append(name)
+
+ return exts
+
+
+class ProductExtension(Product):
+ interface.implements(IProductExtension)
+
+ def install(self):
+ if not self.__parent__.__installed__:
+ raise interfaces.ProductNotInstalledError(
+ self.__parent__.__product_name__)
+ super(ProductExtension, self).install()
+
+ def update(self):
+ if not self.__parent__.__installed__:
+ raise interfaces.ProductNotInstalledError(
+ self.__parent__.__product_name__)
+ super(ProductExtension, self).update()
+
+ def isInstalled(self):
+ if self.__parent__.__installed__:
+ return self.__installed__
+ else:
+ return False
Added: z3ext.product/trunk/src/z3ext/product/product_icon.gif
===================================================================
(Binary files differ)
Property changes on: z3ext.product/trunk/src/z3ext/product/product_icon.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: z3ext.product/trunk/src/z3ext/product/registry.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/registry.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/registry.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id: 2007-12-12 12:27:02Z fafhrd $
+"""
+from zope.component import queryUtility
+from zope.component.interfaces import IComponents
+from zope.component import globalregistry, globalSiteManager
+
+import z3ext.product
+from z3ext.product.i18n import _
+
+
+def BC(components, name):
+ bc = getattr(z3ext.product, name, None)
+ if bc is None:
+ return broken
+ else:
+ return bc
+
+
+class ProductRegistry(globalregistry.BaseGlobalComponents):
+
+ def __init__(self, name, title):
+ self.title = title
+ self.__name__ = name
+ self.__parent__ = globalSiteManager
+ super(ProductRegistry, self).__init__(name)
+
+ def __str__(self):
+ return "Product: %s"%self.title
+
+ def __repr__(self):
+ return "<Product: %s>"%self.title
+
+ def __reduce__(self):
+ # Global site managers are pickled as global objects
+ return BC, (self.__parent__, self.__name__)
+
+
+class BrokenProductRegistry(globalregistry.BaseGlobalComponents):
+
+ def __init__(self):
+ self.__parent__ = globalSiteManager
+ super(BrokenProductRegistry, self).__init__('broken')
+
+ def __repr__(self):
+ return _("Product: Broken product!!!")
+
+
+broken = BrokenProductRegistry()
Added: z3ext.product/trunk/src/z3ext/product/tests.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/tests.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/tests.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,38 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id: tests.py 84833 2008-03-21 09:09:54Z fafhrd $
+"""
+import unittest, doctest
+from zope.component import testing
+from zope.app.testing import setup
+from z3ext.controlpanel.testing import setUpControlPanel
+
+def setUp(test):
+ setup.placefulSetUp(True)
+ setup.setUpTestAsModule(test, 'z3ext.product.README')
+ setUpControlPanel()
+
+def tearDown(test):
+ setup.placefulTearDown()
+ setup.tearDownTestAsModule(test)
+
+def test_suite():
+ return unittest.TestSuite((
+ doctest.DocFileSuite(
+ 'README.txt',
+ setUp=setUp, tearDown=tearDown,
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
+ ))
Added: z3ext.product/trunk/src/z3ext/product/utils.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/utils.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/utils.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,98 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id: utils.py 1839 2008-03-25 13:28:26Z fafhrd91 $
+"""
+from zope import interface, event, component
+from zope.component import queryUtility
+from zope.lifecycleevent import ObjectCreatedEvent
+from zope.security.proxy import removeSecurityProxy
+
+from zope.app.component.hooks import getSite
+from zope.app.component.site import SiteManagementFolder
+from zope.app.component.interfaces import ISite
+
+from z3ext.product.i18n import _
+from z3ext.product.interfaces import IProduct, IProductExtension
+
+
+def registerUtility(id, factory, ifaces, container='system'):
+ site = getSite()
+ if not ISite.providedBy(site):
+ raise RuntimeError(_("Can't create utility."))
+
+ sm = component.getSiteManager()
+
+ if isinstance(container, basestring):
+ if container:
+ if container not in sm:
+ folder = SiteManagementFolder()
+ event.notify(ObjectCreatedEvent(folder))
+ sm[container] = folder
+
+ container = sm[container]
+ else:
+ container = sm
+ elif container is None:
+ container = sm
+
+ if id not in container:
+ if callable(factory):
+ utility = factory()
+ else:
+ utility = component.createObject(factory)
+
+ event.notify(ObjectCreatedEvent(utility))
+ removeSecurityProxy(container)[id] = utility
+
+ for iface, name in ifaces:
+ sm.registerUtility(utility, iface, name)
+
+ return container[id]
+
+
+def unregisterUtility(id, ifaces, container='system'):
+ site = getSite()
+ sm = component.getSiteManager()
+
+ if container not in sm:
+ return
+
+ container = sm[container]
+
+ if id in container:
+ utility = container[id]
+
+ for iface, name in ifaces:
+ sm.unregisterUtility(utility, iface, name)
+
+ del container[id]
+
+
+class ProductTest(object):
+
+ def __init__(self, product):
+ self.product = product
+
+ def __call__(self, *args, **kw):
+ product = queryUtility(IProduct, self.product)
+ if product is not None:
+ return product.__installed__
+
+ product = queryUtility(IProductExtension, self.product)
+ if product is not None:
+ return product.__installed__
+
+ return False
Added: z3ext.product/trunk/src/z3ext/product/view.pt
===================================================================
--- z3ext.product/trunk/src/z3ext/product/view.pt (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/view.pt 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,86 @@
+<div i18n:domain="z3ext.product" tal:define="data view/getProducts">
+ <div class="topframe" tal:condition="data/installed">
+ <h1>Installed Products</h1>
+
+ <form tal:attributes="action request/URL" method="post">
+ <ul class="listing">
+ <li tal:repeat="product data/installed">
+ <div class="icon">
+ <input class="noborder" type="checkbox"
+ name="products:list" tal:attributes="value product/name" />
+ <img tal:replace="structure product/product/@@zmi_icon" />
+ </div>
+ <div class="details">
+ <a tal:omit-tag="not:product/configlet"
+ tal:attributes="href string:${product/name}/">
+ <span tal:content="product/title"></span>
+ </a>
+ <div tal:content="product/description"></div>
+ </div>
+ <div class="small"
+ tal:define="name product/name;
+ extensions python:view.getExtensions(product['product'])"
+ tal:condition="extensions">
+ <ul class="listing">
+ <li tal:repeat="product extensions">
+ <div class="icon">
+ <img tal:replace="structure product/@@zmi_icon" />
+ </div>
+ <div class="details">
+ <span>
+ <a tal:omit-tag="not:product/isAvailable"
+ tal:attributes="href string:${product/__parent__/__name__}/${product/__name__}/">
+ <span tal:content="product/__title__"></span>
+ </a>
+ <a tal:attributes="href
+ string:${context/@@absolute_url}/?extension=${product/__id__}"
+ tal:condition="product/__installed__">
+ (Installed)
+ </a>
+ <a tal:attributes="href
+ string:${context/@@absolute_url}/?extension=${product/__id__}"
+ tal:condition="not:product/__installed__">
+ (Not installed)
+ </a>
+ </span>
+ <div tal:content="product/__description__"></div>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </li>
+ </ul>
+
+ <div class="formControls">
+ <input type="submit" class="z-form-button" name="update" value="Update" />
+ <input type="submit" class="z-form-removebutton" name="uninstall" value="Uninstall" />
+ </div>
+ </form>
+ </div>
+
+ <div class="frame" tal:condition="data/notinstalled"
+ tal:attributes="class python:not data['installed'] and 'topframe' or 'frame'">
+ <h1>Products available for install</h1>
+ <p>This is the Add-on Products install section, you can add products in the lists below.</p>
+
+ <form tal:attributes="action request/URL" method="post">
+ <ul class="listing">
+ <li tal:repeat="product data/notinstalled">
+ <div class="icon">
+ <input class="noborder" type="checkbox"
+ name="products:list" tal:attributes="value product/name" />
+ <img tal:replace="structure product/product/@@zmi_icon" />
+ </div>
+ <div class="details">
+ <span tal:content="product/title"></span>
+ <div tal:content="product/description"></div>
+ </div>
+ </li>
+ </ul>
+
+ <div class="formControls">
+ <input type="submit" class="context" name="install" value="Install" />
+ </div>
+ </form>
+ </div>
+</div>
Added: z3ext.product/trunk/src/z3ext/product/view.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/view.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/view.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,150 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+""" z3ext.product interfaces
+
+$Id: view.py 1839 2008-03-25 13:28:26Z fafhrd91 $
+"""
+import logging, sys
+from transaction import abort
+from zope.component import getUtility, queryUtility, getUtilitiesFor
+
+from z3ext.layout.pagelet import BrowserPagelet
+from z3ext.statusmessage.interfaces import IStatusMessage
+
+from z3ext.product.i18n import _
+from z3ext.product.interfaces import IProductExtension
+from z3ext.product.interfaces import ProductWarningError
+
+def log_exc(msg=''):
+ log = logging.getLogger(u'z3ext.product')
+ log.log(logging.ERROR, msg, exc_info=sys.exc_info())
+
+
+class InstallerView(BrowserPagelet):
+
+ def getProducts(self):
+ context = self.context
+
+ installed = []
+ notinstalled = []
+
+ for name, product in context.items():
+ info = {'name': name,
+ 'product': product,
+ 'title': product.__title__,
+ 'description': product.__description__}
+
+ if product.__installed__:
+ info['configlet'] = product.isAvailable()
+ installed.append((product.__title__, info))
+ else:
+ notinstalled.append((product.__title__, info))
+
+ installed.sort()
+ installed = [info for t, info in installed]
+
+ notinstalled.sort()
+ notinstalled = [info for t, info in notinstalled]
+
+ return {'installed': installed, 'notinstalled': notinstalled}
+
+ def getExtensions(self, product):
+ extensions = []
+
+ for name in product.listExtensions():
+ ext = product.get(name)
+ extensions.append((ext.__title__, ext))
+ extensions.sort()
+ return [ext for t, ext in extensions]
+
+ def update(self, *args, **kw):
+ request = self.request
+ context = self.context
+
+ service = IStatusMessage(request)
+ products = request.get('products', ())
+
+ if request.has_key('install'):
+ if not products:
+ service.add(_('Select one or more products to install.'), 'warning')
+ else:
+ try:
+ for product_id in products:
+ product = context.get(product_id)
+ product.install()
+
+ service.add(_('Selected products has been installed.'))
+ except ProductWarningError, e:
+ abort()
+ service.add(unicode(e), 'warning')
+ except Exception, e:
+ abort()
+ log_exc(str(e))
+ service.add(e, 'error')
+
+ elif request.has_key('update'):
+ if not products:
+ service.add(_('Select one or more products to update.'), 'warning')
+ else:
+ try:
+ for product_id in products:
+ product = context.get(product_id)
+ product.update()
+
+ service.add('Selected products has been updated.')
+ except Exception, e:
+ abort()
+ log_exc(str(e))
+ service.add(e, 'error')
+
+ elif request.has_key('uninstall'):
+ if not products:
+ service.add(_('Select one or more products to uninstall.'), 'warning')
+ else:
+ try:
+ for product_id in products:
+ product = context.get(product_id)
+ product.uninstall()
+
+ service.add(_('Selected products has been uninstalled.'))
+ except Exception, e:
+ abort()
+ log_exc(str(e))
+ service.add(e, 'error')
+
+ elif request.has_key('extension'):
+ try:
+ product = ''
+ extension = request.get('extension', '')
+ if '.' in extension:
+ c, product, extension = extension.split('.', 2)
+
+ product = context.get(product)
+ if product is not None:
+ extension = product.get(extension)
+
+ if not IProductExtension.providedBy(extension):
+ extension = None
+
+ if extension is None:
+ service.add("Can't fine extension.", 'error')
+ else:
+ if extension.__installed__:
+ extension.uninstall()
+ else:
+ extension.install()
+ except Exception, e:
+ abort()
+ log_exc(str(e))
+ service.add(e, 'error')
Added: z3ext.product/trunk/src/z3ext/product/zcml.py
===================================================================
--- z3ext.product/trunk/src/z3ext/product/zcml.py (rev 0)
+++ z3ext.product/trunk/src/z3ext/product/zcml.py 2008-03-25 18:41:11 UTC (rev 84940)
@@ -0,0 +1,95 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+""" z3ext:product directive
+
+$Id: interfaces.py 802 2007-12-28 11:25:55Z fafhrd91 $
+"""
+from zope import schema
+from zope.configuration import fields
+from zope.component.zcml import utility
+from zope.component import globalSiteManager
+from zope.component.interfaces import IComponents
+from zope.security.checker import CheckerPublic
+
+import z3ext.product
+from z3ext.controlpanel.zcml import IConfigletDirective, ConfigletDirective
+
+from interfaces import IProduct
+from registry import ProductRegistry
+from product import Product, ProductExtension
+
+
+class IProductDirective(IConfigletDirective):
+
+ configurable = schema.Bool(
+ title = u'Configurable',
+ default = False,
+ required = False)
+
+
+class ProductDirective(ConfigletDirective):
+
+ def __init__(self, _context, name, schema, title,
+ description='', class_=None, provides=(),
+ permission='z3ext.ManageProducts', tests=(), configurable=False):
+
+ if '.' not in name:
+ product_class = Product
+ else:
+ product_class = ProductExtension
+
+ if class_ is None:
+ class_ = product_class
+ else:
+ class_ = (class_, product_class)
+
+ if configurable:
+ test = ProductTest()
+ tests = (test,) + tuple(tests)
+ else:
+ tests = (False,)
+
+ # create component registry
+ registry = ProductRegistry(name, title)
+ z3ext.product.registries[name] = registry
+ setattr(z3ext.product, name, registry)
+ utility(_context, IComponents, registry, name=name)
+
+ # register configlet
+ productName = name
+ name = 'product.' + name
+
+ super(ProductDirective, self).__init__(
+ _context, name, schema, title,
+ description, class_, provides, permission, tests)
+
+ self._class.__product_name__ = productName
+
+ if configurable:
+ test.product = self._configlet
+
+ utility(_context, IProduct, self._configlet, name=productName)
+
+ self.require(_context, permission, interface=(IProduct,))
+ self.require(_context, CheckerPublic,
+ attributes=('isInstalled', '__installed__'))
+
+
+class ProductTest(object):
+
+ def __init__(self, product=None):
+ self.product = product
+
+ def __call__(self, *args, **kw):
+ return self.product.isInstalled()
More information about the Checkins
mailing list