[Checkins] SVN: z3ext.preferences/tags/1.1.0/ egg 1.1.0
Nikolay Kim
fafhrd at datacom.kz
Fri Apr 11 07:54:02 EDT 2008
Log message for revision 85237:
egg 1.1.0
Changed:
A z3ext.preferences/tags/1.1.0/
D z3ext.preferences/tags/1.1.0/CHANGES.txt
A z3ext.preferences/tags/1.1.0/CHANGES.txt
D z3ext.preferences/tags/1.1.0/setup.py
A z3ext.preferences/tags/1.1.0/setup.py
D z3ext.preferences/tags/1.1.0/src/z3ext/preferences/README.txt
A z3ext.preferences/tags/1.1.0/src/z3ext/preferences/README.txt
D z3ext.preferences/tags/1.1.0/src/z3ext/preferences/configure.zcml
A z3ext.preferences/tags/1.1.0/src/z3ext/preferences/configure.zcml
D z3ext.preferences/tags/1.1.0/src/z3ext/preferences/interfaces.py
A z3ext.preferences/tags/1.1.0/src/z3ext/preferences/interfaces.py
D z3ext.preferences/tags/1.1.0/src/z3ext/preferences/preference.py
A z3ext.preferences/tags/1.1.0/src/z3ext/preferences/preference.py
D z3ext.preferences/tags/1.1.0/src/z3ext/preferences/root.py
A z3ext.preferences/tags/1.1.0/src/z3ext/preferences/root.py
D z3ext.preferences/tags/1.1.0/src/z3ext/preferences/utils.py
A z3ext.preferences/tags/1.1.0/src/z3ext/preferences/utils.py
D z3ext.preferences/tags/1.1.0/src/z3ext/preferences/zcml.py
A z3ext.preferences/tags/1.1.0/src/z3ext/preferences/zcml.py
-=-
Copied: z3ext.preferences/tags/1.1.0 (from rev 85230, z3ext.preferences/trunk)
Deleted: z3ext.preferences/tags/1.1.0/CHANGES.txt
===================================================================
--- z3ext.preferences/trunk/CHANGES.txt 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/CHANGES.txt 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,42 +0,0 @@
-=======
-CHANGES
-=======
-
-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.1.0/CHANGES.txt (from rev 85236, z3ext.preferences/trunk/CHANGES.txt)
===================================================================
--- z3ext.preferences/tags/1.1.0/CHANGES.txt (rev 0)
+++ z3ext.preferences/tags/1.1.0/CHANGES.txt 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,48 @@
+=======
+CHANGES
+=======
+
+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.1.0/setup.py
===================================================================
--- z3ext.preferences/trunk/setup.py 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/setup.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,85 +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.0.3dev'
-
-
-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.i18nmessageid',
- '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',
- ],
- extras_require = dict(test=['zope.app.testing',
- 'zope.testing',
- ]),
- include_package_data = True,
- zip_safe = False
- )
Copied: z3ext.preferences/tags/1.1.0/setup.py (from rev 85236, z3ext.preferences/trunk/setup.py)
===================================================================
--- z3ext.preferences/tags/1.1.0/setup.py (rev 0)
+++ z3ext.preferences/tags/1.1.0/setup.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,85 @@
+##############################################################################
+#
+# 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.1.0'
+
+
+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.i18nmessageid',
+ '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',
+ ],
+ extras_require = dict(test=['zope.app.testing',
+ 'zope.testing',
+ ]),
+ include_package_data = True,
+ zip_safe = False
+ )
Deleted: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/README.txt
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/README.txt 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/README.txt 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,429 +0,0 @@
-================
-User Preferences
-================
-
-Implementing user preferences is usually a painful task, since it requires a
-lot of custom coding and constantly changing preferences makes it hard to
-maintain the data and UI. The `preference` package
-
- >>> from z3ext.preferences import interfaces, preference, preferencetype
-
-eases this pain by providing a generic user preferences framework that uses
-schemas to categorize and describe the preferences.
-
-We also have to do some additional setup beforehand:
-
- >>> from zope.app.testing import setup
-
- >>> import zope.app.component.hooks
- >>> zope.app.component.hooks.setHooks()
- >>> setup.setUpTraversal()
- >>> setup.setUpSiteManagerLookup()
-
-
-Preference Groups
-------------------
-
-Preferences are grouped in preference groups and the preferences inside a
-group are specified via the preferences group schema:
-
- >>> import zope.schema
- >>> import zope.interface
-
- >>> class IZMIUserSettings(zope.interface.Interface):
- ... """Basic User Preferences"""
- ...
- ... email = zope.schema.TextLine(
- ... title=u"E-mail Address",
- ... description=u"E-mail Address used to send notifications")
- ...
- ... skin = zope.schema.Choice(
- ... title=u"Skin",
- ... description=u"The skin that should be used for the ZMI.",
- ... values=['Rotterdam', 'ZopeTop', 'Basic'],
- ... default='Rotterdam')
- ...
- ... showZopeLogo = zope.schema.Bool(
- ... title=u"Show Zope Logo",
- ... description=u"Specifies whether Zope logo should be displayed "
- ... u"at the top of the screen.",
- ... default=True)
-
-Each preference group must have an
-ID by which it can be accessed and optional title and description fields for UI
-purposes. Before create preference group we should create unique class for
-our preferences:
-
- >>> settingsClass = preferencetype.PreferenceType(
- ... "ZMISettings",
- ... IZMIUserSettings,
- ... title=u"ZMI User Settings", description=u"")
-
-Now we can instantiate the preference group.
-
- >>> settings = settingsClass()
-
-We can't change schema for preference group:
-
- >>> settings.__schema__ = IZMIUserSettings
- Traceback (most recent call last):
- ...
- AttributeError: Can't set __schema__
-
-
-Note that the preferences group provides the interface it is representing:
-
- >>> IZMIUserSettings.providedBy(settings)
- True
-
-and the id, schema and title of the group are directly available:
-
- >>> settings.__id__
- u'ZMISettings'
- >>> settings.__schema__
- <InterfaceClass z3ext.preferences.README.IZMIUserSettings>
- >>> settings.__title__
- u'ZMI User Settings'
-
-So let's ask the preference group for the `skin` setting:
-
- >>> settings.skin
- Traceback (most recent call last):
- ...
- UnboundPreferenceGroup
-
-
-So why did the lookup fail? Because we have not specified a principal yet, for
-which we want to lookup the preferences. To do that, we have to create a principal:
-
- >>> class Principal:
- ... def __init__(self, id):
- ... self.id = id
- >>> principal = Principal('zope.user')
-
- >>> class Participation:
- ... interaction = None
- ... def __init__(self, principal):
- ... self.principal = principal
-
- >>> participation = Participation(principal)
-
- >>> import zope.security.management
- >>> zope.security.management.newInteraction(participation)
-
-We also need an IAnnotations adapter for principals, so we can store the
-settings:
-
- >>> from zope.annotation.interfaces import IAnnotations
- >>> class PrincipalAnnotations(dict):
- ... zope.interface.implements(IAnnotations)
- ... data = {}
- ... def __new__(class_, principal, context):
- ... try:
- ... annotations = class_.data[principal.id]
- ... except KeyError:
- ... annotations = dict.__new__(class_)
- ... class_.data[principal.id] = annotations
- ... return annotations
- ... def __init__(self, principal, context):
- ... pass
-
- >>> from zope import component
- >>> component.provideAdapter(
- ... PrincipalAnnotations,
- ... (Principal, zope.interface.Interface), IAnnotations)
-
-And now we need bind preferences to principal. We can just call __bind__
-method in this case preference will use principal from current interaction.
-
- >>> nsettings = settings.__bind__()
- >>> interfaces.IBound.providedBy(nsettings)
- True
-
- >>> nsettings.__principal__ == principal
- True
-
-Or we can explicitly set principal, this is usefull when we want to know
-preferences for principal.
-
- >>> settings = settings.__bind__(principal=principal)
- >>> interfaces.IBound.providedBy(nsettings)
- True
-
-Let's now try to access the settings again:
-
- >>> settings.skin
- 'Rotterdam'
-
-which is the default value, since we have not set it yet. We can now reassign
-the value:
-
- >>> settings.skin = 'Basic'
- >>> settings.skin
- 'Basic'
-
-However, you cannot just enter any value, since it is validated before the
-assignment:
-
- >>> settings.skin = 'MySkin'
- Traceback (most recent call last):
- ...
- ConstraintNotSatisfied: MySkin
-
-
-Preference Group Trees
-----------------------
-
-The preferences would not be very powerful, if you could create a full
-preferences. So let's create a sub-group for our ZMI user settings, where we
-can adjust the look and feel of the folder contents view:
-
- >>> import sets
- >>> class IFolderSettings(zope.interface.Interface):
- ... """Basic User Preferences"""
- ...
- ... shownFields = zope.schema.Set(
- ... title=u"Shown Fields",
- ... description=u"Fields shown in the table.",
- ... value_type=zope.schema.Choice(['name', 'size', 'creator']),
- ... default=sets.Set(['name', 'size']))
- ...
- ... sortedBy = zope.schema.Choice(
- ... title=u"Sorted By",
- ... description=u"Data field to sort by.",
- ... values=['name', 'size', 'creator'],
- ... default='name')
-
- >>> folderSettingsClass = preferencetype.PreferenceType(
- ... "ZMISettings.Folder",
- ... IFolderSettings,
- ... title=u"Folder Content View Settings")
-
- >>> folderSettings = folderSettingsClass()
-
-Note that the id was chosen so that the parent id is the prefix of the child's
-id. Our new preference sub-group should now be available as an attribute or an
-item on the parent group ...
-
- >>> settings['Folder']
- Traceback (most recent call last):
- ...
- KeyError: 'Folder'
-
-but not before we register the groups as utilities:
-
- >>> from zope import component
- >>> siteManager = component.getSiteManager()
-
- >>> siteManager.registerUtility(
- ... settings, interfaces.IPreferenceGroup, 'ZMISettings')
- >>> siteManager.registerUtility(
- ... folderSettings, interfaces.IPreferenceGroup, 'ZMISettings.Folder')
-
-If we now try to lookup the sub-group again, we should be successful:
-
- >>> settings['Folder']
- <z3ext.preferences.preferencetype.Preference<ZMISettings.Folder> ...>
-
-In z3ext.preferences we can't access to subfolder as attribute, this
-is one of difference from zope.app.preference.
-
- >>> settings['Folder'].sortedBy = 'size'
- >>> settings['Folder'].sortedBy
- 'size'
-
-While the registry of the preference groups is flat, the careful naming of the
-ids allows us to have a tree of preferences. Note that this pattern is very
-similar to the way modules are handled in Python; they are stored in a flat
-dictionary in ``sys.modules``, but due to the naming they appear to be in a
-namespace tree.
-
-While we are at it, there are also preference categories that can be compared
-to Python packages. They basically are just a higher level grouping concept
-that is used by the UI to better organize the preferences. A preference group
-can be converted to a category by simply providing an additional interface:
-
- >>> zope.interface.alsoProvides(settings, interfaces.IPreferenceCategory)
-
- >>> interfaces.IPreferenceCategory.providedBy(settings)
- True
-
-Clear:
-
- >>> t = siteManager.unregisterUtility(
- ... settings, interfaces.IPreferenceGroup, 'ZMISettings')
- >>> t = siteManager.unregisterUtility(
- ... folderSettings, interfaces.IPreferenceGroup, 'ZMISettings.Folder')
-
-
-Creating Preference Groups Using ZCML
--------------------------------------
-
-If you are using the user preference system in Zope 3, you will not have to
-manually setup the preference groups as we did above (of course). We will use
-ZCML instead. First, we need to register the directives:
-
- >>> from zope.configuration import xmlconfig
- >>> import z3ext.preferences
- >>> context = xmlconfig.file('meta.zcml', z3ext.preferences)
-
-Second we need root preference group:
-
- >>> from z3ext.preferences.root import PersonalPreferences
-
- >>> siteManager.registerUtility(
- ... PersonalPreferences(), interfaces.IPreferenceGroup)
-
-Then the system sets up a root preference group:
-
- >>> context = xmlconfig.string('''
- ... <configure
- ... xmlns:z3ext="http://namespaces.zope.org/z3ext" i18n_domain="test">
- ...
- ... <z3ext:preferenceGroup
- ... id="ZMISettings"
- ... schema="z3ext.preferences.README.IZMIUserSettings"
- ... title="ZMI User Settings" />
- ...
- ... <z3ext:preferenceGroup
- ... id="ZMISettings.Folder"
- ... schema="z3ext.preferences.README.IFolderSettings"
- ... title="Folder Content View Settings" />
- ...
- ... </configure>''', context)
-
-Now we can use the preference system in its intended way. We access the folder
-settings as follows:
-
- >>> prefs = component.getUtility(interfaces.IPreferenceGroup)
-
-Don't forget to bind preferences to principal
-
- >>> prefs = prefs.__bind__(principal=principal)
- >>> prefs['ZMISettings']['Folder'].sortedBy
- 'size'
-
- >>> prefs.items()
- [(u'ZMISettings', <z3ext.preferences.preferencetype.Preference<ZMISettings> ...>)]
-
- >>> u'ZMISettings' in prefs
- True
-
- >>> prefs.keys()
- (u'ZMISettings',)
-
- >>> prefs.values()
- [<z3ext.preferences.preferencetype.Preference<ZMISettings> ...>]
-
- >>> list(iter(prefs))
- [<z3ext.preferences.preferencetype.Preference<ZMISettings> ...>]
-
- >>> len(prefs)
- 1
-
-
-Let's register the ZMI settings again under a new name via ZCML:
-
- >>> context = xmlconfig.string('''
- ... <configure
- ... xmlns:z3ext="http://namespaces.zope.org/z3ext"
- ... i18n_domain="test">
- ...
- ... <z3ext:preferenceGroup
- ... id="ZMISettings2"
- ... title="ZMI Settings NG"
- ... schema="z3ext.preferences.README.IZMIUserSettings"
- ... provides="z3ext.preferences.interfaces.IPreferenceCategory" />
- ...
- ... </configure>''', context)
-
- >>> prefs['ZMISettings2']
- <z3ext.preferences.preferencetype.Preference<ZMISettings2> ...>
-
- >>> prefs['ZMISettings2'].__title__
- u'ZMI Settings NG'
-
- >>> IZMIUserSettings.providedBy(prefs['ZMISettings2'])
- True
- >>> interfaces.IPreferenceCategory.providedBy(prefs['ZMISettings2'])
- True
-
-And the tree can built again by carefully constructing the id:
-
- >>> context = xmlconfig.string('''
- ... <configure
- ... xmlns:z3ext="http://namespaces.zope.org/z3ext"
- ... i18n_domain="test">
- ...
- ... <z3ext:preferenceGroup
- ... id="ZMISettings2.Folder"
- ... title="Folder Settings"
- ... schema="z3ext.preferences.README.IFolderSettings" />
- ...
- ... </configure>''', context)
-
- >>> prefs['ZMISettings2']
- <z3ext.preferences.preferencetype.Preference<ZMISettings2> ...>
-
- >>> prefs['ZMISettings2'].items()
- [(u'ZMISettings2.Folder', <z3ext.preferences.preferencetype.Preference<ZMISettings2.Folder> ...)]
-
- >>> list(iter(prefs['ZMISettings2']))
- [<z3ext.preferences.preferencetype.Preference<ZMISettings2.Folder> ...>]
-
- >>> prefs['ZMISettings2']['Folder'].__title__
- u'Folder Settings'
-
- >>> IFolderSettings.providedBy(prefs['ZMISettings2']['Folder'])
- True
- >>> interfaces.IPreferenceCategory.providedBy(prefs['ZMISettings2']['Folder'])
- False
-
-
-Simple Python-Level Access
---------------------------
-
-If a site is set, getting the user preferences is very simple:
-
- >>> prefs2 = component.getUtility(interfaces.IPreferenceGroup, 'ZMISettings.Folder')
- >>> prefs2 = prefs2.__bind__(principal=principal)
-
- >>> prefs2.sortedBy
- 'size'
-
-
-Security
---------
-
-You might already wonder under which permissions the preferences are
-available. They are actually available publicly (`CheckerPublic`), but that
-is not a problem, since the available values are looked up specifically for
-the current user. And why should a user not have full access to his/her
-preferences? But sometimes we need preferences which can be changed
-only by manager. In this case we can provide default permission or
-even set security checks on field level, like in <class /> directive.
-
- >>> import zope.security
- >>> context = xmlconfig.file('meta.zcml', zope.security, context)
-
- >>> context = xmlconfig.string('''
- ... <configure
- ... xmlns="http://namespaces.zope.org/zope"
- ... xmlns:z3ext="http://namespaces.zope.org/z3ext"
- ... i18n_domain="z3ext">
- ...
- ... <permission id="zope.View" title="zope view" />
- ... <permission id="zope.Manage" title="zope manage" />
- ...
- ... <z3ext:preferenceGroup
- ... id="ZMISettings3"
- ... title="ZMI Settings 3"
- ... schema="z3ext.preferences.README.IZMIUserSettings"
- ... provides="z3ext.preferences.interfaces.IPreferenceCategory"
- ... permission="zope.View">
- ... <require
- ... attributes="showZopeLogo" permission="zope.Manage" />
- ... </z3ext:preferenceGroup>
- ...
- ... </configure>''', context)
-
Copied: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/README.txt (from rev 85236, z3ext.preferences/trunk/src/z3ext/preferences/README.txt)
===================================================================
--- z3ext.preferences/tags/1.1.0/src/z3ext/preferences/README.txt (rev 0)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/README.txt 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,461 @@
+================
+User Preferences
+================
+
+Implementing user preferences is usually a painful task, since it requires a
+lot of custom coding and constantly changing preferences makes it hard to
+maintain the data and UI. The `preference` package
+
+ >>> from z3ext.preferences import interfaces, preference, preferencetype
+
+eases this pain by providing a generic user preferences framework that uses
+schemas to categorize and describe the preferences.
+
+We also have to do some additional setup beforehand:
+
+ >>> from zope.app.testing import setup
+
+ >>> import zope.app.component.hooks
+ >>> zope.app.component.hooks.setHooks()
+ >>> setup.setUpTraversal()
+ >>> setup.setUpSiteManagerLookup()
+
+
+Preference Groups
+------------------
+
+Preferences are grouped in preference groups and the preferences inside a
+group are specified via the preferences group schema:
+
+ >>> import zope.schema
+ >>> import zope.interface
+
+ >>> class IZMIUserSettings(zope.interface.Interface):
+ ... """Basic User Preferences"""
+ ...
+ ... email = zope.schema.TextLine(
+ ... title=u"E-mail Address",
+ ... description=u"E-mail Address used to send notifications")
+ ...
+ ... skin = zope.schema.Choice(
+ ... title=u"Skin",
+ ... description=u"The skin that should be used for the ZMI.",
+ ... values=['Rotterdam', 'ZopeTop', 'Basic'],
+ ... default='Rotterdam')
+ ...
+ ... showZopeLogo = zope.schema.Bool(
+ ... title=u"Show Zope Logo",
+ ... description=u"Specifies whether Zope logo should be displayed "
+ ... u"at the top of the screen.",
+ ... default=True)
+
+Each preference group must have an
+ID by which it can be accessed and optional title and description fields for UI
+purposes. Before create preference group we should create unique class for
+our preferences:
+
+ >>> settingsClass = preferencetype.PreferenceType(
+ ... "ZMISettings",
+ ... IZMIUserSettings,
+ ... title=u"ZMI User Settings", description=u"")
+
+Now we can instantiate the preference group.
+
+ >>> settings = settingsClass()
+
+We can't change schema for preference group:
+
+ >>> settings.__schema__ = IZMIUserSettings
+ Traceback (most recent call last):
+ ...
+ AttributeError: Can't set __schema__
+
+
+Note that the preferences group provides the interface it is representing:
+
+ >>> IZMIUserSettings.providedBy(settings)
+ True
+
+and the id, schema and title of the group are directly available:
+
+ >>> settings.__id__
+ u'ZMISettings'
+ >>> settings.__schema__
+ <InterfaceClass z3ext.preferences.README.IZMIUserSettings>
+ >>> settings.__title__
+ u'ZMI User Settings'
+
+So let's ask the preference group for the `skin` setting:
+
+ >>> settings.skin
+ Traceback (most recent call last):
+ ...
+ UnboundPreferenceGroup
+
+
+So why did the lookup fail? Because we have not specified a principal yet, for
+which we want to lookup the preferences. To do that, we have to create a principal:
+
+ >>> class Principal:
+ ... def __init__(self, id):
+ ... self.id = id
+ >>> principal = Principal('zope.user')
+
+ >>> class Participation:
+ ... interaction = None
+ ... def __init__(self, principal):
+ ... self.principal = principal
+
+ >>> participation = Participation(principal)
+
+ >>> import zope.security.management
+ >>> zope.security.management.newInteraction(participation)
+
+We also need an IAnnotations adapter for principals, so we can store the
+settings:
+
+ >>> from zope.annotation.interfaces import IAnnotations
+ >>> class PrincipalAnnotations(dict):
+ ... zope.interface.implements(IAnnotations)
+ ... data = {}
+ ... def __new__(class_, principal, context):
+ ... try:
+ ... annotations = class_.data[principal.id]
+ ... except KeyError:
+ ... annotations = dict.__new__(class_)
+ ... class_.data[principal.id] = annotations
+ ... return annotations
+ ... def __init__(self, principal, context):
+ ... pass
+
+ >>> from zope import component
+ >>> component.provideAdapter(
+ ... PrincipalAnnotations,
+ ... (Principal, zope.interface.Interface), IAnnotations)
+
+And now we need bind preferences to principal. We can just call __bind__
+method in this case preference will use principal from current interaction.
+
+ >>> nsettings = settings.__bind__()
+ >>> interfaces.IBound.providedBy(nsettings)
+ True
+
+ >>> nsettings.__principal__ == principal
+ True
+
+Or we can explicitly set principal, this is usefull when we want to know
+preferences for principal.
+
+ >>> settings = settings.__bind__(principal=principal)
+ >>> interfaces.IBound.providedBy(nsettings)
+ True
+
+Let's now try to access the settings again:
+
+ >>> settings.skin
+ 'Rotterdam'
+
+which is the default value, since we have not set it yet. We can now reassign
+the value:
+
+ >>> settings.skin = 'Basic'
+ >>> settings.skin
+ 'Basic'
+
+However, you cannot just enter any value, since it is validated before the
+assignment:
+
+ >>> settings.skin = 'MySkin'
+ Traceback (most recent call last):
+ ...
+ ConstraintNotSatisfied: MySkin
+
+
+Preference Group Trees
+----------------------
+
+The preferences would not be very powerful, if you could create a full
+preferences. So let's create a sub-group for our ZMI user settings, where we
+can adjust the look and feel of the folder contents view:
+
+ >>> import sets
+ >>> class IFolderSettings(zope.interface.Interface):
+ ... """Basic User Preferences"""
+ ...
+ ... shownFields = zope.schema.Set(
+ ... title=u"Shown Fields",
+ ... description=u"Fields shown in the table.",
+ ... value_type=zope.schema.Choice(['name', 'size', 'creator']),
+ ... default=sets.Set(['name', 'size']))
+ ...
+ ... sortedBy = zope.schema.Choice(
+ ... title=u"Sorted By",
+ ... description=u"Data field to sort by.",
+ ... values=['name', 'size', 'creator'],
+ ... default='name')
+
+ >>> folderSettingsClass = preferencetype.PreferenceType(
+ ... "ZMISettings.Folder",
+ ... IFolderSettings,
+ ... title=u"Folder Content View Settings")
+
+ >>> folderSettings = folderSettingsClass()
+
+Note that the id was chosen so that the parent id is the prefix of the child's
+id. Our new preference sub-group should now be available as an attribute or an
+item on the parent group ...
+
+ >>> settings['Folder']
+ Traceback (most recent call last):
+ ...
+ KeyError: 'Folder'
+
+but not before we register the groups as utilities:
+
+ >>> from zope import component
+ >>> siteManager = component.getSiteManager()
+
+ >>> siteManager.registerUtility(
+ ... settings, interfaces.IPreferenceGroup, 'ZMISettings')
+ >>> siteManager.registerUtility(
+ ... folderSettings, interfaces.IPreferenceGroup, 'ZMISettings.Folder')
+
+If we now try to lookup the sub-group again, we should be successful:
+
+ >>> settings['Folder']
+ <z3ext.preferences.preferencetype.Preference<ZMISettings.Folder> ...>
+
+In z3ext.preferences we can't access to subfolder as attribute, this
+is one of difference from zope.app.preference.
+
+ >>> settings['Folder'].sortedBy = 'size'
+ >>> settings['Folder'].sortedBy
+ 'size'
+
+While the registry of the preference groups is flat, the careful naming of the
+ids allows us to have a tree of preferences. Note that this pattern is very
+similar to the way modules are handled in Python; they are stored in a flat
+dictionary in ``sys.modules``, but due to the naming they appear to be in a
+namespace tree.
+
+While we are at it, there are also preference categories that can be compared
+to Python packages. They basically are just a higher level grouping concept
+that is used by the UI to better organize the preferences. A preference group
+can be converted to a category by simply providing an additional interface:
+
+ >>> zope.interface.alsoProvides(settings, interfaces.IPreferenceCategory)
+
+ >>> interfaces.IPreferenceCategory.providedBy(settings)
+ True
+
+Clear:
+
+ >>> t = siteManager.unregisterUtility(
+ ... settings, interfaces.IPreferenceGroup, 'ZMISettings')
+ >>> t = siteManager.unregisterUtility(
+ ... folderSettings, interfaces.IPreferenceGroup, 'ZMISettings.Folder')
+
+
+Creating Preference Groups Using ZCML
+-------------------------------------
+
+If you are using the user preference system in Zope 3, you will not have to
+manually setup the preference groups as we did above (of course). We will use
+ZCML instead. First, we need to register the directives:
+
+ >>> from zope.configuration import xmlconfig
+ >>> import z3ext.preferences
+ >>> context = xmlconfig.file('meta.zcml', z3ext.preferences)
+
+Second we need root preference group:
+
+ >>> from z3ext.preferences.root import PersonalPreferences
+
+ >>> siteManager.registerUtility(
+ ... PersonalPreferences(), interfaces.IPreferenceGroup)
+
+Then the system sets up a root preference group:
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns:z3ext="http://namespaces.zope.org/z3ext" i18n_domain="test">
+ ...
+ ... <z3ext:preferenceGroup
+ ... id="ZMISettings"
+ ... schema="z3ext.preferences.README.IZMIUserSettings"
+ ... title="ZMI User Settings" />
+ ...
+ ... <z3ext:preferenceGroup
+ ... id="ZMISettings.Folder"
+ ... schema="z3ext.preferences.README.IFolderSettings"
+ ... title="Folder Content View Settings" />
+ ...
+ ... </configure>''', context)
+
+Now we can use the preference system in its intended way. We access the folder
+settings as follows:
+
+ >>> prefs = component.getUtility(interfaces.IPreferenceGroup)
+
+Don't forget to bind preferences to principal
+
+ >>> prefs = prefs.__bind__(principal=principal)
+ >>> prefs['ZMISettings']['Folder'].sortedBy
+ 'size'
+
+ >>> prefs.items()
+ [(u'ZMISettings', <z3ext.preferences.preferencetype.Preference<ZMISettings> ...>)]
+
+ >>> u'ZMISettings' in prefs
+ True
+
+ >>> prefs.keys()
+ (u'ZMISettings',)
+
+ >>> prefs.values()
+ [<z3ext.preferences.preferencetype.Preference<ZMISettings> ...>]
+
+ >>> list(iter(prefs))
+ [<z3ext.preferences.preferencetype.Preference<ZMISettings> ...>]
+
+ >>> len(prefs)
+ 1
+
+
+Let's register the ZMI settings again under a new name via ZCML:
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns:z3ext="http://namespaces.zope.org/z3ext"
+ ... i18n_domain="test">
+ ...
+ ... <z3ext:preferenceGroup
+ ... id="ZMISettings2"
+ ... title="ZMI Settings NG"
+ ... schema="z3ext.preferences.README.IZMIUserSettings"
+ ... provides="z3ext.preferences.interfaces.IPreferenceCategory" />
+ ...
+ ... </configure>''', context)
+
+ >>> prefs['ZMISettings2']
+ <z3ext.preferences.preferencetype.Preference<ZMISettings2> ...>
+
+ >>> prefs['ZMISettings2'].__title__
+ u'ZMI Settings NG'
+
+ >>> IZMIUserSettings.providedBy(prefs['ZMISettings2'])
+ True
+ >>> interfaces.IPreferenceCategory.providedBy(prefs['ZMISettings2'])
+ True
+
+And the tree can built again by carefully constructing the id:
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns:z3ext="http://namespaces.zope.org/z3ext"
+ ... i18n_domain="test">
+ ...
+ ... <z3ext:preferenceGroup
+ ... id="ZMISettings2.Folder"
+ ... title="Folder Settings"
+ ... schema="z3ext.preferences.README.IFolderSettings" />
+ ...
+ ... </configure>''', context)
+
+ >>> prefs['ZMISettings2']
+ <z3ext.preferences.preferencetype.Preference<ZMISettings2> ...>
+
+ >>> prefs['ZMISettings2'].items()
+ [(u'ZMISettings2.Folder', <z3ext.preferences.preferencetype.Preference<ZMISettings2.Folder> ...)]
+
+ >>> list(iter(prefs['ZMISettings2']))
+ [<z3ext.preferences.preferencetype.Preference<ZMISettings2.Folder> ...>]
+
+ >>> prefs['ZMISettings2']['Folder'].__title__
+ u'Folder Settings'
+
+ >>> IFolderSettings.providedBy(prefs['ZMISettings2']['Folder'])
+ True
+ >>> interfaces.IPreferenceCategory.providedBy(prefs['ZMISettings2']['Folder'])
+ False
+
+We can define preference group for principal type
+
+ >>> class IMyPrincipal(zope.interface.Interface):
+ ... pass
+
+Now let's register preference for for this type of principal
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns:z3ext="http://namespaces.zope.org/z3ext"
+ ... i18n_domain="test">
+ ...
+ ... <z3ext:preferenceGroup
+ ... id="ZMISettings2.Folder10"
+ ... for="z3ext.preferences.README.IMyPrincipal"
+ ... title="Folder Settings"
+ ... schema="z3ext.preferences.README.IFolderSettings" />
+ ...
+ ... </configure>''', context)
+
+ >>> p = component.getUtility(interfaces.IPreferenceGroup, 'ZMISettings2.Folder10')
+ >>> new_prefs = p.__bind__()
+ >>> new_prefs.isAvailable()
+ False
+
+Now let's mark our principal
+
+ >>> zope.interface.alsoProvides(principal, IMyPrincipal)
+ >>> new_prefs = p.__bind__()
+ >>> new_prefs.isAvailable()
+ True
+
+
+Simple Python-Level Access
+--------------------------
+
+If a site is set, getting the user preferences is very simple:
+
+ >>> prefs2 = component.getUtility(interfaces.IPreferenceGroup, 'ZMISettings.Folder')
+ >>> prefs2 = prefs2.__bind__(principal=principal)
+
+ >>> prefs2.sortedBy
+ 'size'
+
+
+Security
+--------
+
+You might already wonder under which permissions the preferences are
+available. They are actually available publicly (`CheckerPublic`), but that
+is not a problem, since the available values are looked up specifically for
+the current user. And why should a user not have full access to his/her
+preferences? But sometimes we need preferences which can be changed
+only by manager. In this case we can provide default permission or
+even set security checks on field level, like in <class /> directive.
+
+ >>> import zope.security
+ >>> context = xmlconfig.file('meta.zcml', zope.security, context)
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... xmlns:z3ext="http://namespaces.zope.org/z3ext"
+ ... i18n_domain="z3ext">
+ ...
+ ... <permission id="zope.View" title="zope view" />
+ ... <permission id="zope.Manage" title="zope manage" />
+ ...
+ ... <z3ext:preferenceGroup
+ ... id="ZMISettings3"
+ ... title="ZMI Settings 3"
+ ... schema="z3ext.preferences.README.IZMIUserSettings"
+ ... provides="z3ext.preferences.interfaces.IPreferenceCategory"
+ ... permission="zope.View">
+ ... <require
+ ... attributes="showZopeLogo" permission="zope.Manage" />
+ ... </z3ext:preferenceGroup>
+ ...
+ ... </configure>''', context)
+
Deleted: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/configure.zcml
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/configure.zcml 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/configure.zcml 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,56 +0,0 @@
-<configure
- xmlns="http://namespaces.zope.org/zope"
- xmlns:z3ext="http://namespaces.zope.org/z3ext"
- i18n_domain="z3ext">
-
- <autoinclude package="z3ext.preferences" />
-
- <role
- id="preference.Owner"
- title="Preference group owner" />
-
- <permission
- id="z3ext.ModifyPreference"
- title="Modifye preference" />
-
- <grant
- permission="z3ext.ModifyPreference"
- role="preference.Owner" />
-
- <!-- root preference group -->
- <utility
- provides=".interfaces.IPreferenceGroup"
- factory=".root.PersonalPreferences" />
-
- <class class=".root.PersonalPreferences">
- <require
- permission="zope.Public"
- interface=".interfaces.IPreferenceGroup
- zope.interface.common.mapping.IEnumerableMapping" />
- </class>
-
- <class class=".preference.PreferenceGroup">
- <implements interface="zope.annotation.interfaces.IAttributeAnnotatable" />
- </class>
-
- <!-- preference group publisher -->
- <adapter
- for=".interfaces.IPreferenceGroup *"
- factory="z3c.traverser.traverser.PluggableTraverser"
- provides="zope.publisher.interfaces.IPublishTraverse" />
-
- <subscriber
- for=".interfaces.IPreferenceGroup *"
- provides="z3c.traverser.interfaces.ITraverserPlugin"
- factory=".publisher.PreferenceTraverserPlugin" />
-
- <!-- predefined preference group -->
- <z3ext:preferenceGroup
- id="portal"
- title="Portal preferences"
- description="These are all the preferences related to common portal settings."
- provides="z3ext.preferences.interfaces.IPreferenceCategory" />
-
- <include package=".browser" />
-
-</configure>
Copied: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/configure.zcml (from rev 85236, z3ext.preferences/trunk/src/z3ext/preferences/configure.zcml)
===================================================================
--- z3ext.preferences/tags/1.1.0/src/z3ext/preferences/configure.zcml (rev 0)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/configure.zcml 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,57 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:z3ext="http://namespaces.zope.org/z3ext"
+ i18n_domain="z3ext">
+
+ <autoinclude package="z3ext.preferences" />
+
+ <role
+ id="preference.Owner"
+ title="Preference group owner" />
+
+ <permission
+ id="z3ext.ModifyPreference"
+ title="Modifye preference" />
+
+ <grant
+ permission="z3ext.ModifyPreference"
+ role="preference.Owner" />
+
+ <!-- root preference group -->
+ <utility
+ provides=".interfaces.IPreferenceGroup"
+ factory=".root.PersonalPreferences" />
+
+ <class class=".root.PersonalPreferences">
+ <require
+ permission="zope.Public"
+ interface=".interfaces.IPreferenceGroup
+ zope.interface.common.mapping.IEnumerableMapping" />
+ </class>
+
+ <class class=".preference.PreferenceGroup">
+ <implements interface="zope.annotation.interfaces.IAttributeAnnotatable" />
+ </class>
+
+ <!-- preference group publisher -->
+ <adapter
+ for=".interfaces.IPreferenceGroup *"
+ factory="z3c.traverser.traverser.PluggableTraverser"
+ provides="zope.publisher.interfaces.IPublishTraverse" />
+
+ <subscriber
+ for=".interfaces.IPreferenceGroup *"
+ provides="z3c.traverser.interfaces.ITraverserPlugin"
+ factory=".publisher.PreferenceTraverserPlugin" />
+
+ <!-- predefined preference group -->
+ <z3ext:preferenceGroup
+ id="portal"
+ title="Portal preferences"
+ description="These are all the preferences related to common portal settings."
+ provides="z3ext.preferences.interfaces.IPreferenceCategory" />
+
+ <!-- browser views -->
+ <include package=".browser" />
+
+</configure>
Deleted: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/interfaces.py
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/interfaces.py 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/interfaces.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,94 +0,0 @@
-##############################################################################
-#
-# 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.preferences interfaces
-
-$Id$
-"""
-from zope import schema, interface
-from zope.configuration import fields
-from zope.location.interfaces import ILocation
-
-
-class UnboundPreferenceGroup(Exception):
- """ Prefernce group is not bound to principal """
-
-
-class IPreferenceGroup(ILocation):
- """A group of preferences.
-
- This component represents a logical group of preferences. The preferences
- contained by this group is defined through the schema. The group has also
- a name by which it can be accessed.
-
- The fields specified in the schema *must* be available as attributes and
- items of the group instance. It is up to the implementation how this is
- realized, however, most often one will implement __setattr__ and
- __getattr__ as well as the common mapping API.
-
- The reason all the API fields are doubly underlined is to avoid name clashes.
- """
-
- __id__ = schema.TextLine(
- title = u"Id",
- description = u"The id of the group.",
- required = True)
-
- __schema__ = schema.InterfaceField(
- title = u"Schema",
- description = u"Schema describing the preferences of the group.",
- required = False,
- readonly = True)
-
- __title__ = fields.MessageID(
- title = u"Title",
- description = u"The title of the group used in the UI.",
- required = True)
-
- __description__ = fields.MessageID(
- title = u"Description",
- description = u"The description of the group used in the UI.",
- required = False)
-
- __principal__ = interface.Attribute('Owner principal of preferences')
-
- def isAvailable():
- """ is group available for bound principal """
-
- def add(name):
- """ add subgroup name """
-
- def remove(name):
- """ remove subgroup name """
-
-
-class IPreferenceCategory(interface.Interface):
- """A collection of preference groups.
-
- Objects providing this interface serve as groups of preference
- groups. This allows UIs to distinguish between high- and low-level
- prefernce groups.
- """
-
-
-class IBound(interface.Interface):
- """ bound to context """
-
- __principal__ = interface.Attribute('IPrincipal object')
-
-
-class IRootPreferences(interface.Interface):
- """ root preferences """
-
- def __bind__(parent=None, principal=None):
- """ bind preferences """
Copied: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/interfaces.py (from rev 85236, z3ext.preferences/trunk/src/z3ext/preferences/interfaces.py)
===================================================================
--- z3ext.preferences/tags/1.1.0/src/z3ext/preferences/interfaces.py (rev 0)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/interfaces.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,97 @@
+##############################################################################
+#
+# 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.preferences interfaces
+
+$Id$
+"""
+from zope import schema, interface
+from zope.configuration import fields
+from zope.location.interfaces import ILocation
+
+
+class UnboundPreferenceGroup(Exception):
+ """ Prefernce group is not bound to principal """
+
+
+class IPreferenceGroup(ILocation):
+ """A group of preferences.
+
+ This component represents a logical group of preferences. The preferences
+ contained by this group is defined through the schema. The group has also
+ a name by which it can be accessed.
+
+ The fields specified in the schema *must* be available as attributes and
+ items of the group instance. It is up to the implementation how this is
+ realized, however, most often one will implement __setattr__ and
+ __getattr__ as well as the common mapping API.
+
+ The reason all the API fields are doubly underlined is to avoid name clashes.
+ """
+
+ __id__ = schema.TextLine(
+ title = u"Id",
+ description = u"The id of the group.",
+ required = True)
+
+ __schema__ = schema.InterfaceField(
+ title = u"Schema",
+ description = u"Schema describing the preferences of the group.",
+ required = False,
+ readonly = True)
+
+ __title__ = fields.MessageID(
+ title = u"Title",
+ description = u"The title of the group used in the UI.",
+ required = True)
+
+ __description__ = fields.MessageID(
+ title = u"Description",
+ description = u"The description of the group used in the UI.",
+ required = False)
+
+ __principal__ = interface.Attribute('Owner principal of preferences')
+
+ def isAvailable():
+ """ is group available for bound principal """
+
+ def add(name):
+ """ add subgroup name """
+
+ def remove(name):
+ """ remove subgroup name """
+
+ def __bind__(principal=None, parent=None):
+ """ bind preferences """
+
+
+class IPreferenceCategory(interface.Interface):
+ """A collection of preference groups.
+
+ Objects providing this interface serve as groups of preference
+ groups. This allows UIs to distinguish between high- and low-level
+ prefernce groups.
+ """
+
+
+class IBound(interface.Interface):
+ """ bound to context """
+
+ __principal__ = interface.Attribute('IPrincipal object')
+
+
+class IRootPreferences(interface.Interface):
+ """ root preferences """
+
+ def __bind__(principal=None, parent=None):
+ """ bind preferences """
Deleted: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/preference.py
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/preference.py 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/preference.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,184 +0,0 @@
-##############################################################################
-#
-# 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 BTrees.OOBTree import OOBTree
-
-from zope import interface
-from zope.interface.common.mapping import IEnumerableMapping
-from zope.component import getGlobalSiteManager
-from zope.component import queryUtility, getMultiAdapter
-from zope.cachedescriptors.property import Lazy
-from zope.security.management import getInteraction
-from zope.annotation.interfaces import IAnnotations
-from zope.app.component.hooks import getSite
-from zope.app.security.interfaces import IAuthentication, PrincipalLookupError
-
-from interfaces import IPreferenceGroup, IBound, UnboundPreferenceGroup
-
-pref_key = 'zope.app.user.UserPreferences'
-
-_marker = object()
-
-
-class PreferenceGroup(object):
- interface.implements(IPreferenceGroup, IEnumerableMapping)
-
- __principal__ = None
-
- def __init__(self, tests=()):
- self.__name__ = self.__id__.rsplit('.', 1)[-1]
- self.__tests__ = tests
- self.__subgroups__ = ()
-
- def __bind__(self, parent=None, principal=None):
- clone = self.__class__.__new__(self.__class__)
- clone.__dict__.update(self.__dict__)
-
- if parent is None:
- parent = getSite()
-
- clone.__parent__ = parent
-
- if principal is None:
- if IBound.providedBy(parent):
- clone.__principal__ = parent.__principal__
- else:
- principal = getInteraction().participations[0].principal
-
- auth = queryUtility(IAuthentication)
- if auth is not None:
- try:
- principal = auth.getPrincipal(principal.id)
- except PrincipalLookupError:
- pass
-
- clone.__principal__ = principal
- else:
- clone.__principal__ = principal
-
- interface.alsoProvides(clone, IBound)
- return clone
-
- @Lazy
- def data(self):
- if not IBound.providedBy(self):
- raise UnboundPreferenceGroup()
-
- ann = getMultiAdapter((self.__principal__, self), IAnnotations)
-
- # If no preferences exist, create the root preferences object.
- if ann.get(pref_key) is None:
- ann[pref_key] = OOBTree()
- prefs = ann[pref_key]
-
- # If no entry for the group exists, create a new entry.
- if self.__id__ not in prefs.keys():
- prefs[self.__id__] = OOBTree()
-
- return prefs[self.__id__]
-
- def isAvailable(self):
- if IPreferenceGroup.providedBy(self.__parent__):
- if not self.__parent__.isAvailable():
- return False
-
- for test in self.__tests__:
- if callable(test):
- if not test(self):
- return False
- elif not bool(test):
- return False
-
- return True
-
- def add(self, name):
- if name not in self.__subgroups__:
- self.__subgroups__ = self.__subgroups__ + (name,)
-
- id = self.__id__
- if id:
- id = id + '.'
-
- items = []
- for grp_id in self.__subgroups__:
- name = id + grp_id
-
- group = queryUtility(IPreferenceGroup, name)
- if group is None:
- group = getGlobalSiteManager().queryUtility(
- IPreferenceGroup, name)
-
- if group is not None:
- items.append((group.order, group.__title__, grp_id))
-
- items.sort()
- self.__subgroups__ = tuple([id for o,t,id in items])
-
- def remove(self, name):
- if name in self.__subgroups__:
- names = list(self.__subgroups__)
- names.remove(name)
- self.__subgroups__ = tuple(names)
-
- def get(self, key, default=None):
- id = self.__id__ and self.__id__ + '.' + key or key
- group = queryUtility(IPreferenceGroup, id, default)
- if group is default:
- return default
- return group.__bind__(self)
-
- def items(self):
- id = self.__id__
- if id:
- id = id + '.'
-
- items = []
- for key in self.keys():
- name = id + key
- group = queryUtility(IPreferenceGroup, name)
- if group is not None:
- items.append((name, group.__bind__(self)))
- return items
-
- def __getitem__(self, key):
- obj = self.get(key, _marker)
- if obj is _marker:
- raise KeyError(key)
- return obj
-
- 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
- group = queryUtility(IPreferenceGroup, name)
- if group is not None:
- yield group.__bind__(self)
-
- def values(self):
- return [group for id, group in self.items()]
-
- def __len__(self):
- return len(self.keys())
Copied: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/preference.py (from rev 85236, z3ext.preferences/trunk/src/z3ext/preferences/preference.py)
===================================================================
--- z3ext.preferences/tags/1.1.0/src/z3ext/preferences/preference.py (rev 0)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/preference.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,184 @@
+##############################################################################
+#
+# 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 BTrees.OOBTree import OOBTree
+
+from zope import interface
+from zope.interface.common.mapping import IEnumerableMapping
+from zope.component import getGlobalSiteManager
+from zope.component import queryUtility, getMultiAdapter
+from zope.cachedescriptors.property import Lazy
+from zope.security.management import getInteraction
+from zope.annotation.interfaces import IAnnotations
+from zope.app.component.hooks import getSite
+from zope.app.security.interfaces import IAuthentication, PrincipalLookupError
+
+from interfaces import IPreferenceGroup, IBound, UnboundPreferenceGroup
+
+pref_key = 'zope.app.user.UserPreferences'
+
+_marker = object()
+
+
+class PreferenceGroup(object):
+ interface.implements(IPreferenceGroup, IEnumerableMapping)
+
+ __principal__ = None
+
+ def __init__(self, tests=()):
+ self.__name__ = self.__id__.rsplit('.', 1)[-1]
+ self.__tests__ = tests
+ self.__subgroups__ = ()
+
+ def __bind__(self, principal=None, parent=None):
+ clone = self.__class__.__new__(self.__class__)
+ clone.__dict__.update(self.__dict__)
+
+ if parent is None:
+ parent = getSite()
+
+ clone.__parent__ = parent
+
+ if principal is None:
+ if IBound.providedBy(parent):
+ clone.__principal__ = parent.__principal__
+ else:
+ principal = getInteraction().participations[0].principal
+
+ auth = queryUtility(IAuthentication)
+ if auth is not None:
+ try:
+ principal = auth.getPrincipal(principal.id)
+ except PrincipalLookupError:
+ pass
+
+ clone.__principal__ = principal
+ else:
+ clone.__principal__ = principal
+
+ interface.alsoProvides(clone, IBound)
+ return clone
+
+ @Lazy
+ def data(self):
+ if not IBound.providedBy(self):
+ raise UnboundPreferenceGroup()
+
+ ann = getMultiAdapter((self.__principal__, self), IAnnotations)
+
+ # If no preferences exist, create the root preferences object.
+ if ann.get(pref_key) is None:
+ ann[pref_key] = OOBTree()
+ prefs = ann[pref_key]
+
+ # If no entry for the group exists, create a new entry.
+ if self.__id__ not in prefs.keys():
+ prefs[self.__id__] = OOBTree()
+
+ return prefs[self.__id__]
+
+ def isAvailable(self):
+ if IPreferenceGroup.providedBy(self.__parent__):
+ if not self.__parent__.isAvailable():
+ return False
+
+ for test in self.__tests__:
+ if callable(test):
+ if not test(self):
+ return False
+ elif not bool(test):
+ return False
+
+ return True
+
+ def add(self, name):
+ if name not in self.__subgroups__:
+ self.__subgroups__ = self.__subgroups__ + (name,)
+
+ id = self.__id__
+ if id:
+ id = id + '.'
+
+ items = []
+ for grp_id in self.__subgroups__:
+ name = id + grp_id
+
+ group = queryUtility(IPreferenceGroup, name)
+ if group is None:
+ group = getGlobalSiteManager().queryUtility(
+ IPreferenceGroup, name)
+
+ if group is not None:
+ items.append((group.order, group.__title__, grp_id))
+
+ items.sort()
+ self.__subgroups__ = tuple([id for o,t,id in items])
+
+ def remove(self, name):
+ if name in self.__subgroups__:
+ names = list(self.__subgroups__)
+ names.remove(name)
+ self.__subgroups__ = tuple(names)
+
+ def get(self, key, default=None):
+ id = self.__id__ and self.__id__ + '.' + key or key
+ group = queryUtility(IPreferenceGroup, id, default)
+ if group is default:
+ return default
+ return group.__bind__(parent=self)
+
+ def items(self):
+ id = self.__id__
+ if id:
+ id = id + '.'
+
+ items = []
+ for key in self.keys():
+ name = id + key
+ group = queryUtility(IPreferenceGroup, name)
+ if group is not None:
+ items.append((name, group.__bind__(parent=self)))
+ return items
+
+ def __getitem__(self, key):
+ obj = self.get(key, _marker)
+ if obj is _marker:
+ raise KeyError(key)
+ return obj
+
+ 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
+ group = queryUtility(IPreferenceGroup, name)
+ if group is not None:
+ yield group.__bind__(parent=self)
+
+ def values(self):
+ return [group for id, group in self.items()]
+
+ def __len__(self):
+ return len(self.keys())
Deleted: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/root.py
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/root.py 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/root.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,53 +0,0 @@
-##############################################################################
-#
-# 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 Preference Group
-
-$Id$
-"""
-from zope import interface
-from zope.securitypolicy.interfaces import IPrincipalRoleManager
-from zope.app.security.interfaces import IUnauthenticatedPrincipal
-
-from i18n import _
-from preference import PreferenceGroup
-from interfaces import IRootPreferences, IPreferenceCategory
-
-
-class PersonalPreferences(PreferenceGroup):
- interface.implements(IRootPreferences, IPreferenceCategory)
-
- __id__ = ''
- __name__ = u'preferences'
- __title__ = _(u'Personal preferences')
- __description__ = _('This area allows you to change personal preferences.')
- __schema__ = IRootPreferences
- __principal__ = None
-
- def __init__(self):
- self.__subgroups__ = ()
-
- def isAvailable(self):
- if IUnauthenticatedPrincipal.providedBy(self.__principal__):
- return False
- return True
-
- def __bind__(self, parent=None, principal=None):
- clone = super(PersonalPreferences, self).__bind__(parent, principal)
-
- rmanager = IPrincipalRoleManager(clone, None)
- if rmanager is not None:
- rmanager.assignRoleToPrincipal(
- 'preference.Owner', clone.__principal__.id)
-
- return clone
Copied: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/root.py (from rev 85236, z3ext.preferences/trunk/src/z3ext/preferences/root.py)
===================================================================
--- z3ext.preferences/tags/1.1.0/src/z3ext/preferences/root.py (rev 0)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/root.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,53 @@
+##############################################################################
+#
+# 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 Preference Group
+
+$Id$
+"""
+from zope import interface
+from zope.securitypolicy.interfaces import IPrincipalRoleManager
+from zope.app.security.interfaces import IUnauthenticatedPrincipal
+
+from i18n import _
+from preference import PreferenceGroup
+from interfaces import IRootPreferences, IPreferenceCategory
+
+
+class PersonalPreferences(PreferenceGroup):
+ interface.implements(IRootPreferences, IPreferenceCategory)
+
+ __id__ = ''
+ __name__ = u'preferences'
+ __title__ = _(u'Personal preferences')
+ __description__ = _('This area allows you to change personal preferences.')
+ __schema__ = IRootPreferences
+ __principal__ = None
+
+ def __init__(self):
+ self.__subgroups__ = ()
+
+ def isAvailable(self):
+ if IUnauthenticatedPrincipal.providedBy(self.__principal__):
+ return False
+ return True
+
+ def __bind__(self, principal=None, parent=None):
+ clone = super(PersonalPreferences, self).__bind__(principal, parent)
+
+ rmanager = IPrincipalRoleManager(clone, None)
+ if rmanager is not None:
+ rmanager.assignRoleToPrincipal(
+ 'preference.Owner', clone.__principal__.id)
+
+ return clone
Deleted: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/utils.py
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/utils.py 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/utils.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,32 +0,0 @@
-##############################################################################
-#
-# 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 import interface
-from zope.security.interfaces import IPrincipal, IGroup, IMemberAwareGroup
-
-
-def isUser(group):
- principal = group.__principal__
- return IPrincipal.providedBy(principal) and not IGroup.providedBy(principal)
-
-
-def isGroup(group):
- return IGroup.providedBy(group.__principal__)
-
-
-def isMemberAwareGroup(group):
- return IMemberAwareGroup.providedBy(group.__principal__)
Copied: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/utils.py (from rev 85236, z3ext.preferences/trunk/src/z3ext/preferences/utils.py)
===================================================================
--- z3ext.preferences/tags/1.1.0/src/z3ext/preferences/utils.py (rev 0)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/utils.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,41 @@
+##############################################################################
+#
+# 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 import interface
+from zope.security.interfaces import IPrincipal, IGroup, IMemberAwareGroup
+
+
+def isUser(group):
+ principal = group.__principal__
+ return IPrincipal.providedBy(principal) and not IGroup.providedBy(principal)
+
+
+def isGroup(group):
+ return IGroup.providedBy(group.__principal__)
+
+
+def isMemberAwareGroup(group):
+ return IMemberAwareGroup.providedBy(group.__principal__)
+
+
+class PrincipalChecker(object):
+
+ def __init__(self, iface):
+ self.iface = iface
+
+ def __call__(self, group):
+ return self.iface.providedBy(group.__principal__)
Deleted: z3ext.preferences/tags/1.1.0/src/z3ext/preferences/zcml.py
===================================================================
--- z3ext.preferences/trunk/src/z3ext/preferences/zcml.py 2008-04-11 01:48:14 UTC (rev 85230)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/zcml.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -1,226 +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.security.zcml import Permission
-from zope.security.checker import Checker, CheckerPublic
-
-from zope.interface.common.mapping import IEnumerableMapping
-
-from zope.component.zcml import utility
-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 interfaces import IPreferenceGroup
-from preference import PreferenceGroup
-from preferencetype import PreferenceType
-
-
-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)
-
- schema = fields.GlobalInterface(
- title=u"Schema",
- description=u"Schema of the preference group used defining the "
- u"preferences of the group.",
- required=False)
-
- 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 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 PreferenceGroupDirective(object):
-
- def __init__(self, _context, id=None, schema=interface.Interface,
- title=u'', description=u'', category=False,
- class_=None, provides=[], permission=CheckerPublic,
- tests=(), order = 9999):
-
- Class = PreferenceType(str(id), schema, class_, title, description)
- Class.order = order
-
- group = Class(tests)
-
- utility(_context, IPreferenceGroup, group, name=id)
-
- interface.classImplements(Class, *provides)
-
- self._class = Class
- self._context = _context
- self._permission = permission
-
- self.require(_context, permission, interface=(IPreferenceGroup, schema))
- self.require(_context, 'z3ext.ModifyPreference', set_schema=(schema,))
- self.require(_context, CheckerPublic, interface=(IEnumerableMapping,))
-
- _context.action(
- discriminator=('z3ext:preferences', group),
- callable=addSubgroup, args=(group,))
-
- 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 like_class:
- self.__mimic(_context, like_class)
-
- 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 __mimic(self, _context, class_):
- """Base security requirements on those of the given class"""
- _context.action(
- discriminator=('z3ext:preferences:mimic', self._class),
- callable=protectLikeUnto,
- args=(self._class, class_),
- )
-
- 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.1.0/src/z3ext/preferences/zcml.py (from rev 85236, z3ext.preferences/trunk/src/z3ext/preferences/zcml.py)
===================================================================
--- z3ext.preferences/tags/1.1.0/src/z3ext/preferences/zcml.py (rev 0)
+++ z3ext.preferences/tags/1.1.0/src/z3ext/preferences/zcml.py 2008-04-11 11:54:01 UTC (rev 85237)
@@ -0,0 +1,237 @@
+##############################################################################
+#
+# 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.security.zcml import Permission
+from zope.security.checker import Checker, CheckerPublic
+
+from zope.interface.common.mapping import IEnumerableMapping
+
+from zope.component.zcml import utility
+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 interfaces import IPreferenceGroup
+from preference import PreferenceGroup
+from preferencetype import PreferenceType
+from utils import PrincipalChecker
+
+
+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=False)
+
+ 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 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 PreferenceGroupDirective(object):
+
+ def __init__(self, _context, id, title,
+ for_=None, schema=interface.Interface,
+ description=u'', category=False,
+ class_=None, provides=[], permission=CheckerPublic,
+ tests=(), order = 9999):
+
+ Class = PreferenceType(str(id), schema, class_, title, description)
+ Class.order = order
+
+ if interface.interfaces.IInterface.providedBy(for_):
+ tests = tests + (PrincipalChecker(for_),)
+
+ group = Class(tests)
+
+ utility(_context, IPreferenceGroup, group, name=id)
+
+ interface.classImplements(Class, *provides)
+
+ self._class = Class
+ self._context = _context
+ self._permission = permission
+
+ self.require(_context, permission, interface=(IPreferenceGroup, schema))
+ self.require(_context, 'z3ext.ModifyPreference', set_schema=(schema,))
+ self.require(_context, CheckerPublic,
+ interface=(IEnumerableMapping,), attributes=('isAvailable',))
+
+ _context.action(
+ discriminator=('z3ext:preferences', group),
+ callable=addSubgroup, args=(group,))
+
+ 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 like_class:
+ self.__mimic(_context, like_class)
+
+ 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 __mimic(self, _context, class_):
+ """Base security requirements on those of the given class"""
+ _context.action(
+ discriminator=('z3ext:preferences:mimic', self._class),
+ callable=protectLikeUnto,
+ args=(self._class, class_),
+ )
+
+ 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