[Checkins] SVN: z3ext.controlpanel/ initial import

Nikolay Kim fafhrd at datacom.kz
Fri Mar 21 05:09:54 EDT 2008


Log message for revision 84833:
  initial import

Changed:
  A   z3ext.controlpanel/
  A   z3ext.controlpanel/branches/
  A   z3ext.controlpanel/tags/
  A   z3ext.controlpanel/trunk/
  A   z3ext.controlpanel/trunk/AUTHOR.txt
  A   z3ext.controlpanel/trunk/CHANGES.txt
  A   z3ext.controlpanel/trunk/LICENSE.txt
  A   z3ext.controlpanel/trunk/bootstrap.py
  A   z3ext.controlpanel/trunk/buildout.cfg
  A   z3ext.controlpanel/trunk/setup.py
  A   z3ext.controlpanel/trunk/src/
  A   z3ext.controlpanel/trunk/src/z3ext/
  A   z3ext.controlpanel/trunk/src/z3ext/__init__.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/README.txt
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/__init__.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/__init__.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/breadcrumb.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.pt
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.pt
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet_icon.gif
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configure.zcml
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/interfaces.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/layout.pt
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.pt
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/preferences-system.png
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/README.txt
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/__init__.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/configure.zcml
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/interfaces.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/test_functional.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlet.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlettype.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/configure.zcml
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/ftesting.zcml
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/i18n.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/interfaces.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/meta.zcml
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/root.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/storage.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/testing.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/tests.py
  A   z3ext.controlpanel/trunk/src/z3ext/controlpanel/zcml.py

-=-

Property changes on: z3ext.controlpanel/trunk
___________________________________________________________________
Name: svn:ignore
   + bin
develop-eggs
eggs
parts
coverage
.installed.cfg


Added: z3ext.controlpanel/trunk/AUTHOR.txt
===================================================================
--- z3ext.controlpanel/trunk/AUTHOR.txt	                        (rev 0)
+++ z3ext.controlpanel/trunk/AUTHOR.txt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1 @@
+Nikolay Kim (fafhrd91 <at> gmail <dot> com)

Added: z3ext.controlpanel/trunk/CHANGES.txt
===================================================================
--- z3ext.controlpanel/trunk/CHANGES.txt	                        (rev 0)
+++ z3ext.controlpanel/trunk/CHANGES.txt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,64 @@
+=======
+CHANGES
+=======
+
+1.2.0 (2008-03-21)
+------------------
+
+- Use z3ext.pagelet directive for browser views
+
+- Added i18n
+
+- Moved to svn.zope.org
+
+
+1.1.7 (2008-03-18)
+------------------
+
+- Added functional tests
+
+
+1.1.6 (2008-02-28)
+------------------
+
+- Use z3c.autoinclude
+
+
+1.1.5 (2008-02-22)
+------------------
+
+- Added buildout.cfg for testing
+
+- Added viewlet manager for configlet navigation
+
+
+1.1.4 (2008-02-20)
+------------------
+
+- Use z3ext.layoutform
+
+
+1.1.3 (2008-02-0?)
+------------------
+
+- Added 'UI' configuration category
+
+
+1.1.2 (2008-02-04)
+------------------
+
+- Fixed problem with generated class and persistence
+
+- Remove all <grant/> directives
+
+
+1.1.0 (2008-01-31)
+------------------
+
+- Use z3ext.layout for rendering
+
+
+1.0.0 (2007-26-07)
+------------------
+
+- Initial release.

Added: z3ext.controlpanel/trunk/LICENSE.txt
===================================================================
--- z3ext.controlpanel/trunk/LICENSE.txt	                        (rev 0)
+++ z3ext.controlpanel/trunk/LICENSE.txt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -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.controlpanel/trunk/bootstrap.py
===================================================================
--- z3ext.controlpanel/trunk/bootstrap.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/bootstrap.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -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$
+"""
+
+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)


Property changes on: z3ext.controlpanel/trunk/bootstrap.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/buildout.cfg
===================================================================
--- z3ext.controlpanel/trunk/buildout.cfg	                        (rev 0)
+++ z3ext.controlpanel/trunk/buildout.cfg	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,18 @@
+[buildout]
+develop = .
+parts = test coverage-test coverage-report
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3ext.controlpanel [test]
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = z3ext.controlpanel [test]
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')

Added: z3ext.controlpanel/trunk/setup.py
===================================================================
--- z3ext.controlpanel/trunk/setup.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/setup.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,86 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Setup for z3ext.controlpanel package
+
+$Id$
+"""
+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.2.0'
+
+
+setup(name = 'z3ext.controlpanel',
+      version = version,
+      description = "Control Panel - userfriendly system control panel.",
+      long_description = (
+        'Detailed Documentation\n' +
+        '======================\n'
+        + '\n\n' +
+        read('src', 'z3ext', 'controlpanel', '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',
+                          'zope.schema',
+    		          'zope.interface',
+                          'zope.component',
+                          'zope.annotation',
+                          'zope.security',
+                          'zope.location',
+                          'zope.publisher',
+                          'zope.i18nmessageid',
+                          'zope.viewlet',
+                          'zope.contentprovider',
+                          'zope.cachedescriptors',
+                          'zope.app.publisher',
+                          'zope.app.component',
+                          'zope.app.security',
+                          'zope.configuration',
+                          'z3c.traverser',
+                          'z3c.autoinclude',
+                          'z3ext.layout',
+                          'z3ext.layoutform',
+                          ],
+      extras_require = dict(test=['zope.securitypolicy',
+                                  'zope.app.security',
+                                  'zope.app.testing',
+                                  'zope.app.zcmlfiles',
+                                  'zope.traversing',
+                                  'zope.testing',
+                                  'zope.testbrowser',
+                                  ]),
+      include_package_data = True,
+      zip_safe = False
+      )


Property changes on: z3ext.controlpanel/trunk/setup.py
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/__init__.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/__init__.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/__init__.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -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__)


Property changes on: z3ext.controlpanel/trunk/src/z3ext/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/README.txt
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/README.txt	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/README.txt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,302 @@
+=============
+Control Panel
+=============
+
+In many cases programm modules needs configuration and some common way
+of managing configuration. Control panel very similar with zope.app.preference,
+it stores all data in site annotation, in BTrees. so you can removeing 
+and add any configlet without problem with zodb.
+
+We need load zcml configuration
+
+  >>> from zope.configuration import xmlconfig
+  >>> context = xmlconfig.string("""
+  ... <configure xmlns:z3ext="http://namespaces.zope.org/z3ext">
+  ...    <include package="z3ext.controlpanel" file="meta.zcml" />
+  ... </configure>""")
+
+  >>> from zope import interface, component
+  >>> from z3ext.controlpanel import tests, interfaces
+
+We can register configlet with z3ext:configlet directive.
+
+Let's create simple configlet
+
+  >>> context = xmlconfig.string("""
+  ... <configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
+  ...    i18n_domain="zope">
+  ...   <z3ext:configlet
+  ...	    name="configlet1"
+  ...      schema="z3ext.controlpanel.tests.ITestConfiglet1"
+  ...      title="Test configlet1"
+  ...      description="Test configlet1 description" />
+  ... </configure>""", context)
+
+That's all. now we can get configlet as utility.
+
+As named IConfiglet
+
+  >>> cl = component.getUtility(interfaces.IConfiglet, name='configlet1')
+  >>> cl.__name__ == 'configlet1'
+  True
+  >>> cl.__title__ == 'Test configlet1'
+  True
+  >>> cl.__description__ == 'Test configlet1 description'
+  True
+
+As schema
+
+  >>> cl1 = component.getUtility(tests.ITestConfiglet1)
+  >>> cl is cl1
+  True
+
+  >>> cl.__schema__
+  <InterfaceClass z3ext.controlpanel.tests.ITestConfiglet1>
+
+We can't change __schema__ at runtime
+
+  >>> cl.__schema__ = tests.ITestConfiglet2
+  Traceback (most recent call last):
+  ...
+  AttributeError: Can't set __schema__
+
+
+IConfiglet
+----------
+
+Let's access the settings:
+
+  >>> cl.param1
+  u'default param1'
+
+  >>> cl.param2
+  10
+
+which is the default value, since we have not set it yet. We can now reassign
+the value:
+
+  >>> cl.param1 = u'test'
+  >>> cl.param1
+  u'test'
+
+However, you cannot just enter any value, since it is validated before the
+assignment:
+
+  >>> cl.param2 = 'str'
+  Traceback (most recent call last):
+  ...
+  WrongType: ...
+
+You can delete attribute, default value would restored
+
+  >>> del cl.param1
+  >>> cl.param1
+  u'default param1'
+
+You can set/remove any attributes to configlet, but this attributes won't 
+be persistent.
+
+  >>> cl.test = 1
+  >>> cl.test
+  1
+
+  >>> del cl.test
+
+Configlet is ILocation object so it can't be used in traversing
+
+  >>> cl.__parent__
+  <z3ext.controlpanel.root.RootConfiglet object at ...>
+
+  >>> cl.__name__
+  u'configlet1'
+
+
+Configlet security
+------------------
+
+Read/Write access to configlet same as for <class> directive. By default
+all fields in IConfiglet interface and schema protected by 'z3ext.Configure'
+permission. We can define default permission by 'permission' attribute. 
+We can use <require/> and <allow/> subdirectives inside <z3ext:configlet>
+directive.
+
+  >>> xmlconfig.string("""
+  ... <configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
+  ...    i18n_domain="zope">
+  ...   <include package="z3ext.controlpanel" file="meta.zcml" />
+  ...   <z3ext:configlet
+  ...	    name="configlet2"
+  ...      schema="z3ext.controlpanel.tests.ITestConfiglet2"
+  ...      title="Test configlet2"
+  ...      permission="zope.Public">
+  ...    <require />
+  ...   </z3ext:configlet>
+  ... </configure>""")
+  Traceback (most recent call last):
+  ...
+  ZopeXMLConfigurationError: ...Nothing required...
+
+  >>> xmlconfig.string("""
+  ... <configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
+  ...    i18n_domain="zope">
+  ...   <include package="z3ext.controlpanel" file="meta.zcml" />
+  ...   <z3ext:configlet
+  ...	    name="configlet2"
+  ...      schema="z3ext.controlpanel.tests.ITestConfiglet2"
+  ...      title="Test configlet2"
+  ...      permission="zope.Public">
+  ...    <require attributes="param1" />
+  ...   </z3ext:configlet>
+  ... </configure>""")
+  Traceback (most recent call last):
+  ...
+  ZopeXMLConfigurationError: ...No permission specified...
+
+  >>> context = xmlconfig.string("""
+  ... <configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
+  ...    i18n_domain="zope">
+  ...   <include package="z3ext.controlpanel" file="meta.zcml" />
+  ...   <z3ext:configlet
+  ...	    name="configlet2"
+  ...      schema="z3ext.controlpanel.tests.ITestConfiglet2"
+  ...      title="Test configlet2"
+  ...      permission="zope.Public">
+  ...    <require attributes="param1" permission="zope.Public" />
+  ...    <allow attributes="param2" />
+  ...    <require set_attributes="param3" permission="zope.Public" />
+  ...   </z3ext:configlet>
+  ... </configure>""", context)
+
+
+Custom class implementation
+---------------------------
+
+We can use custom configlet implementation, but it should subclass
+original Configlet class
+
+  >>> context = xmlconfig.string("""
+  ... <configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
+  ...    i18n_domain="zope">
+  ...   <include package="z3ext.controlpanel" file="meta.zcml" />
+  ...   <z3ext:configlet
+  ...	    name="configlet3"
+  ...      class="z3ext.controlpanel.tests.TestConfiglet1"
+  ...      schema="z3ext.controlpanel.tests.ITestConfiglet2"
+  ...      title="Test configlet3">
+  ...   </z3ext:configlet>
+  ... </configure>""")
+
+  >>> configlet = component.getUtility(interfaces.IConfiglet, 'configlet3')
+  >>> isinstance(configlet, tests.TestConfiglet1)
+  True
+
+
+Configlet groups
+----------------
+
+The configlet would not be very powerful, if you could create a full
+settingss. So let's create a sub-configlet for settings:
+
+  >>> len(configlet)
+  0
+
+  >>> 'configlet' in configlet
+  False
+
+  >>> configlet.get('configlet') is None
+  True
+
+  >>> configlet['configlet']
+  Traceback (most recent call last):
+  ...
+  KeyError: 'configlet'
+
+  >>> def testConfiglet(configlet):
+  ...   return True
+
+  >>> context = xmlconfig.string("""
+  ... <configure xmlns:z3ext="http://namespaces.zope.org/z3ext"
+  ...    i18n_domain="zope">
+  ...   <include package="z3ext.controlpanel" file="meta.zcml" />
+  ...   <z3ext:configlet
+  ...	    name="configlet3.configlet"
+  ...      schema="z3ext.controlpanel.tests.ITestConfiglet1"
+  ...	    tests="z3ext.controlpanel.tests.testConfiglet1"
+  ...      title="Test configlet4">
+  ...   </z3ext:configlet>
+  ... </configure>""", context)
+
+  >>> configlet['configlet'].__parent__ is configlet
+  True
+
+  >>> len(configlet)
+  1
+
+  >>> 'configlet' in configlet
+  True
+
+  >>> configlet['configlet'].__id__
+  u'configlet3.configlet'
+   
+  >>> configlet.items()
+  [(u'configlet', <z3ext.controlpanel.configlettype.Configlet<configlet3.configlet> ...)]
+
+  >>> configlet.values()
+  [<z3ext.controlpanel.configlettype.Configlet<configlet3.configlet> ...>]
+
+  >>> list(iter(configlet))
+  [<z3ext.controlpanel.configlettype.Configlet<configlet3.configlet> ...>]
+
+
+Configlet availability
+----------------------
+
+We can check availability
+
+  >>> c1 = configlet['configlet']
+  >>> c1.isAvailable()
+  True
+
+  >>> c1.__tests__ = (tests.testConfiglet2,)
+  >>> c1.isAvailable()
+  False
+
+Avialability automaticly checks in parent configlet
+
+  >>> c1.__tests__ = (tests.testConfiglet1,)
+  >>> c1.isAvailable()
+  True
+
+  >>> configlet.__tests__ = (tests.testConfiglet2,)
+
+  >>> c1.isAvailable()
+  False
+
+  >>> c1.__tests__ = (tests.testConfiglet1, False)
+  >>> c1.isAvailable()
+  False
+
+  >>> configlet.remove('configlet')
+  >>> len(configlet)
+  0
+
+
+Root configlet
+--------------
+
+There is root configlet. You can access any other configlets from root configlet.
+This configlet has no name, so it's available as nameless IConfiglet utility:
+
+ >>> from zope.app.component.hooks import getSite
+
+ >>> root = component.getUtility(interfaces.IConfiglet)
+ >>> root
+ <z3ext.controlpanel.root.RootConfiglet object at ...>
+
+Root configlet parent is ISite object
+
+ >>> root.__parent__ is getSite()
+ True
+
+ >>> tests.ITestConfiglet1.providedBy(root['configlet1'])
+ True

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/__init__.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/__init__.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/__init__.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/__init__.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/__init__.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/__init__.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/breadcrumb.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/breadcrumb.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/breadcrumb.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" custom IBreadcrumb implementation for IConfiglet
+
+$Id$
+"""
+from zope import interface, component
+from z3c.breadcrumb.interfaces import IBreadcrumb
+from z3c.breadcrumb.browser import GenericBreadcrumb
+from z3ext.controlpanel.interfaces import IConfiglet
+
+
+class ConfigletBreadcrumb(GenericBreadcrumb):
+    component.adapts(IConfiglet, interface.Interface)
+
+    @property
+    def name(self):
+        return self.context.__title__ or self.context.__name__


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/breadcrumb.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.pt
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.pt	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.pt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,25 @@
+<div class="topframe" tal:define="configlets view/data" i18n:domain="z3ext">
+  <h1 tal:content="context/__title__">Configlet category</h1>
+  <div class="pageDescription" 
+       tal:content="context/__description__">Description</div>
+
+  <div tal:condition="not:configlets" i18n:translate="">
+    There are no configlets in this category.
+  </div>
+
+  <ul class="listing" tal:condition="configlets" metal:define-macro="configlets">
+    <li tal:repeat="configlet configlets">
+      <div class="icon">
+	<tal:block tal:content="structure configlet/icon|nothing" />
+      </div>
+      <div class="details">
+	<a tal:attributes="href string:${configlet/configlet/@@absolute_url}/"
+	   tal:content="configlet/title"></a>
+	<div><tal tal:content="configlet/description" /> &nbsp;</div>
+	<tal:block define="configlets configlet/items" condition="configlets">
+	  <metal:block use-macro="view/template/macros/configlets" />
+	</tal:block>
+      </div>
+    </li>
+  </ul>
+</div>

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,60 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" category view
+
+$Id$
+"""
+from zope import interface
+from zope.component import queryMultiAdapter
+from z3ext.controlpanel.interfaces import ICategory, IConfiglet
+
+
+class CategoryView(object):
+
+    def update(self):
+        super(CategoryView, self).update()
+
+        request = self.request
+	context = self.context
+
+        data = self.process(context, request)
+
+        configlets = []
+        for info in data:
+            info['items'] = self.process(info['configlet'], request)
+            if ICategory.providedBy(info['configlet']) and not info['items']:
+                continue
+            configlets.append(info)
+        self.data = configlets
+
+    def process(self, context, request):
+        data = []
+        for configlet in context.values():
+            if not IConfiglet.providedBy(configlet) or \
+                    not configlet.isAvailable():
+                continue
+
+            info = {'name': configlet.__name__,
+                    'title': configlet.__title__,
+                    'description': configlet.__description__,
+                    'icon': queryMultiAdapter(
+                        (configlet, request), name='zmi_icon'),
+                    'items': (),
+                    'selected': False,
+                    'configlet': configlet}
+
+            data.append((configlet.__title__, info))
+
+        data.sort()
+        return [info for t, info in data]


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/category.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.pt
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.pt	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.pt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,25 @@
+<div class="topframe">
+  <form method="post" class="edit-form" enctype="multipart/form-data"
+	tal:attributes="action request/URL">
+    <h1 tal:content="view/label|nothing">Do something</h1>
+    <div class="discreet" tal:content="view/description|nothing"></div>
+    <br />
+    
+    <div class="fieldset">
+      <div>
+	<tal:block tal:repeat="widget view/widgets">
+	  <metal:block use-macro="context/@@form_macros/widget_row"/>
+	</tal:block>
+      </div>
+    </div>
+    
+    <div id="formControls">
+      <hr />
+      <span class="actionButtons"
+	    tal:condition="view/availableActions">
+	<input tal:repeat="action view/actions"
+	       tal:replace="structure action/render" />
+      </span>
+    </div>
+  </form>
+</div>

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,35 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" Default view for IConfiglet
+
+$Id$
+"""
+from zope.cachedescriptors.property import Lazy
+from z3ext.layoutform import Fields, PageletEditForm
+
+
+class Configlet(PageletEditForm):
+    """ configlet view """
+
+    @property
+    def label(self):
+        return self.context.__title__
+
+    @property
+    def description(self):
+        return self.context.__description__
+
+    @Lazy
+    def fields(self):
+        return Fields(self.context.__schema__)


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet_icon.gif
===================================================================
(Binary files differ)


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configlet_icon.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configure.zcml
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configure.zcml	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/configure.zcml	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,72 @@
+<configure 
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:zcml="http://namespaces.zope.org/zcml"
+   xmlns:z3ext="http://namespaces.zope.org/z3ext"
+   xmlns:browser="http://namespaces.zope.org/browser"
+   i18n_domain="z3ext">
+
+  <z3ext:layout
+     layout="portal"
+     name="workspace"
+     for="..interfaces.IRootConfiglet"
+     template="layout.pt"
+     hidden="yes" />
+
+  <browser:icon
+     name="zmi_icon"
+     for="..interfaces.IConfiglet"
+     file="preferences-system.png" />
+
+  <browser:defaultView
+     name="index.html"
+     for="..interfaces.IConfiglet" />
+
+  <browser:menuItem
+     for="..interfaces.IConfiglet"
+     title="View"
+     menu="zmi_views"
+     action="index.html"
+     permission="zope.Public" />
+
+  <z3ext:pagelet
+     name="index.html"
+     for="..interfaces.IConfiglet"
+     class=".configlet.Configlet"
+     permission="zope.Public" />
+
+  <z3ext:pagelet
+     name="index.html"
+     for="..interfaces.ICategory"
+     template="category.pt"
+     class=".category.CategoryView"
+     permission="zope.Public" />
+
+  <!-- navigation -->
+  <browser:viewletManager
+     name="z3ext.controlpanel-navigation"
+     provides=".interfaces.IConfigletNavigation"
+     template="navigation.pt"
+     class=".navigation.Navigation"
+     permission="zope.Public" />
+
+  <!-- for ILocalSiteManager -->
+  <browser:menuItem
+     for="zope.app.component.interfaces.ISite"
+     menu="zmi_actions"
+     title="System settings"
+     action="settings/"
+     permission="z3ext.Configure" />
+
+  <browser:menuItem
+     for="zope.app.component.interfaces.ILocalSiteManager"
+     menu="zmi_actions"
+     title="System settings"
+     action="../settings/"
+     permission="z3ext.Configure" />
+
+  <!-- configlet breadcrumb -->
+  <adapter 
+     zcml:condition="installed z3c.breadcrumb"
+     factory=".breadcrumb.ConfigletBreadcrumb" />
+
+</configure>

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/interfaces.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/interfaces.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/interfaces.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,22 @@
+##############################################################################
+#
+# 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$
+"""
+from zope.viewlet.interfaces import IViewletManager
+
+
+class IConfigletNavigation(IViewletManager):
+    """ extra configlet navigation viewlet manager """


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/layout.pt
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/layout.pt	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/layout.pt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,14 @@
+<div id="z-portal-workspace"
+     tal:define="context nocall:maincontext;
+		 nav provider:z3ext.controlpanel-navigation;
+		 noNav not:nav; rendered view/render">
+  <div class="page">
+    <table class="wide" tal:omit-tag="noNav">
+      <tr style="vertical-align: top" tal:omit-tag="noNav">
+	<td style="padding-right: 1em; width: 200px"
+	    tal:condition="nav" tal:content="structure nav"></td>
+	<td tal:omit-tag="noNav" tal:content="structure rendered"></td>
+      </tr>
+    </table>
+  </div>
+</div>

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.pt
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.pt	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.pt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,23 @@
+<tal:block tal:repeat="viewlet view/viewlets"
+	   tal:content="structure viewlet/render" />
+
+<div class="x-listing box small">
+  <tal:block tal:repeat="item view/data">
+    <metal:block metal:define-macro="level">
+      <div class="x-listing-item"
+	   tal:attributes="class python:item['selected'] and 'x-listing-item-selected' 
+			   or 'x-listing-item'">
+	<div tal:omit-tag="not:item/level|nothing"
+	     tal:attributes="class string:level${item/level|nothing}">
+	  <a tal:attributes="href string:${item/configlet/@@absolute_url}/">
+	    <al:block tal:content="structure item/icon" />
+	    <tal:block tal:content="item/title" />
+	  </a>
+	</div>
+      </div>
+      <tal:block tal:repeat="item item/items">
+	<metal:block use-macro="view/template/macros/level"/>
+      </tal:block>
+    </metal:block>
+  </tal:block>
+</div>

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,80 @@
+##############################################################################
+#
+# 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$
+"""
+from zope.component import queryMultiAdapter
+from zope.viewlet.manager import ViewletManagerBase
+from z3ext.controlpanel.interfaces import IConfiglet, IRootConfiglet
+
+
+class Navigation(ViewletManagerBase):
+
+    def update(self):
+        super(Navigation, self).update()
+
+        context = self.context
+
+        self.isRoot = IRootConfiglet.providedBy(context)
+        if self.isRoot:
+            return
+
+        path = []
+        parent = context
+        while IConfiglet.providedBy(parent):
+            path.insert(0, parent)
+            parent = parent.__parent__
+
+        self.root, path = path[0], path[1:]
+
+        self.data = self._process(self.root, path)
+
+    def _process(self, context, path, level=1):
+        request = self.request
+
+        if path:
+            data = []
+            for name, configlet in context.items():
+                if not IConfiglet.providedBy(configlet) or \
+                        not configlet.isAvailable():
+                    continue
+
+                info = {'name': name,
+                        'title': configlet.__title__,
+                        'icon': queryMultiAdapter(
+                             (configlet, request), name='zmi_icon'),
+                        'items': (),
+                        'selected': False,
+                        'configlet': configlet,
+                        'level': level}
+
+                if configlet.__id__ == path[0].__id__:
+                    info['items'] = self._process(configlet, path[1:], level+1)
+                
+                if configlet.__id__ == self.context.__id__:
+                    info['selected'] = True
+                    info['items'] = self._process(configlet, [configlet], level+1)
+
+                data.append((configlet.__title__, info))
+
+            data.sort()
+            data = [info for t, info in data]
+            return data
+
+    def render(self):
+        if self.isRoot:
+            return u''
+        else:
+            return super(Navigation, self).render()


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/navigation.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/preferences-system.png
===================================================================
(Binary files differ)


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/preferences-system.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/README.txt
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/README.txt	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/README.txt	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,85 @@
+=============
+Control Panel
+=============
+
+We can access controlpanel with following url http://localhost/settings/
+'setting' name availabel for every ISite object.
+
+Let's demonstrate how we can access controlpanel. 
+
+  >>> from zope import component
+  >>> from zope.testbrowser.testing import Browser
+
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/settings/")
+  Traceback (most recent call last):
+  ...
+  Unauthorized: settings
+
+  >>> browser.open("http://localhost/settings/system/")
+  Traceback (most recent call last):
+  ...
+  Unauthorized: settings
+
+  >>> browser = Browser()
+  >>> browser.addHeader("Authorization", "Basic mgr:mgrpw")
+  >>> browser.handleErrors = False
+
+We should have 'System settings' link in ISite actions menu
+
+  >>> browser.open("http://localhost/@@contents.html")
+  >>> print browser.contents
+  <!DOCTYPE html PUBLIC...
+  ...<li><a href="settings/">System settings</a></li>...
+  <BLANKLINE>
+
+  >>> browser.getLink('System settings').click()
+  >>> print browser.contents
+  <!DOCTYPE html PUBLIC...
+  ...System settings...
+  <BLANKLINE>
+
+Configlet categories, by default only first level of categories is
+shown. And only categories that have visible configlets.
+
+  >>> 'Category1' in browser.contents
+  False
+
+  >>> 'Category2' in browser.contents
+  True
+
+Also controlponal show configlets in toplevel categories
+
+  >>> 'Configlet1' in browser.contents
+  True
+
+Category shows only its configlets
+
+  >>> browser.open("http://localhost/settings/category1/")
+  >>> print browser.contents
+  <!DOCTYPE html PUBLIC...
+  ...Category1...
+  ...Category 1 area...
+  ...There are no configlets in this category...
+  <BLANKLINE>
+
+  >>> browser.open("http://localhost/settings/category2/")
+  >>> print browser.contents
+  <!DOCTYPE html PUBLIC...
+  ...Category2...
+  ...Category 2 area...
+  ...http://localhost/settings/category2/configlet1/...Configlet1...
+  ...http://localhost/settings/category2/configlet2/...Configlet2...
+  <BLANKLINE>
+
+But it should not show not available configlets.
+
+  >>> 'Configlet3' in browser.contents
+  False
+
+By default control panel create edit for each configlet, form name 'index.html'
+
+  >>> browser.getLink('Configlet1').click()
+  >>> browser.getControl(name='form.buttons.save').click()
+  >>> browser.getControl(name='form.buttons.cancel').click()

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/__init__.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/__init__.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/__init__.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/configure.zcml
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/configure.zcml	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/configure.zcml	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,46 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:z3ext="http://namespaces.zope.org/z3ext"
+   xmlns:browser="http://namespaces.zope.org/browser">
+
+  <interface
+     name="MySkin"
+     interface=".interfaces.MySkin"
+     type="zope.publisher.interfaces.browser.IBrowserSkinType" />
+
+  <z3ext:configlet
+     name="category1"
+     schema=".interfaces.ICategory1"
+     title="Category1"
+     description="Category 1 area."
+     provides="z3ext.controlpanel.interfaces.ICategory"
+     permission="zope.Public" />
+
+  <z3ext:configlet
+     name="category2"
+     schema=".interfaces.ICategory2"
+     title="Category2"
+     description="Category 2 area."
+     provides="z3ext.controlpanel.interfaces.ICategory"
+     permission="zope.Public" />
+
+  <z3ext:configlet
+     name="category2.configlet1"
+     schema=".interfaces.IConfiglet1"
+     title="Configlet1"
+     permission="zope.Public" />
+
+  <z3ext:configlet
+     name="category2.configlet2"
+     schema=".interfaces.IConfiglet2"
+     title="Configlet2"
+     permission="zope.Public" />
+
+  <z3ext:configlet
+     name="category2.configlet3"
+     schema=".interfaces.IConfiglet3"
+     title="Configlet3"
+     tests=".interfaces.notAvailable"
+     permission="zope.Public" />
+
+</configure>

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/interfaces.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/interfaces.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/interfaces.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,66 @@
+##############################################################################
+#
+# 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$
+"""
+from zope import schema, interface
+from zope.app.rotterdam import Rotterdam
+from z3ext.layoutform.interfaces import ILayoutFormLayer
+
+
+class MySkin(ILayoutFormLayer, Rotterdam):
+    """ my skin """
+
+
+class ICategory1(interface.Interface):
+    """ test category 1 """
+
+
+class ICategory2(interface.Interface):
+    """ test category 2 """
+
+
+class IConfiglet1(interface.Interface):
+
+    param1 = schema.TextLine(
+        title = u'param1',
+        default = u'default param1')
+
+    param2 = schema.Int(
+        title = u'param2',
+        default = 10)
+
+
+class IConfiglet2(interface.Interface):
+
+    param1 = schema.TextLine(
+        title = u'param1',
+        default = u'default param1')
+
+    param2 = schema.Int(
+        title = u'param2',
+        default = 10)
+
+    param3 = schema.TextLine(
+        title = u'param3',
+        default = u'default param3')
+
+
+class IConfiglet3(interface.Interface):
+    pass
+
+
+def notAvailable(*args):
+    return False


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/test_functional.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/test_functional.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/test_functional.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,35 @@
+##############################################################################
+#
+# 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$
+"""
+import unittest, doctest
+from zope import interface
+from zope.app.testing import functional
+from zope.publisher.browser import BrowserRequest
+from z3ext.controlpanel.testing import z3extControlPanelLayer
+
+from interfaces import MySkin
+
+
+def test_suite():
+    interface.classImplements(BrowserRequest, MySkin)
+
+    controlpanel = functional.FunctionalDocFileSuite(
+        "README.txt",
+        optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE)
+    controlpanel.layer = z3extControlPanelLayer
+
+    return unittest.TestSuite((controlpanel,))


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/browser/tests/test_functional.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlet.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlet.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlet.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,114 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" Configlet implementation
+
+$Id$
+"""
+from zope import schema, interface
+from zope.location import Location
+from zope.component import getUtility, queryUtility
+from zope.security.proxy import removeSecurityProxy
+from zope.interface.common.mapping import IEnumerableMapping
+
+from interfaces import IConfiglet, IDataStorage
+
+_marker = object()
+
+
+class Configlet(Location):
+    interface.implements(IConfiglet, IEnumerableMapping)
+
+    def __init__(self, tests=()):
+        self.__name__ = self.__id__.rsplit('.', 1)[-1]
+        self.__tests__ = tests
+        self.__subgroups__ = ()
+
+    @property
+    def data(self):
+        data = getUtility(IDataStorage)
+        return removeSecurityProxy(data)[self.__name__]
+
+    def isAvailable(self):
+        for test in self.__tests__:
+            if callable(test):
+                if not test(self):
+                    return False
+            elif not bool(test):
+                return False
+
+        if IConfiglet.providedBy(self.__parent__):
+            if not self.__parent__.isAvailable():
+                return False
+
+        return True
+
+    def add(self, name):
+        if name not in self.__subgroups__:
+            self.__subgroups__ = self.__subgroups__ + (name,)
+
+    def remove(self, name):
+        if name in self.__subgroups__:
+            names = list(self.__subgroups__)
+            names.remove(name)
+            self.__subgroups__ = tuple(names)
+
+    # implementation of IEnumerableMapping interface
+    def __getitem__(self, key):
+        obj = self.get(key, _marker)
+        if obj is _marker:
+            raise KeyError(key)
+        return obj
+
+    def get(self, key, default=None):
+        id = self.__id__ and self.__id__ + '.' + key or key
+        configlet = queryUtility(IConfiglet, id, default)
+        if configlet is default:
+            return default
+        return configlet
+
+    def __contains__(self, key):
+        return key in self.keys()
+
+    def keys(self):
+        return self.__subgroups__
+
+    def __iter__(self):
+        id = self.__id__
+        if id:
+            id = id + '.'
+
+        for key in self.keys():
+            name = id + key
+            configlet = queryUtility(IConfiglet, name)
+            if configlet is not None:
+                yield configlet
+
+    def values(self):
+        return [group for id, group in self.items()]
+
+    def items(self):
+        id = self.__id__
+        if id:
+            id = id + '.'
+
+        items = []
+        for key in self.keys():
+            name = id + key
+            configlet = queryUtility(IConfiglet, name)
+            if configlet is not None:
+                items.append((key, configlet))
+        return items
+
+    def __len__(self):
+        return len(self.keys())


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlet.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlettype.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlettype.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlettype.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,192 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" Configlet metaclass
+
+$Id$
+"""
+import sys
+from zope.schema import getFields
+
+from z3ext.controlpanel.i18n import _
+from z3ext.controlpanel.configlet import Configlet
+
+_marker = object()
+
+
+class ConfigletType(type):
+    """ Metaclass for all configlets
+
+    >>> from zope import interface, schema
+    >>> from z3ext.controlpanel import configlettype
+
+    >>> class IMyConfiglet(interface.Interface):
+    ...   title = schema.TextLine(title = u'Title')
+    
+    >>> class MyConfiglet(object):
+    ...   pass
+
+    >>> ConfigletClass = configlettype.ConfigletType(
+    ...    'myconfiglet', IMyConfiglet, MyConfiglet, 'MyConfiglet', '')
+
+    New class avilable by it's cname in z3ext.controlpanel.configlettype module
+
+    >>> getattr(configlettype, 'Configlet<myconfiglet>') is ConfigletClass
+    True
+
+    Automaticly generate schema fields to ConfigletProperty
+
+    >>> ConfigletClass.title
+    <z3ext.controlpanel.configlettype.ConfigletProperty object at ...>
+
+    >>> configlet = ConfigletClass()
+    >>> configlet
+    <z3ext.controlpanel.configlettype.Configlet<myconfiglet> object at ...>
+
+    >>> isinstance(configlet, MyConfiglet)
+    True
+
+    >>> isinstance(configlet, configlettype.Configlet)
+    True
+
+    We also can use number of base classes
+
+    >>> class MyConfiglet2(object):
+    ...   pass
+
+    >>> ConfigletClass = configlettype.ConfigletType(
+    ...    'myconfiglet', IMyConfiglet, 
+    ...    (MyConfiglet, MyConfiglet2), 'MyConfiglet', '')
+
+    """
+
+    def __new__(cls, name, schema, class_=None, *args, **kw):
+        cname = 'Configlet<%s>'%name
+        if type(class_) is tuple:
+            bases = class_ + (Configlet,)
+        elif class_ is not None:
+            bases = (class_, Configlet)
+        else:
+            bases = (Configlet,)
+
+        tp = type.__new__(cls, str(cname), bases, {})
+        setattr(sys.modules['z3ext.controlpanel.configlettype'], cname, tp)
+
+        return tp
+
+    def __init__(cls, name, schema, class_=None, title='', description=''):
+        for f_id in getFields(schema):
+            if not hasattr(cls, f_id):
+                setattr(cls, f_id, ConfigletProperty(schema[f_id]))
+
+        cls.__id__ = unicode(name)
+        cls.__title__ = title
+        cls.__description__ = description
+        cls.__schema__ = DataProperty(schema)
+
+
+class DataProperty(object):
+
+    def __init__(self, schema):
+        self.schema = schema
+
+    def __get__(self, inst, klass):
+        return self.schema
+
+    def __set__(self, inst, value):
+        raise AttributeError("Can't set __schema__")
+    
+
+class ConfigletProperty(object):
+    """ Special property thats reads and writes values from 
+    instance's 'data' attribute
+
+    Let's define simple schema field
+
+    >>> from zope import schema
+    >>> field = schema.TextLine(
+    ...    title = u'Test',
+    ...    default = u'default value')
+    >>> field.__name__ = 'attr1'
+
+    Now we need content class
+
+    >>> from z3ext.controlpanel.configlettype import ConfigletProperty
+    >>> class Content(object):
+    ...
+    ...    attr1 = ConfigletProperty(field)
+    
+    Lets create class instance and add field values storage
+
+    >>> ob = Content()
+    >>> ob.data = {}
+    
+    By default we should get field default value
+
+    >>> ob.attr1
+    u'default value'
+
+    We can set only valid value 
+
+    >>> ob.attr1 = 'value1'
+    Traceback (most recent call last):
+    ...
+    WrongType: ('value1', <type 'unicode'>)
+
+    >>> ob.attr1 = u'value1'
+    >>> ob.attr1
+    u'value1'
+
+    If storage contains field value we shuld get it
+
+    >>> ob.data['attr1'] = u'value2'
+    >>> ob.attr1
+    u'value2'
+
+    We can't set value for readonly fields
+
+    >>> field.readonly = True
+    >>> ob.attr1 = u'value1'
+    Traceback (most recent call last):
+    ...
+    ValueError: ('attr1', 'field is readonly')
+
+    """
+
+    def __init__(self, field, name=None):
+        if name is None:
+            name = field.__name__
+
+        self.__field = field
+        self.__name = name
+
+    def __get__(self, inst, klass):
+        if inst is None:
+            return self
+
+        value = inst.data.get(self.__name, _marker)
+        if value is _marker:
+            return self.__field.default
+
+        return value
+
+    def __set__(self, inst, value):
+        field = self.__field.bind(inst)
+        field.validate(value)
+        if field.readonly and self.__name in inst.data:
+            raise ValueError(self.__name, _(u'Field is readonly'))
+        inst.data[self.__name] = value
+
+    def __delete__(self, inst):
+        if self.__name in inst.data:
+            del inst.data[self.__name]


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/configlettype.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/configure.zcml
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/configure.zcml	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/configure.zcml	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,83 @@
+<configure 
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:z3ext="http://namespaces.zope.org/z3ext"
+   i18n_domain="z3ext">
+
+  <autoinclude package="z3ext.controlpanel" />
+
+  <permission
+     id="z3ext.Configure"
+     title="Configure control panel's configlets." />
+
+  <utility
+     provides=".interfaces.IConfiglet"
+     factory=".root.RootConfiglet" />
+
+  <class class=".root.RootConfiglet">
+    <require
+       permission="zope.Public"
+       interface=".interfaces.IConfiglet
+		  zope.interface.common.mapping.IEnumerableMapping" />
+  </class>
+
+  <z3ext:configlet
+     name="system"
+     schema=".interfaces.ISystemConfiglet"
+     title="System configuration"
+     description="This area allows you to configure system."
+     provides=".interfaces.ICategory"
+     permission="zope.Public" />
+
+  <z3ext:configlet
+     name="principals"
+     schema=".interfaces.IPrincipalsConfiglet"
+     title="Portal principals"
+     description="Portal principals related settings."
+     provides=".interfaces.ICategory"
+     permission="zope.Public" />
+
+  <z3ext:configlet
+     name="ui"
+     schema=".interfaces.IUIConfiguration"
+     title="Portal ui configuration"
+     description="This area allows you to configure portal look&amp;feel."
+     provides=".interfaces.ICategory"
+     permission="zope.Public" />
+
+  <utility factory=".storage.DataStorage" />
+
+  <!-- settings view -->
+  <adapter
+     name="settings"
+     for="zope.app.component.interfaces.ISite *"
+     provides="zope.interface.Interface"
+     factory=".root.getSettings" />
+
+  <!-- Configlet publisher -->
+  <adapter
+     for=".interfaces.IConfiglet *"
+     factory="z3c.traverser.traverser.PluggableTraverser"
+     provides="zope.publisher.interfaces.IPublishTraverse" />
+
+  <subscriber
+     for=".interfaces.IConfiglet *"
+     provides="z3c.traverser.interfaces.ITraverserPlugin"
+     factory="z3c.traverser.traverser.ContainerTraverserPlugin" />
+
+  <include package=".browser" />
+
+  <!-- Registering documentation with API doc -->
+  <configure
+     xmlns:apidoc="http://namespaces.zope.org/apidoc"
+     xmlns:zcml="http://namespaces.zope.org/zcml"
+     zcml:condition="have apidoc">
+
+    <apidoc:bookchapter
+       id="z3ext-controlpanel"
+       title="z3ext.controlpanel - Control Panel"
+       doc_path="README.txt"
+       parent="z3ext" />
+
+  </configure>
+
+</configure>

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/ftesting.zcml
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/ftesting.zcml	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/ftesting.zcml	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,58 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   i18n_domain="z3ext" package="z3ext.controlpanel">
+
+  <!-- This file is the equivalent of site.zcml and it is -->
+  <!-- used for functional testing setup -->
+
+  <include package="zope.component" file="meta.zcml" />
+  <include package="zope.securitypolicy" file="meta.zcml" />
+  <include package="zope.viewlet" file="meta.zcml" />
+  <include package="zope.app.component" file="meta.zcml" />
+  <include package="zope.app.security" file="meta.zcml" />
+  <include package="zope.app.pagetemplate" file="meta.zcml" />
+
+  <include package="zope.securitypolicy" />
+  <include package="zope.contentprovider" />
+  <include package="zope.app.security" />
+  <include package="zope.app.zcmlfiles" />
+  <include package="zope.app.authentication" />
+  <include package="zope.session" />
+
+  <include package="z3c.autoinclude" file="meta.zcml" />
+  <include package="z3ext.controlpanel" file="meta.zcml" />
+  <include package="z3ext.controlpanel" />
+  <include package="z3ext.controlpanel.browser.tests" />
+  <include package="z3ext.portalmessage" />
+
+  <securityPolicy
+      component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+
+  <role id="zope.Anonymous" title="Everybody"
+        description="All users have this role implicitly" />
+  <role id="zope.Manager" title="Site Manager" />
+
+  <!-- Replace the following directive if you don't want public access -->
+  <grant permission="zope.View"
+         role="zope.Anonymous" />
+
+  <grant permission="zope.app.dublincore.view"
+         role="zope.Anonymous" />
+
+  <!-- Principals -->
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User" />
+
+  <!-- Principal that tests generally run as -->
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw" />
+
+  <grant role="zope.Manager" principal="zope.mgr" />
+
+  <grantAll role="zope.Manager" />
+
+</configure>

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/i18n.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/i18n.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/i18n.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,19 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" i18n
+
+$Id$
+"""
+from zope.i18nmessageid import MessageFactory
+_ = MessageFactory('z3ext')


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/i18n.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/interfaces.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/interfaces.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/interfaces.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,73 @@
+##############################################################################
+#
+# 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.controlpanel interfaces
+
+$Id$
+"""
+from zope import schema, interface
+from zope.location.interfaces import ILocation
+
+
+class ICategory(interface.Interface):
+    """ settings category """
+
+
+class IRootConfiglet(interface.Interface):
+    """ root settings configlet """
+
+
+class ISystemConfiglet(interface.Interface):
+    """This area allows you to configure system."""
+
+
+class IPrincipalsConfiglet(interface.Interface):
+    """ Portal principals related settings """
+
+
+class IUIConfiguration(interface.Interface):
+    """ Portal UI related settings """
+
+
+class IDataStorage(interface.Interface):
+    """ data storage """
+
+    def get(name):
+        """ get named data """
+
+    def __getitem__(name):
+        """ get named data """
+
+
+class IConfiglet(ILocation):
+    """A group of settings."""
+
+    __id__ = schema.TextLine(
+        title = u"Id",
+        description = u"The id of the configlet.",
+        required = True)
+
+    __title__ = schema.TextLine(
+        title = u"Title",
+        description = u"The title of the configlet used in the UI.",
+        required = True)
+
+    __description__ = schema.TextLine(
+        title = u"Description",
+        description = u"The description of the configlet used in the UI.",
+        required = False)
+
+    __schema__ = interface.Attribute('Configlet schema (readonly)')
+
+    def isAvailable():
+        """ is configlet available in current site """


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/meta.zcml
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/meta.zcml	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/meta.zcml	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,22 @@
+<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="configlet"
+       schema=".zcml.IConfigletDirective"
+       handler=".zcml.ConfigletDirective">
+
+      <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.controlpanel/trunk/src/z3ext/controlpanel/root.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/root.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/root.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,56 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" Root configlet
+
+$Id$
+"""
+from zope import interface, component
+from zope.component import getUtility
+from zope.security import checkPermission
+from zope.security.interfaces import Unauthorized
+
+from zope.app.component.hooks import getSite
+from zope.app.component.interfaces import ISite
+
+from i18n import _
+from configlet import Configlet
+from interfaces import IConfiglet, IRootConfiglet, ICategory
+
+
+class RootConfiglet(Configlet):
+    interface.implements(ICategory, IRootConfiglet)
+
+    __id__ = ''
+    __name__ = 'settings'
+    __title__ = _(u'System settings')
+    __description__ = ''
+    __schema__ = IRootConfiglet
+
+    def __init__(self):
+        self.__subgroups__ = ()
+
+    def isAvailable(self):
+        return True
+
+    @property
+    def __parent__(self):
+        return getSite()
+
+
+ at interface.implementer(interface.Interface)
+ at component.adapter(ISite, interface.Interface)
+def getSettings(site, request):
+    if not checkPermission('z3ext.Configure', site):
+        raise Unauthorized('settings')
+    return getUtility(IConfiglet)


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/root.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/storage.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/storage.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/storage.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,50 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" IDataStorage implementation
+
+$Id$
+"""
+from BTrees.OOBTree import OOBTree
+
+from zope import interface
+from zope.app.component.hooks import getSite
+from zope.annotation.interfaces import IAnnotations
+from z3ext.controlpanel.interfaces import IDataStorage
+
+key = 'z3ext.controlpanel.Settings'
+_temp = {}
+
+class DataStorage(object):
+    interface.implements(IDataStorage)
+
+    @property
+    def _data(self):
+        site = getSite()
+        ann = IAnnotations(site, None)
+        if ann is None:
+            return _temp
+
+        storage = ann.get(key)
+        if storage is None:
+            storage = OOBTree()
+            ann[key] = storage
+
+        return storage
+
+    def __getitem__(self, name):
+        try:
+            return self._data[name]
+        except KeyError:
+            self._data[name] = OOBTree()
+            return self._data[name]


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/storage.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/testing.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/testing.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/testing.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,40 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" setup z3ext.controlpanel
+
+$Id$
+"""
+import os
+from zope import component
+from zope.app.testing import setup
+from zope.annotation.attribute import AttributeAnnotations
+from zope.app.component.hooks import getSite, setSite
+from zope.app.testing.functional import ZCMLLayer
+
+from z3ext.controlpanel import storage, root, interfaces
+
+
+def setUpControlPanel():
+    setup.setUpTraversal()
+    setup.setUpSiteManagerLookup()
+
+    component.provideAdapter(root.getSettings, name='settings')
+    component.provideAdapter(AttributeAnnotations)
+    component.provideUtility(storage.DataStorage())
+    component.provideUtility(root.RootConfiglet(), interfaces.IConfiglet)
+
+
+z3extControlPanelLayer = ZCMLLayer(
+    os.path.join(os.path.split(__file__)[0], 'ftesting.zcml'),
+    __name__, 'z3extControlPanelLayer', allow_teardown=True)


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/testing.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/tests.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/tests.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/tests.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,81 @@
+##############################################################################
+#
+# 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 Control Panel tests
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import unittest, doctest
+from zope import interface, schema
+from zope.app.testing import setup
+from z3ext.controlpanel.configlet import Configlet
+from z3ext.controlpanel.testing import setUpControlPanel
+
+def testConfiglet1(configlet):
+    return True
+
+def testConfiglet2(configlet):
+    return False
+
+
+class ITestConfiglet1(interface.Interface):
+    
+    param1 = schema.TextLine(
+        title = u'param1',
+        default = u'default param1')
+
+    param2 = schema.Int(
+        title = u'param2',
+        default = 10)
+
+
+class ITestConfiglet2(interface.Interface):
+
+    param1 = schema.TextLine(
+        title = u'param1',
+        default = u'default param1')
+
+    param2 = schema.Int(
+        title = u'param2',
+        default = 10)
+
+    param3 = schema.TextLine(
+        title = u'param3',
+        default = u'default param3')
+
+
+class TestConfiglet1(Configlet):
+    pass
+
+
+class TestConfiglet2(object):
+    pass
+
+
+def setUp(test):
+    setup.placefulSetUp(True)
+    setUpControlPanel()
+
+
+def test_suite():
+    return unittest.TestSuite((
+            doctest.DocFileSuite(
+                'README.txt',
+                setUp=setUp, tearDown=setup.placefulTearDown(),
+                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
+            doctest.DocTestSuite(
+                'z3ext.controlpanel.configlettype',
+                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
+            ))


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3ext.controlpanel/trunk/src/z3ext/controlpanel/zcml.py
===================================================================
--- z3ext.controlpanel/trunk/src/z3ext/controlpanel/zcml.py	                        (rev 0)
+++ z3ext.controlpanel/trunk/src/z3ext/controlpanel/zcml.py	2008-03-21 09:09:54 UTC (rev 84833)
@@ -0,0 +1,219 @@
+##############################################################################
+#
+# 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:configlet directive
+
+$Id$
+"""
+from zope import interface
+from zope.schema import getFields
+from zope.interface.common.mapping import IEnumerableMapping
+
+from zope.component import getUtility
+from zope.component.zcml import utility
+from zope.component.interface import provideInterface
+
+from zope.schema.interfaces import IField
+
+from zope.security import checkPermission
+from zope.security.zcml import Permission
+from zope.security.checker import Checker, CheckerPublic
+
+from zope.configuration import fields
+from zope.configuration.exceptions import ConfigurationError
+
+from zope.app.security.protectclass import protectName, protectSetAttribute
+
+from configlet import Configlet
+from configlettype import ConfigletType
+from interfaces import IConfiglet
+
+
+class IConfigletDirective(interface.Interface):
+
+    name = fields.PythonIdentifier(
+        title = u"Name",
+        description = u"Name of the configlet used to access the settings.",
+        required = True)
+
+    schema = fields.GlobalInterface(
+        title = u"Configlet schema",
+        description = u"This attribute specifies the schema of the configlet",
+        required = True)
+
+    title = fields.MessageID(
+        title = u"Title",
+        description = u"Title of the configlet used in UIs.",
+        required = True)
+
+    description = fields.MessageID(
+        title = u"Description",
+        description = u"Description of the configlet used in UIs.",
+        required = False)
+
+    class_ = fields.GlobalObject(
+	title = u"Class",
+        description = u'Custom configlet class',
+	required = False)
+
+    provides = fields.Tokens(
+	title = u'Provides',
+        required = False,
+        value_type = fields.GlobalInterface())
+
+    permission = Permission(
+        title = u'Permission',
+        description = u'Default access permission.',
+        required = False)
+
+    tests = fields.Tokens(
+	title = u"Tests",
+        description = u'Tests for check availability.',
+        value_type = fields.GlobalObject(),
+	required = False)
+
+
+class ConfigletDirective(object):
+
+    def __init__(self, _context, name, schema, title,
+                 description='', class_=None, provides=(),
+                 permission='z3ext.Configure', tests=(), install_schema_utility=True):
+
+        ConfigletClass = ConfigletType(
+            str(name), schema, class_, title, description)
+
+        if permission == 'zope.Public':
+            configlet = ConfigletClass(tuple(tests))
+        else:
+            configlet = ConfigletClass(
+                (PermissionChecker(permission),) + tuple(tests))
+
+        utility(_context, IConfiglet, configlet, name=name)
+
+        if install_schema_utility:
+            utility(_context, schema, configlet)            
+
+        interface.classImplements(ConfigletClass, schema, *provides)
+
+        self._class = ConfigletClass
+        self._context = _context
+        self._configlet = configlet
+        self._permission = permission
+
+        self.require(_context, permission,
+                     interface=(IConfiglet, schema), set_schema=(schema,))
+        self.require(_context, CheckerPublic, interface=(IEnumerableMapping,))
+        self.require(_context, CheckerPublic, attributes=('isAvailable',))
+
+        _context.action(
+            discriminator=('z3ext:controlpanel', configlet),
+            callable=addSubgroup, args=(configlet,))
+
+    def require(self, _context,
+                permission=None, attributes=None, interface=None,
+                like_class=None, set_attributes=None, set_schema=None):
+        """Require a permission to access a specific aspect"""
+        if not (interface or attributes or set_attributes or set_schema):
+            raise ConfigurationError("Nothing required")
+
+        if not permission:
+            raise ConfigurationError("No permission specified")
+
+        if interface:
+            for i in interface:
+                if i:
+                    self.__protectByInterface(i, permission)
+
+        if attributes:
+            self.__protectNames(attributes, permission)
+
+        if set_attributes:
+            self.__protectSetAttributes(set_attributes, permission)
+
+        if set_schema:
+            for s in set_schema:
+                self.__protectSetSchema(s, permission)
+
+    def allow(self, _context, attributes=None, interface=None):
+        """Like require, but with permission_id zope.Public"""
+        return self.require(_context, self._permission, attributes, interface)
+
+    def __protectByInterface(self, interface, permission_id):
+        "Set a permission on names in an interface."
+        for n, d in interface.namesAndDescriptions(1):
+            self.__protectName(n, permission_id)
+
+        self._context.action(
+            discriminator = None,
+            callable = provideInterface,
+            args = (interface.__module__+'.'+interface.getName(), interface))
+
+    def __protectName(self, name, permission_id):
+        "Set a permission on a particular name."
+        self._context.action(
+            discriminator = ('z3ext:controlpanel:protectName',
+                             self._class, name, object()),
+            callable = protectName,
+            args = (self._class, name, permission_id))
+
+    def __protectNames(self, names, permission_id):
+        "Set a permission on a bunch of names."
+        for name in names:
+            self.__protectName(name, permission_id)
+
+    def __protectSetAttributes(self, names, permission_id):
+        "Set a permission on a bunch of names."
+        for name in names:
+            self._context.action(
+                discriminator = ('z3ext:controlpanel:protectSetAttribute', 
+                                 self._class, name, object()),
+                callable = protectSetAttribute,
+                args = (self._class, name, permission_id))
+
+    def __protectSetSchema(self, schema, permission_id):
+        "Set a permission on a bunch of names."
+        _context = self._context
+
+        for name in schema:
+            field = schema[name]
+            if IField.providedBy(field) and not field.readonly:
+                _context.action(
+                    discriminator = ('z3ext:controlpanel:protectSetAttribute',
+                                     self._class, name, object()),
+                    callable = protectSetAttribute,
+                    args = (self._class, name, permission_id))
+
+        _context.action(
+            discriminator = None,
+            callable = provideInterface,
+            args = (schema.__module__+'.'+schema.getName(), schema))
+
+
+def addSubgroup(configlet):
+    if '.' in configlet.__id__:
+        parentId = configlet.__id__.rsplit('.', 1)[0]
+    else:
+        parentId = ''
+
+    parent = getUtility(IConfiglet, parentId)
+    parent.add(configlet.__name__)
+    configlet.__parent__ = parent
+
+
+class PermissionChecker(object):
+
+    def __init__(self, permission):
+        self.permission = permission
+
+    def __call__(self, configlet):
+        return checkPermission(self.permission, configlet)


Property changes on: z3ext.controlpanel/trunk/src/z3ext/controlpanel/zcml.py
___________________________________________________________________
Name: svn:keywords
   + Id



More information about the Checkins mailing list