[Checkins] SVN: z3ext.preferences/tags/1.4.5/ release tag

Nikolay Kim fafhrd at datacom.kz
Thu Jan 8 21:48:48 EST 2009


Log message for revision 94667:
  release tag

Changed:
  A   z3ext.preferences/tags/1.4.5/
  D   z3ext.preferences/tags/1.4.5/CHANGES.txt
  A   z3ext.preferences/tags/1.4.5/CHANGES.txt
  D   z3ext.preferences/tags/1.4.5/setup.py
  A   z3ext.preferences/tags/1.4.5/setup.py
  D   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/browser/navigation.pt
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/browser/navigation.pt
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/configure.zcml
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/ftesting.zcml
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/interfaces.py
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/overrides.zcml
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/test.pt
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/testbrowser.txt
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/testlayout.pt
  D   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/tests.py
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/tests.py
  D   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/zcml.py
  A   z3ext.preferences/tags/1.4.5/src/z3ext/preferences/zcml.py

-=-
Deleted: z3ext.preferences/tags/1.4.5/CHANGES.txt
===================================================================
--- z3ext.preferences/trunk/CHANGES.txt	2009-01-08 07:26:31 UTC (rev 94610)
+++ z3ext.preferences/tags/1.4.5/CHANGES.txt	2009-01-09 02:48:48 UTC (rev 94667)
@@ -1,128 +0,0 @@
-=======
-CHANGES
-=======
-
-1.4.5 (Unreleased)
-------------------
-
-- Fixed security for preference group
-
-
-1.4.4 (2008-12-22)
-------------------
-
-- Use new pagelet api
-
-
-1.4.3 (2008-12-12)
-------------------
-
-- Simplify preferences navigation
-
-- raise Unauthorized exception if unauthenticated user access preferences panel
-
-
-1.4.2 (2008-10-27)
-------------------
-
-- Show preference category if it has editable fields
-
-
-1.4.1 (2008-10-22)
-------------------
-
-- Added translations: ru, nl
-
-
-1.4.0 (2008-10-15)
-------------------
-
-- UI api refactored
-
-- Added default css styles
-
-
-1.3.2 (2008-05-16)
-------------------
-
-- Replace 'autoinclude' with 'includeDependendcies'
-
-
-1.3.1 (2008-05-07)
-------------------
-
-- Fix category rendering
-
-
-1.3.0 (2008-05-06)
-------------------
-
-- UI refactoring
-
-- Do not include permission checker for zope.Public permission
-
-
-1.2.1 (2008-04-22)
-------------------
-
-- Added permission checker to directive
-
-
-1.2.0 (2008-04-18)
-------------------
-
-- 'schema' field for z3ext:preferenceGroup is required now
-
-- Added adapter for IPrincipal to 'schema' with automatic binding
-
-
-1.1.1 (2008-04-15)
-------------------
-
-- Use 'z3ext.ManagePreference' as default preference permission
-
-
-1.1.0 (2008-04-11)
-------------------
-
-- Added 'for' field to z3ext:preferenceGroup directive
-
-
-1.0.2 (2008-04-07)
-------------------
-
-- Fix UI in navigation
-
-
-1.0.1 (2008-04-04)
-------------------
-
-- Fixed group category layout
-
-
-1.0.0 (2008-03-25)
-------------------
-
-- Tests added
-
-- Code moved to svn.zope.org
-
-
-0.9.2 (2008-02-29)
-------------------
-
-- Use z3c.autoinclude
-
-- Added z3c.baseregistry support
-
-
-0.9.1 (2008-02-20)
-------------------
-
-- Use z3ext.layoutform
-
-
-0.9.0 (2008-02-01)
-------------------
-
-- Initial release

Copied: z3ext.preferences/tags/1.4.5/CHANGES.txt (from rev 94666, z3ext.preferences/trunk/CHANGES.txt)
===================================================================
--- z3ext.preferences/tags/1.4.5/CHANGES.txt	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/CHANGES.txt	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,130 @@
+=======
+CHANGES
+=======
+
+1.4.5 (2009-01-09)
+------------------
+
+- Added 'accesspremission' attribute for preferenceGroup directive
+
+- Fixed security for preference group
+
+
+1.4.4 (2008-12-22)
+------------------
+
+- Use new pagelet api
+
+
+1.4.3 (2008-12-12)
+------------------
+
+- Simplify preferences navigation
+
+- raise Unauthorized exception if unauthenticated user access preferences panel
+
+
+1.4.2 (2008-10-27)
+------------------
+
+- Show preference category if it has editable fields
+
+
+1.4.1 (2008-10-22)
+------------------
+
+- Added translations: ru, nl
+
+
+1.4.0 (2008-10-15)
+------------------
+
+- UI api refactored
+
+- Added default css styles
+
+
+1.3.2 (2008-05-16)
+------------------
+
+- Replace 'autoinclude' with 'includeDependendcies'
+
+
+1.3.1 (2008-05-07)
+------------------
+
+- Fix category rendering
+
+
+1.3.0 (2008-05-06)
+------------------
+
+- UI refactoring
+
+- Do not include permission checker for zope.Public permission
+
+
+1.2.1 (2008-04-22)
+------------------
+
+- Added permission checker to directive
+
+
+1.2.0 (2008-04-18)
+------------------
+
+- 'schema' field for z3ext:preferenceGroup is required now
+
+- Added adapter for IPrincipal to 'schema' with automatic binding
+
+
+1.1.1 (2008-04-15)
+------------------
+
+- Use 'z3ext.ManagePreference' as default preference permission
+
+
+1.1.0 (2008-04-11)
+------------------
+
+- Added 'for' field to z3ext:preferenceGroup directive
+
+
+1.0.2 (2008-04-07)
+------------------
+
+- Fix UI in navigation
+
+
+1.0.1 (2008-04-04)
+------------------
+
+- Fixed group category layout
+
+
+1.0.0 (2008-03-25)
+------------------
+
+- Tests added
+
+- Code moved to svn.zope.org
+
+
+0.9.2 (2008-02-29)
+------------------
+
+- Use z3c.autoinclude
+
+- Added z3c.baseregistry support
+
+
+0.9.1 (2008-02-20)
+------------------
+
+- Use z3ext.layoutform
+
+
+0.9.0 (2008-02-01)
+------------------
+
+- Initial release

Deleted: z3ext.preferences/tags/1.4.5/setup.py
===================================================================
--- z3ext.preferences/trunk/setup.py	2009-01-08 07:26:31 UTC (rev 94610)
+++ z3ext.preferences/tags/1.4.5/setup.py	2009-01-09 02:48:48 UTC (rev 94667)
@@ -1,89 +0,0 @@
-##############################################################################
-#
-# 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.preferences 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.4.5dev'
-
-
-setup(name = 'z3ext.preferences',
-      version = version,
-      author = 'Nikolay Kim',
-      author_email = 'fafhrd91 at gmail.com',
-      description = "z3ext principal preferences",
-      long_description = (
-        'Detailed Documentation\n' +
-        '======================\n'
-        + '\n\n' +
-        read('src', 'z3ext', 'preferences', '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'],
-      url='http://z3ext.net/',
-      license='ZPL 2.1',
-      packages=find_packages('src'),
-      package_dir = {'':'src'},
-      namespace_packages=['z3ext'],
-      install_requires = ['setuptools',
-                          'ZODB3',
-                          'zope.component',
-                          'zope.interface',
-                          'zope.annotation',
-                          'zope.publisher',
-                          'zope.configuration',
-                          'zope.schema',
-                          'zope.location',
-                          'zope.security',
-                          'zope.securitypolicy',
-			  'zope.cachedescriptors',
-			  'zope.pagetemplate',
-			  'zope.i18n',
-                          'zope.i18nmessageid',
-			  'zope.viewlet',
-			  'zope.contentprovider',
-			  'zope.app.security',
-                          'zope.app.component',
-			  'zope.app.publisher',
-			  'zope.app.pagetemplate',
-			  'zope.app.principalannotation',
-                          'z3c.traverser',
-			  'z3c.autoinclude',
-			  'z3ext.layout >= 1.5.1',
-			  'z3ext.layoutform >= 1.2.3',
-                          'z3ext.statusmessage',
-			  'z3ext.resourcepackage',
-                          ],
-      extras_require = dict(test=['zope.app.testing',
-                                  'zope.testing',
-                                  ]),
-      include_package_data = True,
-      zip_safe = False
-      )

Copied: z3ext.preferences/tags/1.4.5/setup.py (from rev 94666, z3ext.preferences/trunk/setup.py)
===================================================================
--- z3ext.preferences/tags/1.4.5/setup.py	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/setup.py	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,90 @@
+##############################################################################
+#
+# 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.preferences 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.4.5'
+
+
+setup(name = 'z3ext.preferences',
+      version = version,
+      author = 'Nikolay Kim',
+      author_email = 'fafhrd91 at gmail.com',
+      description = "z3ext principal preferences",
+      long_description = (
+        'Detailed Documentation\n' +
+        '======================\n'
+        + '\n\n' +
+        read('src', 'z3ext', 'preferences', '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'],
+      url='http://z3ext.net/',
+      license='ZPL 2.1',
+      packages=find_packages('src'),
+      package_dir = {'':'src'},
+      namespace_packages=['z3ext'],
+      install_requires = ['setuptools',
+                          'ZODB3',
+                          'zope.component',
+                          'zope.interface',
+                          'zope.annotation',
+                          'zope.publisher',
+                          'zope.configuration',
+                          'zope.schema',
+                          'zope.location',
+                          'zope.security',
+                          'zope.securitypolicy',
+			  'zope.cachedescriptors',
+			  'zope.pagetemplate',
+			  'zope.i18n',
+                          'zope.i18nmessageid',
+			  'zope.viewlet',
+			  'zope.contentprovider',
+			  'zope.app.security',
+                          'zope.app.component',
+			  'zope.app.publisher',
+			  'zope.app.pagetemplate',
+			  'zope.app.principalannotation',
+                          'z3c.traverser',
+			  'z3c.autoinclude',
+			  'z3ext.layout',
+			  'z3ext.layoutform',
+                          'z3ext.statusmessage',
+			  'z3ext.resourcepackage',
+                          ],
+      extras_require = dict(test=['zope.app.testing',
+                                  'zope.testing',
+				  'zope.testbrowser',
+                                  ]),
+      include_package_data = True,
+      zip_safe = False
+      )

Deleted: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/browser/navigation.pt
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/browser/navigation.pt	2009-01-08 07:26:31 UTC (rev 94610)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/browser/navigation.pt	2009-01-09 02:48:48 UTC (rev 94667)
@@ -1,25 +0,0 @@
-<tal:block tal:repeat="viewlet view/viewlets"
-           tal:content="structure viewlet/render" />
-
-<div class="z-prefs-nav">
-  <tal:block tal:repeat="item view/data">
-    <metal:block metal:define-macro="level">
-      <div class="z-prefs-nav-item"
-	   tal:attributes="class python:item['selected'] and 'z-prefs-nav-item-selected' 
-			   or 'z-prefs-nav-item'">
-	<div tal:omit-tag="not:item/level|nothing"
-	     tal:attributes="class string:z-level${item/level|nothing}">
-	  <a tal:attributes="href string:${item/prefs/@@absolute_url}/;
-			     title item/description"
-	     tal:omit-tag="not:item/editable">
-	    <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>

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/browser/navigation.pt (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/browser/navigation.pt)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/browser/navigation.pt	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/browser/navigation.pt	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,25 @@
+<tal:block tal:repeat="viewlet view/viewlets"
+           tal:content="structure viewlet/render" />
+
+<div class="z-prefs-nav">
+  <tal:block tal:repeat="item view/data">
+    <metal:block metal:define-macro="level">
+      <div class="z-prefs-nav-item"
+	   tal:attributes="class python:item['selected'] and 'z-prefs-nav-item-selected' 
+			   or 'z-prefs-nav-item'">
+	<div tal:omit-tag="not:item/level|nothing"
+	     tal:attributes="class string:z-level${item/level|nothing}">
+	  <a tal:attributes="href string:${item/prefs/@@absolute_url}/;
+			     title item/description"
+	     tal:omit-tag="not:item/editable">
+	    <tal: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>

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/configure.zcml (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/tests/configure.zcml)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/configure.zcml	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/configure.zcml	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,49 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:z3ext="http://namespaces.zope.org/z3ext"
+   i18n_domain="zope">
+
+  <interface
+     name="DefaultSkin"
+     interface=".tests.IDefaultSkin"
+     type="zope.publisher.interfaces.browser.IBrowserSkinType" />
+
+  <z3ext:pagelet
+     name="test.html"
+     for="*"
+     template="test.pt"
+     permission="zope.Public" />
+
+  <z3ext:preferenceGroup
+     id="category"
+     schema=".interfaces.ICategory"
+     title="Category"
+     accesspermission="zope.Public"
+     provides="z3ext.preferences.interfaces.IPreferenceCategory" />
+
+  <z3ext:preferenceGroup
+     id="category.prefs1"
+     schema=".interfaces.IPrefs1"
+     title="Preferences 1"
+     accesspermission="zope.Public" />
+
+  <z3ext:preferenceGroup
+     id="category.prefs2"
+     schema=".interfaces.IPrefs2"
+     title="Preferences 2"
+     accesspermission="zope.Public" />
+
+  <z3ext:preferenceGroup
+     id="category.prefs3"
+     schema=".interfaces.IPrefs3"
+     title="Preferences 3"
+     accesspermission="zope.Public"
+     tests="z3ext.preferences.tests.tests.notAvailable" />
+
+  <z3ext:preferenceGroup
+     id="portal.prefs4"
+     schema=".interfaces.IPrefs4"
+     title="Preferences 4"
+     accesspermission="zope.Public" />
+
+</configure>

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/ftesting.zcml (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/tests/ftesting.zcml)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/ftesting.zcml	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/ftesting.zcml	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,68 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:z3ext="http://namespaces.zope.org/z3ext"
+   xmlns:browser="http://namespaces.zope.org/browser"
+   i18n_domain="zope">
+
+  <!-- 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="z3c.autoinclude" file="meta.zcml" />
+  <include package="z3ext.preferences" file="meta.zcml" />
+  <include package="z3ext.preferences" />
+  <include package="z3ext.preferences.tests" />
+  <includeOverrides package="z3ext.preferences.tests" file="overrides.zcml" />
+
+  <browser:defaultSkin name="DefaultSkin" />
+
+  <securityPolicy
+     component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+
+  <role id="zope.Anonymous" title="Everybody" />
+  <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" />
+
+  <!-- Principals -->
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User" />
+
+  <!-- Principal that tests generally run as -->
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw" />
+
+  <principal
+      id="zope.user"
+      title="User"
+      login="user"
+      password="userpw" />
+
+  <principal
+      id="zope.user2"
+      title="User2"
+      login="user2"
+      password="userpw" />
+
+  <grant role="zope.Manager" principal="zope.mgr" />
+
+  <grantAll role="zope.Manager" />
+
+</configure>

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/interfaces.py (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/tests/interfaces.py)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/interfaces.py	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/interfaces.py	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,56 @@
+##############################################################################
+#
+# 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 import interface, schema
+
+
+class ICategory(interface.Interface):
+    
+    category = schema.TextLine(
+        title = u'Category',
+        required = False)
+
+
+class IPrefs1(interface.Interface):
+
+    name = schema.TextLine(
+        title = u'Name',
+        required = True)
+
+
+class IPrefs2(interface.Interface):
+
+    location = schema.TextLine(
+        title = u'Location',
+        default = u'',
+        required = False)
+
+
+class IPrefs3(interface.Interface):
+
+    location = schema.TextLine(
+        title = u'Location',
+        default = u'',
+        required = False)
+
+
+class IPrefs4(interface.Interface):
+
+    prefs4 = schema.TextLine(
+        title = u'Prefs4',
+        default = u'',
+        required = False)

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/overrides.zcml (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/tests/overrides.zcml)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/overrides.zcml	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/overrides.zcml	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,12 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:z3ext="http://namespaces.zope.org/z3ext"
+   i18n_domain="zope">
+
+  <z3ext:layout
+     name="portal"
+     title="Test layout"
+     for="zope.app.component.interfaces.ISite"
+     template="testlayout.pt" />
+
+</configure>

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/test.pt (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/tests/test.pt)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/test.pt	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/test.pt	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,3 @@
+
+<div tal:content="request/principal/id"></div>
+<div tal:content="request/principal/title"></div>

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/testbrowser.txt (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/tests/testbrowser.txt)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/testbrowser.txt	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/testbrowser.txt	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,178 @@
+====================
+Personal preferences
+====================
+
+  >>> from zope import component, interface, event
+  >>> from zope.app.component.hooks import setSite
+  >>> from zope.security.management import newInteraction, endInteraction
+  >>> from zope.app.security.interfaces import IAuthentication
+  >>> from zope.securitypolicy.interfaces import IPrincipalRoleMap
+  >>> from z3ext.preferences.tests.interfaces import IPrefs1
+
+  >>> root = getRootFolder()
+  >>> setSite(root)
+  >>> auth = component.getUtility(IAuthentication)
+  >>> principal = auth.getPrincipal('zope.user')
+
+  >>> class Participation:
+  ...     interaction = None
+  ...     def __init__(self, principal):
+  ...         self.principal = principal
+
+  >>> newInteraction(Participation(principal))
+
+  >>> prefs = IPrefs1(principal)
+
+  >>> roles = IPrincipalRoleMap(prefs)
+  >>> roles.getPrincipalsForRole('preference.Owner')
+  (('zope.user', PermissionSetting: Allow),)
+  >>> roles.getPrincipalsForRole('content.Owner')
+  ()
+
+  >>> roles.getRolesForPrincipal('zope.user')
+  (('preference.Owner', PermissionSetting: Allow),)
+  >>> roles.getRolesForPrincipal('zope.manager')
+  ()
+
+  >>> roles.getSetting('preference.Owner', 'zope.user')
+  PermissionSetting: Allow
+
+  >>> roles.getSetting('content.Owner', 'zope.manager')
+  PermissionSetting: Unset
+
+  >>> roles.getPrincipalsAndRoles()
+  ()
+
+  >>> from z3ext.preferences.utils import hasEditableFields
+  >>> hasEditableFields(prefs)
+  True
+
+  >>> endInteraction()
+
+Browser
+
+  >>> from zope.testbrowser.testing import Browser
+
+  >>> user = Browser()
+  >>> user.handleErrors = False
+  >>> user.open("http://localhost/preferences/")
+  Traceback (most recent call last):
+  ...
+  Unauthorized: preferences
+
+  >>> user.addHeader("Authorization", "Basic user:userpw")
+
+  >>> user.open("http://localhost/preferences/")
+  >>> print user.contents
+  <html>
+  ...
+  <h1 class="z-prefs-title">Personal preferences</h1>
+  <div class="z-page-description">This area allows you to change personal preferences.</div>
+  <div class="z-prefs-content"><div class="z-form">
+  <ul class="z-listing">
+     <li>
+        <div class="z-listing-details">
+          <a href="category/">
+            Category</a>
+          <div> &nbsp;</div>
+          <ul class="z-listing">
+            <li>
+              <div class="z-listing-details">
+                <a href="category/prefs1/">
+                  Preferences 1</a>
+                <div> 
+                  &nbsp;</div>
+              </div>
+            </li>
+            <li>
+              <div class="z-listing-details">
+                <a href="category/prefs2/">
+                  Preferences 2</a>
+                <div> 
+                  &nbsp;</div>
+            </div>
+          </li>
+        </ul>
+      </div>
+    </li>
+    <li>
+      <div class="z-listing-details">
+        <a href="portal/">
+           Portal preferences</a>
+        <div>These are all the preferences related to common portal settings. &nbsp;</div>
+      </div>
+    </li>
+  </ul>
+  ...
+  </html>
+
+  >>> user.open("http://localhost/preferences/category/")
+  >>> print user.contents
+  <html>
+  ...
+  <div class="z-prefs-nav">
+    <div class="z-prefs-nav-item-selected">
+       <div class="z-level1">
+         <a href="http://localhost/preferences/category/" title="">
+           Category
+         </a>
+       </div>
+    </div>
+    <div class="z-prefs-nav-item">
+      <div class="z-level1">
+        <a href="http://localhost/preferences/portal/"
+           title="These are all the preferences related to common portal settings.">
+            Portal preferences
+        </a>
+      </div>
+    </div>
+  </div>
+  ...
+  ...<h1 class="z-prefs-title">Category</h1>
+  <div class="z-page-description"></div>
+  <div class="z-prefs-content"><div class="z-form z-form-edit"><form action="http://localhost/preferences/category/index.html"
+          method="post" enctype="multipart/form-data"
+          name="category" id="category">
+    <h1 class="z-form-label">Category</h1>
+    <div class="z-form-fieldset">
+      <div class="z-form-field">
+      <label for="category-widgets-category" title="">Category</label>
+      <div class="z-form-help"></div>
+      <div><input type="text" id="category-widgets-category"
+           name="category.widgets.category"
+           class="text-widget textline-field" value="" />
+    </div>
+    </div>
+    </div>
+      <div class="z-form-controls">
+      <span>
+        <hr />
+        <input type="submit" id="category-buttons-save"
+           name="category.buttons.save"
+           class="z-form-savebutton button-field" value="Save" />
+      </span>
+    </div>
+    </form>
+  </div>
+  <div class="z-form">
+      <h2><a href="http://localhost/preferences/category/prefs1/">Preferences 1</a></h2>
+      <div class="discreet"></div>
+      <br />
+      <h2><a href="http://localhost/preferences/category/prefs2/">Preferences 2</a></h2>
+      <div class="discreet"></div>
+      <br />
+    </div>
+  </div>
+  ...
+  </html>
+
+  >>> user.getLink('Preferences 1').click()
+  >>> user.getControl('Name').value = 'Nikolay'
+  >>> user.getControl(name="category.prefs1.buttons.save").click()
+  >>> 'Data successfully updated.' in user.contents
+  True
+
+  >>> user.open("http://localhost/preferences/category/unknown/")
+  Traceback (most recent call last):
+  ...
+  NotFound: Object: ... name: u'unknown'

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/testlayout.pt (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/tests/testlayout.pt)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/testlayout.pt	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/testlayout.pt	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,7 @@
+<html>
+  <body>
+    <div tal:content="structure provider:statusMessage"></div>
+
+    <div tal:content="structure view/render"></div>
+  </body>
+</html>

Deleted: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/tests.py
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/tests/tests.py	2009-01-08 07:26:31 UTC (rev 94610)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/tests.py	2009-01-09 02:48:48 UTC (rev 94667)
@@ -1,44 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 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.
-#
-##############################################################################
-"""Tests for the Preferences System
-
-$Id$
-"""
-import unittest, doctest
-from zope.testing import doctestunit
-from zope.component import testing
-from zope.app.testing import setup
-
-def setUp(test):
-    testing.setUp(test)
-    setup.setUpTestAsModule(test, 'z3ext.preferences.README')
-
-def tearDown(test):
-    testing.tearDown(test)
-    setup.tearDownTestAsModule(test)
-
-def test_suite():
-    return unittest.TestSuite((
-        doctest.DocFileSuite(
-            '../README.txt',
-            setUp=setUp, tearDown=tearDown,
-            globs={'pprint': doctestunit.pprint},
-            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
-        doctest.DocTestSuite(
-            '../z3ext.preferences.utils',
-            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
-        doctest.DocTestSuite(
-            '../z3ext.preferences.preferencetype',
-            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
-        ))

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/tests.py (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/tests/tests.py)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/tests.py	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/tests/tests.py	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,103 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""Tests for the Preferences System
+
+$Id$
+"""
+import os.path, unittest, doctest
+
+from zope.component import testing
+from zope.testing import doctestunit
+from zope.app.testing import setup, functional
+
+from zope.app.rotterdam import Rotterdam
+from zope.app.principalannotation import PrincipalAnnotationUtility
+from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
+from z3ext.layoutform.interfaces import ILayoutFormLayer
+
+
+class IDefaultSkin(ILayoutFormLayer, Rotterdam):
+    """ skin """
+
+
+z3extPreferences = functional.ZCMLLayer(
+    os.path.join(os.path.split(__file__)[0], 'ftesting.zcml'),
+    __name__, 'z3extPreferences', allow_teardown=True)
+
+
+def FunctionalDocFileSuite(*paths, **kw):
+    globs = kw.setdefault('globs', {})
+    globs['sync'] = functional.sync
+    globs['http'] = functional.HTTPCaller()
+    globs['getRootFolder'] = functional.getRootFolder
+
+    kw['package'] = doctest._normalize_module(kw.get('package'))
+
+    kwsetUp = kw.get('setUp')
+    def setUp(test):
+        functional.FunctionalTestSetup().setUp()
+
+        root = functional.getRootFolder()
+        root['principalannotation'] = PrincipalAnnotationUtility()
+        root.getSiteManager().registerUtility(
+            root['principalannotation'], IPrincipalAnnotationUtility)
+
+    kw['setUp'] = setUp
+
+    kwtearDown = kw.get('tearDown')
+    def tearDown(test):
+        functional.FunctionalTestSetup().tearDown()
+
+    kw['tearDown'] = tearDown
+
+    if 'optionflags' not in kw:
+        old = doctest.set_unittest_reportflags(0)
+        doctest.set_unittest_reportflags(old)
+        kw['optionflags'] = (old
+                             | doctest.ELLIPSIS
+                             | doctest.NORMALIZE_WHITESPACE)
+
+    suite = doctest.DocFileSuite(*paths, **kw)
+    suite.layer = z3extPreferences
+    return suite
+
+
+def setUp(test):
+    testing.setUp(test)
+    setup.setUpTestAsModule(test, 'z3ext.preferences.README')
+
+def tearDown(test):
+    testing.tearDown(test)
+    setup.tearDownTestAsModule(test)
+
+def notAvailable(*args):
+    return None
+
+def test_suite():
+    testbrowser = FunctionalDocFileSuite("testbrowser.txt")
+
+    return unittest.TestSuite((
+            testbrowser,
+            doctest.DocFileSuite(
+                '../README.txt',
+                setUp=setUp, tearDown=tearDown,
+                globs={'pprint': doctestunit.pprint},
+                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
+            doctest.DocTestSuite(
+                'z3ext.preferences.utils',
+                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
+            doctest.DocTestSuite(
+                'z3ext.preferences.preferencetype',
+                optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
+            ))

Deleted: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/zcml.py
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/zcml.py	2009-01-08 07:26:31 UTC (rev 94610)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/zcml.py	2009-01-09 02:48:48 UTC (rev 94667)
@@ -1,262 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-""" z3ext:preferenceGroup directive implementation
-
-$Id$
-"""
-from zope import interface
-from zope.schema import Int
-from zope.component import getUtility, queryUtility, getGlobalSiteManager
-from zope.schema.interfaces import IField
-from zope.location.interfaces import ILocation
-
-from zope.security.zcml import Permission
-from zope.security.checker import Checker, CheckerPublic
-from zope.security.interfaces import IPrincipal
-
-from zope.interface.common.mapping import IEnumerableMapping
-
-from zope.component.zcml import utility, adapter
-from zope.component.interface import provideInterface
-
-from zope.configuration import fields
-from zope.configuration.exceptions import ConfigurationError
-
-from zope.app.security.protectclass import \
-    protectName, protectSetAttribute, protectLikeUnto
-
-from preference import PreferenceGroup
-from interfaces import IPreferenceGroup
-from preferencetype import PreferenceType
-from utils import PrincipalChecker, PermissionChecker
-
-
-class IPreferenceGroupDirective(interface.Interface):
-    """Register a preference group."""
-
-    id = fields.PythonIdentifier(
-        title=u"Id",
-        description=u"""
-            Id of the preference group used to access the group. The id should
-            be a valid path in the preferences tree.""",
-        required=True)
-
-    for_ = fields.GlobalInterface(
-        title=u"For",
-        description=u"Principal interface to use this preference for.",
-        required=False)
-
-    schema = fields.GlobalInterface(
-        title=u"Schema",
-        description=u"Schema of the preference group used defining the "
-                    u"preferences of the group.",
-        required=True)
-
-    title = fields.MessageID(
-        title=u"Title",
-        description=u"Title of the preference group used in UIs.",
-        required=True)
-
-    description = fields.MessageID(
-        title=u"Description",
-        description=u"Description of the preference group used in UIs.",
-        required=False)
-
-    class_ = fields.GlobalObject(
-        title=u"Class",
-        description=u"Custom IPreferenceGroup implementation.",
-        required=False)
-
-    provides = fields.Tokens(
-	title = u'Provides',
-        required = False,
-        value_type = fields.GlobalInterface())
-
-    permission = Permission(
-        title = u'Permission',
-        description = u'Default set schema permission.',
-        required = False)
-
-    accesspermission = Permission(
-        title = u'Access 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)
-
-    order = Int(
-        title = u'Order',
-        default = 999999,
-        required = False)
-
-
-class PreferenceGroupAdapter(object):
-
-    def __init__(self, name):
-        self.name = name
-
-    def __call__(self, principal, context=None):
-        prefs = getUtility(IPreferenceGroup, self.name)
-        return prefs.__bind__(principal, context)
-
-
-class PreferenceGroupDirective(object):
-
-    def __init__(self, _context, id, schema, title,
-                 for_=None, description=u'', class_=None, provides=[],
-                 permission='z3ext.ModifyPreference', accesspermission='',
-                 tests=(), order = 9999):
-
-        if not accesspermission:
-            accesspermission = permission
-
-        Class = PreferenceType(str(id), schema, class_, title, description)
-        Class.order = order
-        Class.__permission__ = permission
-        Class.__accesspermission__ = accesspermission
-
-        tests = tuple(tests)
-        if permission != 'zope.Public':
-            tests = tests + (PermissionChecker,)
-        if interface.interfaces.IInterface.providedBy(for_):
-            tests = tests + (PrincipalChecker(for_),)
-
-        group = Class(tests)
-
-        utility(_context, IPreferenceGroup, group, name=id)
-        adapter(_context, (PreferenceGroupAdapter(id),), schema,
-                (for_ or IPrincipal,))
-        adapter(_context, (PreferenceGroupAdapter(id),), schema,
-                (for_ or IPrincipal, interface.Interface))
-
-        interface.classImplements(Class, *provides)
-
-        self._class = Class
-        self._context = _context
-        self._permission = permission
-
-        self.require(_context, permission, set_schema=(schema,))
-        self.require(_context, accesspermission,
-                     interface=(IPreferenceGroup, schema))
-
-        self.require(_context, CheckerPublic,
-                     interface=(IEnumerableMapping, ILocation),
-                     attributes=('isAvailable',
-                                 '__id__', '__schema__',
-                                 '__title__', '__description__',
-                                 '__permission__'))
-
-        schema.setTaggedValue('preferenceID', id)
-
-        _context.action(
-            discriminator=('z3ext:preferences', schema),
-            callable=addSubgroup, args=(group,))
-
-    def require(self, _context,
-                permission=None, attributes=None, interface=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):
-            if like_class:
-                return
-            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:preferences:protectName', 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:preferences:protectSetAttribute', 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:preferences:protectSetAttribute', object()),
-                    callable = protectSetAttribute,
-                    args = (self._class, name, permission_id))
-
-        _context.action(
-            discriminator = None,
-            callable = provideInterface,
-            args = (schema.__module__+'.'+schema.getName(), schema))
-
-
-def addSubgroup(group):
-    if '.' in group.__id__:
-        parentId = group.__id__.split('.')[0]
-    else:
-        parentId = ''
-
-    parent = queryUtility(IPreferenceGroup, parentId)
-    if parent is None:
-        parent = getGlobalSiteManager().getUtility(IPreferenceGroup, parentId)
-
-    parent.add(group.__name__)
-    group.__parent__ = parent

Copied: z3ext.preferences/tags/1.4.5/src/z3ext/preferences/zcml.py (from rev 94666, z3ext.preferences/trunk/src/z3ext/preferences/zcml.py)
===================================================================
--- z3ext.preferences/tags/1.4.5/src/z3ext/preferences/zcml.py	                        (rev 0)
+++ z3ext.preferences/tags/1.4.5/src/z3ext/preferences/zcml.py	2009-01-09 02:48:48 UTC (rev 94667)
@@ -0,0 +1,262 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" z3ext:preferenceGroup directive implementation
+
+$Id$
+"""
+from zope import interface
+from zope.schema import Int
+from zope.component import getUtility, queryUtility, getGlobalSiteManager
+from zope.schema.interfaces import IField
+from zope.location.interfaces import ILocation
+
+from zope.security.zcml import Permission
+from zope.security.checker import Checker, CheckerPublic
+from zope.security.interfaces import IPrincipal
+
+from zope.interface.common.mapping import IEnumerableMapping
+
+from zope.component.zcml import utility, adapter
+from zope.component.interface import provideInterface
+
+from zope.configuration import fields
+from zope.configuration.exceptions import ConfigurationError
+
+from zope.app.security.protectclass import \
+    protectName, protectSetAttribute, protectLikeUnto
+
+from preference import PreferenceGroup
+from interfaces import IPreferenceGroup
+from preferencetype import PreferenceType
+from utils import PrincipalChecker, PermissionChecker
+
+
+class IPreferenceGroupDirective(interface.Interface):
+    """Register a preference group."""
+
+    id = fields.PythonIdentifier(
+        title=u"Id",
+        description=u"""
+            Id of the preference group used to access the group. The id should
+            be a valid path in the preferences tree.""",
+        required=True)
+
+    for_ = fields.GlobalInterface(
+        title=u"For",
+        description=u"Principal interface to use this preference for.",
+        required=False)
+
+    schema = fields.GlobalInterface(
+        title=u"Schema",
+        description=u"Schema of the preference group used defining the "
+                    u"preferences of the group.",
+        required=True)
+
+    title = fields.MessageID(
+        title=u"Title",
+        description=u"Title of the preference group used in UIs.",
+        required=True)
+
+    description = fields.MessageID(
+        title=u"Description",
+        description=u"Description of the preference group used in UIs.",
+        required=False)
+
+    class_ = fields.GlobalObject(
+        title=u"Class",
+        description=u"Custom IPreferenceGroup implementation.",
+        required=False)
+
+    provides = fields.Tokens(
+	title = u'Provides',
+        required = False,
+        value_type = fields.GlobalInterface())
+
+    permission = Permission(
+        title = u'Permission',
+        description = u'Default set schema permission.',
+        required = False)
+
+    accesspermission = Permission(
+        title = u'Access 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)
+
+    order = Int(
+        title = u'Order',
+        default = 999999,
+        required = False)
+
+
+class PreferenceGroupAdapter(object):
+
+    def __init__(self, name):
+        self.name = name
+
+    def __call__(self, principal, context=None):
+        prefs = getUtility(IPreferenceGroup, self.name)
+        return prefs.__bind__(principal, context)
+
+
+class PreferenceGroupDirective(object):
+
+    def __init__(self, _context, id, schema, title,
+                 for_=None, description=u'', class_=None, provides=[],
+                 permission='z3ext.ModifyPreference', 
+                 accesspermission='z3ext.ModifyPreference', tests=(), order = 9999):
+
+        if not accesspermission:
+            accesspermission = permission
+
+        Class = PreferenceType(str(id), schema, class_, title, description)
+        Class.order = order
+        Class.__permission__ = permission
+        Class.__accesspermission__ = accesspermission
+
+        tests = tuple(tests)
+        if permission != 'zope.Public':
+            tests = tests + (PermissionChecker,)
+        if interface.interfaces.IInterface.providedBy(for_):
+            tests = tests + (PrincipalChecker(for_),)
+
+        group = Class(tests)
+
+        utility(_context, IPreferenceGroup, group, name=id)
+        adapter(_context, (PreferenceGroupAdapter(id),), schema,
+                (for_ or IPrincipal,))
+        adapter(_context, (PreferenceGroupAdapter(id),), schema,
+                (for_ or IPrincipal, interface.Interface))
+
+        interface.classImplements(Class, *provides)
+
+        self._class = Class
+        self._context = _context
+        self._permission = permission
+
+        self.require(_context, permission, set_schema=(schema,))
+        self.require(_context, accesspermission,
+                     interface=(IPreferenceGroup, schema))
+
+        self.require(_context, CheckerPublic,
+                     interface=(IEnumerableMapping, ILocation),
+                     attributes=('isAvailable',
+                                 '__id__', '__schema__',
+                                 '__title__', '__description__',
+                                 '__permission__'))
+
+        schema.setTaggedValue('preferenceID', id)
+
+        _context.action(
+            discriminator=('z3ext:preferences', schema),
+            callable=addSubgroup, args=(group,))
+
+    def require(self, _context,
+                permission=None, attributes=None, interface=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):
+            if like_class:
+                return
+            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:preferences:protectName', 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:preferences:protectSetAttribute', 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:preferences:protectSetAttribute', object()),
+                    callable = protectSetAttribute,
+                    args = (self._class, name, permission_id))
+
+        _context.action(
+            discriminator = None,
+            callable = provideInterface,
+            args = (schema.__module__+'.'+schema.getName(), schema))
+
+
+def addSubgroup(group):
+    if '.' in group.__id__:
+        parentId = group.__id__.split('.')[0]
+    else:
+        parentId = ''
+
+    parent = queryUtility(IPreferenceGroup, parentId)
+    if parent is None:
+        parent = getGlobalSiteManager().getUtility(IPreferenceGroup, parentId)
+
+    parent.add(group.__name__)
+    group.__parent__ = parent



More information about the Checkins mailing list