[Checkins] SVN: zope.app.preference/trunk/ merged icemac-zope.preference branch (using split out zope.preference)
Michael Howitz
mh at gocept.com
Sat Jun 12 07:45:38 EDT 2010
Log message for revision 113388:
merged icemac-zope.preference branch (using split out zope.preference)
Changed:
U zope.app.preference/trunk/CHANGES.txt
U zope.app.preference/trunk/README.txt
U zope.app.preference/trunk/setup.py
D zope.app.preference/trunk/src/zope/app/preference/README.txt
A zope.app.preference/trunk/src/zope/app/preference/README.txt
U zope.app.preference/trunk/src/zope/app/preference/__init__.py
U zope.app.preference/trunk/src/zope/app/preference/browser.py
U zope.app.preference/trunk/src/zope/app/preference/configure.zcml
U zope.app.preference/trunk/src/zope/app/preference/default.py
U zope.app.preference/trunk/src/zope/app/preference/ftesting.zcml
U zope.app.preference/trunk/src/zope/app/preference/interfaces.py
U zope.app.preference/trunk/src/zope/app/preference/meta.zcml
U zope.app.preference/trunk/src/zope/app/preference/metaconfigure.py
U zope.app.preference/trunk/src/zope/app/preference/metadirectives.py
U zope.app.preference/trunk/src/zope/app/preference/preference.py
U zope.app.preference/trunk/src/zope/app/preference/tests.py
D zope.app.preference/trunk/src/zope/app/preference/zmi.txt
-=-
Modified: zope.app.preference/trunk/CHANGES.txt
===================================================================
--- zope.app.preference/trunk/CHANGES.txt 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/CHANGES.txt 2010-06-12 11:45:38 UTC (rev 113388)
@@ -2,10 +2,10 @@
CHANGES
=======
-3.7.1 (unreleased)
+3.8.0 (unreleased)
------------------
-- Nothing changed yet.
+- Use split out `zope.preference`.
3.7.0 (2010-06-11)
Modified: zope.app.preference/trunk/README.txt
===================================================================
--- zope.app.preference/trunk/README.txt 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/README.txt 2010-06-12 11:45:38 UTC (rev 113388)
@@ -1,2 +1,2 @@
-This package provides and API and UI to create and maintain hierarchical user
-preferences. Preferences can be easily created by defining schemas.
+This package provides a UI to maintain hierarchical user preferences
+in the ZMI.
\ No newline at end of file
Modified: zope.app.preference/trunk/setup.py
===================================================================
--- zope.app.preference/trunk/setup.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/setup.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -27,16 +27,14 @@
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
setup(name = 'zope.app.preference',
- version='3.7.1dev',
+ version='3.8.0dev',
author='Zope Corporation and Contributors',
author_email='zope-dev at zope.org',
- description='User Preferences Framework',
+ description='User Preferences Framework ZMI UI',
long_description=(
read('README.txt')
+ '\n\n' +
- 'Detailed Dcoumentation\n' +
- '======================\n'
- + '\n\n' +
+ '.. contents::\n\n' +
read('src', 'zope', 'app', 'preference', 'README.txt')
+ '\n\n' +
read('CHANGES.txt')
@@ -60,29 +58,10 @@
extras_require=dict(test=[
'zope.app.testing',
'zope.app.zcmlfiles',
- 'zope.securitypolicy',
- 'zope.testbrowser',
- 'zope.testing',
]),
install_requires = ['setuptools',
- 'ZODB3',
- 'zope.annotation',
- 'zope.app.basicskin',
- 'zope.app.component',
- 'zope.app.form',
- 'zope.app.pagetemplate',
- 'zope.app.renderer',
+ 'zope.preference',
'zope.app.tree',
- 'zope.component',
- 'zope.configuration',
- 'zope.container',
- 'zope.i18n',
- 'zope.i18nmessageid',
- 'zope.interface',
- 'zope.location',
- 'zope.schema',
- 'zope.security',
- 'zope.traversing',
],
include_package_data = True,
zip_safe = False,
Deleted: zope.app.preference/trunk/src/zope/app/preference/README.txt
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/README.txt 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/README.txt 2010-06-12 11:45:38 UTC (rev 113388)
@@ -1,481 +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 zope.app.preference import preference
-
-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.interface
- >>> import zope.schema
- >>> 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)
-
-Now we can instantiate the preference group. Each preference group must have an
-ID by which it can be accessed and optional title and description fields for UI
-purposes:
-
- >>> settings = preference.PreferenceGroup(
- ... "ZMISettings",
- ... schema=IZMIUserSettings,
- ... title=u"ZMI User Settings",
- ... description=u"")
-
-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__
- 'ZMISettings'
- >>> settings.__schema__
- <InterfaceClass zope.app.preference.README.IZMIUserSettings>
- >>> settings.__title__
- u'ZMI User Settings'
-
-So let's ask the preference group for the `skin` setting:
-
- >>> settings.skin #doctest:+ELLIPSIS
- Traceback (most recent call last):
- ...
- NoInteraction
-
-
-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 new
-interaction:
-
- >>> 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.app.testing import ztapi
- >>> ztapi.provideAdapter((Principal, zope.interface.Interface), IAnnotations,
- ... PrincipalAnnotations)
-
-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:
-
- >>> 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=set(['name', 'size']))
- ...
- ... sortedBy = zope.schema.Choice(
- ... title=u"Sorted By",
- ... description=u"Data field to sort by.",
- ... values=['name', 'size', 'creator'],
- ... default='name')
-
- >>> folderSettings = preference.PreferenceGroup(
- ... "ZMISettings.Folder",
- ... schema=IFolderSettings,
- ... title=u"Folder Content View Settings")
-
-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):
- ...
- AttributeError: 'Folder' is not a preference or sub-group.
-
-... but not before we register the groups as utilities:
-
- >>> from zope.app.preference import interfaces
- >>> from zope.app.testing import ztapi
-
- >>> ztapi.provideUtility(interfaces.IPreferenceGroup, settings,
- ... name='ZMISettings')
- >>> ztapi.provideUtility(interfaces.IPreferenceGroup, folderSettings,
- ... name='ZMISettings.Folder')
-
-If we now try to lookup the sub-group again, we should be successful:
-
- >>> settings.Folder #doctest:+ELLIPSIS
- <zope.app.preference.preference.PreferenceGroup object at ...>
-
- >>> settings['Folder'] #doctest:+ELLIPSIS
- <zope.app.preference.preference.PreferenceGroup object at ...>
-
-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
-
-
-Default Preferences
--------------------
-
-It sometimes desirable to define default settings on a site-by-site basis,
-instead of just using the default value from the schema. The preferences
-package provides a module
-
- >>> from zope.app.preference import default
-
-that implements a default preferences provider that can be added as a unnamed
-utility for each site. So the first step is to create a site:
-
- >>> root = setup.buildSampleFolderTree()
- >>> rsm = setup.createSiteManager(root, True)
-
-Now we can register the default preference provider with the root site:
-
- >>> provider = setup.addUtility(rsm, '',
- ... interfaces.IDefaultPreferenceProvider,
- ... default.DefaultPreferenceProvider())
-
-So before we set an explicit default value for a preference, the schema field
-default is used:
-
- >>> settings.Folder.sortedBy
- 'name'
-
-But if we now set a new default value with the provider,
-
- >>> defaultFolder = provider.getDefaultPreferenceGroup('ZMISettings.Folder')
- >>> defaultFolder.sortedBy = 'size'
-
-then the default of the setting changes:
-
- >>> settings.Folder.sortedBy
- 'size'
-
-The default preference providers also implicitly acquire default values from
-parent sites. So if we make `folder1` a site and set it as the active site
-
- >>> folder1 = root['folder1']
- >>> sm1 = setup.createSiteManager(folder1, True)
-
-and add a default provider there,
-
- >>> provider1 = setup.addUtility(sm1, '',
- ... interfaces.IDefaultPreferenceProvider,
- ... default.DefaultPreferenceProvider())
-
-then we still get the root's default values, because we have not defined any
-in the higher default provider:
-
- >>> settings.Folder.sortedBy
- 'size'
-
-But if we provide the new provider with a default value for `sortedBy`,
-
- >>> defaultFolder1 = provider1.getDefaultPreferenceGroup('ZMISettings.Folder')
- >>> defaultFolder1.sortedBy = 'creator'
-
-then it is used instead:
-
- >>> settings.Folder.sortedBy
- 'creator'
-
-Of course, once the root site becomes our active site again
-
- >>> zope.app.component.hooks.setSite(root)
-
-the default value of the root provider is used:
-
- >>> settings.Folder.sortedBy
- 'size'
-
-Of course, all the defaults in the world are not relevant anymore as soon as
-the user actually provides a value:
-
- >>> settings.Folder.sortedBy = 'name'
- >>> settings.Folder.sortedBy
- 'name'
-
-Oh, and have I mentioned that entered values are always validated? So you
-cannot just assign any old value:
-
- >>> settings.Folder.sortedBy = 'foo'
- Traceback (most recent call last):
- ...
- ConstraintNotSatisfied: foo
-
-Finally, if the user deletes his/her explicit setting, we are back to the
-default value:
-
- >>> del settings.Folder.sortedBy
- >>> settings.Folder.sortedBy
- 'size'
-
-
-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 zope.app.preference
- >>> context = xmlconfig.file('meta.zcml', zope.app.preference)
-
-Then the system sets up a root preference group:
-
- >>> context = xmlconfig.string('''
- ... <configure
- ... xmlns="http://namespaces.zope.org/zope"
- ... i18n_domain="test">
- ...
- ... <preferenceGroup
- ... id=""
- ... title="User Preferences"
- ... />
- ...
- ... </configure>''', context)
-
-Now we can use the preference system in its intended way. We access the folder
-settings as follows:
-
- >>> import zope.component
- >>> prefs = zope.component.getUtility(interfaces.IPreferenceGroup)
- >>> prefs.ZMISettings.Folder.sortedBy
- 'size'
-
-Let's register the ZMI settings again under a new name via ZCML:
-
- >>> context = xmlconfig.string('''
- ... <configure
- ... xmlns="http://namespaces.zope.org/zope"
- ... i18n_domain="test">
- ...
- ... <preferenceGroup
- ... id="ZMISettings2"
- ... title="ZMI Settings NG"
- ... schema="zope.app.preference.README.IZMIUserSettings"
- ... category="true"
- ... />
- ...
- ... </configure>''', context)
-
- >>> prefs.ZMISettings2 #doctest:+ELLIPSIS
- <zope.app.preference.preference.PreferenceGroup object at ...>
-
- >>> 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="http://namespaces.zope.org/zope"
- ... i18n_domain="test">
- ...
- ... <preferenceGroup
- ... id="ZMISettings2.Folder"
- ... title="Folder Settings"
- ... schema="zope.app.preference.README.IFolderSettings"
- ... />
- ...
- ... </configure>''', context)
-
- >>> prefs.ZMISettings2 #doctest:+ELLIPSIS
- <zope.app.preference.preference.PreferenceGroup object at ...>
-
- >>> 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:
-
- >>> from zope.app.preference import UserPreferences
- >>> prefs2 = UserPreferences()
- >>> prefs2.ZMISettings.Folder.sortedBy
- 'size'
-
-This function is also commonly registered as an adapter,
-
- >>> from zope.location.interfaces import ILocation
- >>> ztapi.provideAdapter(ILocation, interfaces.IUserPreferences,
- ... UserPreferences)
-
-so that you can adapt any location to the user preferences:
-
- >>> prefs3 = interfaces.IUserPreferences(folder1)
- >>> prefs3.ZMISettings.Folder.sortedBy
- 'creator'
-
-
-Traversal
----------
-
-Okay, so all these objects are nice, but they do not make it any easier to
-access the preferences in page templates. Thus, a special traversal namespace
-has been created that makes it very simple to access the preferences via a
-traversal path. But before we can use the path expressions, we have to
-register all necessary traversal components and the special `preferences`
-namespace:
-
- >>> import zope.traversing.interfaces
- >>> ztapi.provideAdapter(None,
- ... zope.traversing.interfaces.ITraversable,
- ... preference.preferencesNamespace,
- ... 'preferences')
-
-We can now access the preferences as follows:
-
- >>> from zope.traversing.api import traverse
- >>> traverse(None, '++preferences++ZMISettings/skin')
- 'Basic'
- >>> traverse(None, '++preferences++/ZMISettings/skin')
- 'Basic'
-
-
-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?
-
-Let's create a checker using the function that the security machinery is
-actually using:
-
- >>> checker = preference.PreferenceGroupChecker(settings)
- >>> checker.permission_id('skin')
- Global(CheckerPublic,zope.security.checker)
- >>> checker.setattr_permission_id('skin')
- Global(CheckerPublic,zope.security.checker)
-
-The id, title, description, and schema are publicly available for access,
-but are not available for mutation at all:
-
- >>> checker.permission_id('__id__')
- Global(CheckerPublic,zope.security.checker)
- >>> checker.setattr_permission_id('__id__') is None
- True
-
-
-The only way security could be compromised is when one could override the
-annotations property. However, this property is not available for public
-consumption at all, including read access:
-
- >>> checker.permission_id('annotation') is None
- True
- >>> checker.setattr_permission_id('annotation') is None
- True
Copied: zope.app.preference/trunk/src/zope/app/preference/README.txt (from rev 113387, zope.app.preference/branches/icemac-zope.preference/src/zope/app/preference/README.txt)
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/README.txt (rev 0)
+++ zope.app.preference/trunk/src/zope/app/preference/README.txt 2010-06-12 11:45:38 UTC (rev 113388)
@@ -0,0 +1,153 @@
+===================
+zope.app.preference
+===================
+
+This package provides a user interface in th ZMI, so the user can edit
+the preferences.
+
+Set up
+------
+
+To show the user interface functions we need some setup beforehand:
+
+ >>> from zope.testbrowser.testing import Browser
+ >>> browser = Browser()
+
+As the preferences cannot be defined through the web we have to define
+them in python code:
+
+ >>> import zope.interface
+ >>> import zope.schema
+ >>> 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)
+
+The preference schema is usually registered using a ZCML statement:
+
+ >>> from zope.configuration import xmlconfig
+ >>> import zope.app.preference
+ >>> context = xmlconfig.file('meta.zcml', zope.app.preference)
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... i18n_domain="test">
+ ...
+ ... <preferenceGroup
+ ... id="ZMISettings"
+ ... title="ZMI Settings"
+ ... schema="zope.app.preference.README.IZMIUserSettings"
+ ... category="true"
+ ... />
+ ...
+ ... </configure>''', context)
+
+Editing Preferences
+-------------------
+
+The preferences are accessable in the ``++preferences++`` namespace:
+
+ >>> browser.open('http://localhost/++preferences++')
+
+The page shows a form which allows editing the preference values:
+
+ >>> browser.getControl('E-mail').value = 'hans at example.com'
+ >>> browser.getControl('Skin').displayOptions
+ ['Rotterdam', 'ZopeTop', 'Basic']
+ >>> browser.getControl('Skin').displayValue = ['ZopeTop']
+ >>> browser.getControl('Show Zope Logo').selected
+ True
+ >>> browser.getControl('Show Zope Logo').click()
+
+After selecting `Change` the values get persisted:
+
+ >>> browser.getControl('Change').click()
+ >>> browser.url
+ 'http://localhost/++preferences++/@@index.html'
+ >>> browser.getControl('E-mail').value
+ 'hans at example.com'
+ >>> browser.getControl('Skin').displayValue
+ ['ZopeTop']
+ >>> browser.getControl('Show Zope Logo').selected
+ False
+
+The preference group is shown in a tree. It has a link to the form:
+
+ >>> browser.getLink('ZMISettings').click()
+ >>> browser.url
+ 'http://localhost/++preferences++/ZMISettings/@@index.html'
+ >>> browser.getControl('E-mail').value
+ 'hans at example.com'
+
+
+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:
+
+ >>> class IFolderSettings(zope.interface.Interface):
+ ... """Basic Folder Settings"""
+ ...
+ ... shownFields = zope.schema.Set(
+ ... title=u"Shown Fields",
+ ... description=u"Fields shown in the table.",
+ ... value_type=zope.schema.Choice(['name', 'size', 'creator']),
+ ... default=set(['name', 'size']))
+ ...
+ ... sortedBy = zope.schema.Choice(
+ ... title=u"Sorted By",
+ ... description=u"Data field to sort by.",
+ ... values=['name', 'size', 'creator'],
+ ... default='name')
+
+And register it:
+
+ >>> context = xmlconfig.string('''
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... i18n_domain="test">
+ ...
+ ... <preferenceGroup
+ ... id="ZMISettings.Folder"
+ ... title="Folder Content View Settings"
+ ... schema="zope.app.preference.README.IFolderSettings"
+ ... />
+ ...
+ ... </configure>''', context)
+
+The sub-group is displayed inside the parent group as a form:
+
+ >>> browser.reload()
+ >>> browser.getControl('Shown Fields').displayOptions
+ ['name', 'size', 'creator']
+ >>> browser.getControl('Shown Fields').displayValue
+ ['name', 'size']
+ >>> browser.getControl('Shown Fields').displayValue = ['size', 'creator']
+ >>> browser.getControl('Sorted By').displayOptions
+ ['name', 'size', 'creator']
+ >>> browser.getControl('Sorted By').displayValue = ['creator']
+
+Selecing `Change` persists these values, too:
+
+ >>> browser.getControl('Change').click()
+ >>> browser.getControl('Shown Fields').displayValue
+ ['size', 'creator']
+ >>> browser.getControl('Sorted By').displayValue
+ ['creator']
Modified: zope.app.preference/trunk/src/zope/app/preference/__init__.py
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/__init__.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/__init__.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -1,3 +1,4 @@
# Make a package
-from zope.app.preference.preference import UserPreferences
+# BBB
+from zope.preference.preference import UserPreferences
Modified: zope.app.preference/trunk/src/zope/app/preference/browser.py
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/browser.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/browser.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -20,7 +20,6 @@
import re
import zope.component
import zope.interface
-import zope.schema
from zope.container.interfaces import IObjectFindFilter
from zope.i18n import translate
from zope.i18nmessageid import Message
@@ -29,12 +28,10 @@
from zope.app.basicskin.standardmacros import StandardMacros
from zope.app.form.browser.editview import EditView
-from zope.app.pagetemplate.simpleviewclass import simple
-from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
from zope.app.tree.browser.cookie import CookieTreeView
from zope.i18nmessageid import ZopeMessageFactory as _
-from zope.app.preference import interfaces
+from zope.preference import interfaces
NoneInterface = zope.interface.interface.InterfaceClass('None')
Modified: zope.app.preference/trunk/src/zope/app/preference/configure.zcml
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/configure.zcml 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/configure.zcml 2010-06-12 11:45:38 UTC (rev 113388)
@@ -6,38 +6,12 @@
i18n_domain="zope"
>
- <view
- name="preferences"
- for="*"
- type="*"
- provides="zope.traversing.interfaces.ITraversable"
- factory=".preference.preferencesNamespace"
- />
+ <include package="zope.preference" />
- <adapter
- name="preferences"
- for="*"
- provides="zope.traversing.interfaces.ITraversable"
- factory=".preference.preferencesNamespace"
- />
-
- <adapter
- for="zope.location.interfaces.ILocation"
- provides=".interfaces.IUserPreferences"
- factory=".preference.UserPreferences"
- />
-
- <!-- Root preference group -->
- <preferenceGroup
- id=""
- title="User Preferences"
- />
-
-
<!-- Preference Groups -->
<browser:page
name="index.html"
- for=".interfaces.IPreferenceGroup"
+ for="zope.preference.interfaces.IPreferenceGroup"
class=".browser.EditPreferenceGroup"
template="index.pt"
permission="zope.Public"
@@ -45,34 +19,14 @@
<browser:page
name="editAsSubGroup"
- for=".interfaces.IPreferenceGroup"
+ for="zope.preference.interfaces.IPreferenceGroup"
class=".browser.EditPreferenceGroup"
template="subgroup.pt"
permission="zope.Public"
/>
-
- <!-- Default Preference Provider -->
- <class class=".default.DefaultPreferenceProvider">
- <implements
- interface="zope.annotation.interfaces.IAttributeAnnotatable"
- />
- <require
- permission="zope.ManageSite"
- interface=".interfaces.IDefaultPreferenceProvider"
- />
- </class>
-
- <view
- name="preferences"
- for=".interfaces.IDefaultPreferenceProvider"
- type="*"
- provides="zope.interface.Interface"
- factory=".default.DefaultPreferences"
- />
-
<browser:addMenuItem
- class=".default.DefaultPreferenceProvider"
+ class="zope.preference.default.DefaultPreferenceProvider"
title="Default User Preferences Provider"
description="A Default User Preferences Provider"
permission="zope.ManageSite"
@@ -99,7 +53,7 @@
<browser:page
name="tree"
- for=".interfaces.IPreferenceGroup"
+ for="zope.preference.interfaces.IPreferenceGroup"
class=".browser.PreferencesTree"
permission="zope.View"
attribute="tree"
Modified: zope.app.preference/trunk/src/zope/app/preference/default.py
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/default.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/default.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -11,104 +11,11 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Default Preferences Provider
+"""Default Preferences Provider"""
-$Id$
-"""
-__docformat__ = "reStructuredText"
-import persistent
-from BTrees.OOBTree import OOBTree
-
-import zope.interface
-import zope.component
-from zope.security.checker import defineChecker
-from zope.traversing.interfaces import IContainmentRoot
-from zope.location import locate
-
-import zope.app.component
-from zope.app.container.contained import Contained
-from zope.app.preference import preference, interfaces
-
-class DefaultPreferenceProvider(persistent.Persistent, Contained):
- zope.interface.implements(interfaces.IDefaultPreferenceProvider)
-
- def __init__(self):
- self.data = OOBTree()
-
- def getDefaultPreferenceGroup(self, id=''):
- group = zope.component.getUtility(interfaces.IPreferenceGroup, name=id)
- group = group.__bind__(self)
- default = DefaultPreferenceGroup(group, self)
- zope.interface.alsoProvides(default, IContainmentRoot)
- locate(default, self, 'preferences')
- return default
-
- preferences = property(getDefaultPreferenceGroup)
-
-
-def DefaultPreferences(context, request):
- return context.preferences
-
-
-class DefaultPreferenceGroup(preference.PreferenceGroup):
- """A preference group representing the site-wide default values."""
-
- def __init__(self, group, provider):
- self.provider = provider
- super(DefaultPreferenceGroup, self).__init__(
- group.__id__, group.__schema__,
- group.__title__, group.__description__)
-
- # Make sure that we also mark the default group as category if the
- # actual group is one; this is important for the UI.
- if interfaces.IPreferenceCategory.providedBy(group):
- zope.interface.alsoProvides(self, interfaces.IPreferenceCategory)
-
- def get(self, key, default=None):
- group = super(DefaultPreferenceGroup, self).get(key, default)
- if group is default:
- return default
- return DefaultPreferenceGroup(group, self.provider).__bind__(self)
-
- def items(self):
- return [
- (id, DefaultPreferenceGroup(group, self.provider).__bind__(self))
- for id, group in super(DefaultPreferenceGroup, self).items()]
-
- def __getattr__(self, key):
- # Try to find a sub-group of the given id
- group = self.get(key)
- if group is not None:
- return group
-
- # Try to find a preference of the given name
- if self.__schema__ and key in self.__schema__:
- marker = object()
- value = self.data.get(key, marker)
- if value is not marker:
- return value
-
- # There is currently no local entry, so let's go to the next
- # provider and lookup the group and value there.
- nextProvider = zope.app.component.queryNextUtility(
- self.provider, interfaces.IDefaultPreferenceProvider)
-
- # No more providers found, so return the schema's default
- if nextProvider is None:
- return self.__schema__[key].default
-
- nextGroup = nextProvider.getDefaultPreferenceGroup(self.__id__)
- return getattr(nextGroup, key, self.__schema__[key].default)
-
- # Nothing found, raise an attribute error
- raise AttributeError("'%s' is not a preference or sub-group." % key)
-
- def data(self):
- if self.__id__ not in self.provider.data:
- self.provider.data[self.__id__] = OOBTree()
-
- return self.provider.data[self.__id__]
- data = property(data)
-
-
-defineChecker(DefaultPreferenceGroup, preference.PreferenceGroupChecker)
+# BBB
+from zope.preferences.default import (
+ DefaultPreferenceGroup,
+ DefaultPreferenceProvider,
+ DefaultPreferences,
+ )
Modified: zope.app.preference/trunk/src/zope/app/preference/ftesting.zcml
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/ftesting.zcml 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/ftesting.zcml 2010-06-12 11:45:38 UTC (rev 113388)
@@ -4,10 +4,12 @@
<!-- used for functional testing setup -->
<include package="zope.app.zcmlfiles" />
+
+ <include package="zope.preference" file="meta.zcml"/>
+ <include package="zope.preference" />
+
+ <include package="zope.app.preference" />
<include package="zope.app.tree" />
<include package="zope.app.renderer" />
- <include package="zope.app.preference" file="meta.zcml"/>
- <include package="zope.app.preference" />
-
</configure>
Modified: zope.app.preference/trunk/src/zope/app/preference/interfaces.py
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/interfaces.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/interfaces.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -11,75 +11,12 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""User Preferences Interfaces
+"""User Preferences Interfaces"""
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-import zope.interface
-import zope.schema
-from zope.configuration.fields import MessageID
-from zope.location.interfaces import ILocation
-
-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__ = zope.schema.TextLine(
- title=u"Id",
- description=u"The id of the group.",
- required=True)
-
- __schema__ = zope.schema.InterfaceField(
- title=u"Schema",
- description=u"Schema describing the preferences of the group.",
- required=False)
-
- __title__ = MessageID(
- title=u"Title",
- description=u"The title of the group used in the UI.",
- required=True)
-
- __description__ = MessageID(
- title=u"Description",
- description=u"The description of the group used in the UI.",
- required=False)
-
-
-class IPreferenceCategory(zope.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 IUserPreferences(zope.interface.Interface):
- """Objects providing this interface have to provide the root preference
- group API as well."""
-
-
-class IDefaultPreferenceProvider(zope.interface.Interface):
- """A root object providing default values for the entire preferences tree.
-
- Default preference providers are responsible for providing default values
- for all preferences. The way they get these values are up to the
- implementation.
- """
-
- preferences = zope.schema.Field(
- title = u"Default Preferences Root",
- description = u"Link to the default preferences")
+# BBB
+from zope.preferences.interfaces import (
+ IDefaultPreferenceProvider,
+ IPreferenceCategory,
+ IPreferenceGroup,
+ IUserPreferences,
+ )
Modified: zope.app.preference/trunk/src/zope/app/preference/meta.zcml
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/meta.zcml 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/meta.zcml 2010-06-12 11:45:38 UTC (rev 113388)
@@ -3,16 +3,6 @@
xmlns:meta="http://namespaces.zope.org/meta"
>
- <meta:provides feature="preference" />
+ <include package="zope.preference" file="meta.zcml" />
- <meta:directives namespace="http://namespaces.zope.org/zope">
-
- <meta:directive
- name="preferenceGroup"
- schema=".metadirectives.IPreferenceGroupDirective"
- handler=".metaconfigure.preferenceGroup"
- />
-
- </meta:directives>
-
</configure>
Modified: zope.app.preference/trunk/src/zope/app/preference/metaconfigure.py
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/metaconfigure.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/metaconfigure.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -11,20 +11,7 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""This module handles the 'apidoc' namespace directives.
+"""This module handles the 'preference' namespace directives."""
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-from zope.component.zcml import utility
-
-from zope.app.preference.interfaces import IPreferenceGroup
-from zope.app.preference.preference import PreferenceGroup
-
-
-def preferenceGroup(_context, id=None, schema=None,
- title=u'', description=u'', category=False):
- if id is None:
- id = ''
- group = PreferenceGroup(id, schema, title, description, category)
- utility(_context, IPreferenceGroup, group, name=id)
+# BBB
+from zope.preference.metaconfigure import preferenceGroup
Modified: zope.app.preference/trunk/src/zope/app/preference/metadirectives.py
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/metadirectives.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/metadirectives.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -11,48 +11,7 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""``apidoc:preferencesgroup`` ZCML directive interface
+"""``apidoc:preferencesgroup`` ZCML directive interface"""
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-from zope.interface import Interface
-from zope.configuration import fields
-
-class IPreferenceGroupDirective(Interface):
- """Register a preference group."""
-
- # The id is not required, since the root group has an empty id.
- 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=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
- )
-
- category = fields.Bool(
- title=u"Is Group a Category",
- description=u"Denotes whether this preferences group is a category.",
- required=False,
- default=False
- )
+# BBB
+from zope.preferences.metadirectives import IPreferenceGroupDirective
Modified: zope.app.preference/trunk/src/zope/app/preference/preference.py
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/preference.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/preference.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -11,240 +11,12 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""User Preferences System
+"""User Preferences System"""
-$Id$
-"""
-__docformat__ = "reStructuredText"
-from BTrees.OOBTree import OOBTree
-
-import zope.interface
-import zope.component
-from zope.schema import getFields
-from zope.security.checker import CheckerPublic, Checker, defineChecker
-from zope.security.management import getInteraction
-from zope.traversing.interfaces import IContainmentRoot
-from zope.location import LocationProxy, locate, Location
-from zope.annotation.interfaces import IAnnotations
-
-import zope.app.component.hooks
-from zope.container.contained import Contained
-from zope.container.interfaces import IReadContainer
-
-from zope.app.preference.interfaces import IPreferenceGroup
-from zope.app.preference.interfaces import IPreferenceCategory
-from zope.app.preference.interfaces import IDefaultPreferenceProvider
-
-pref_key = 'zope.app.user.UserPreferences'
-
-
-class PreferenceGroup(Location):
- """A feature-rich ``IPreferenceGroup`` implementation.
-
- This class implements the
- """
- zope.interface.implements(IPreferenceGroup, IReadContainer)
-
- # Declare attributes here, so that they are always available.
- __id__ = ''
- __schema__ = None
- __title__ = None
- __description__ = None
-
- def __init__(self, id, schema=None, title=u'', description=u'',
- isCategory=False):
- self.__id__ = id
- self.__schema__ = schema
- self.__title__ = title
- self.__description__ = description
-
- # The last part of the id is the name.
- self.__name__ = id.split('.')[-1]
-
- # Make sure this group provides all important interfaces.
- directlyProvided = ()
- if isCategory:
- directlyProvided += (IPreferenceCategory,)
- if schema:
- directlyProvided += (schema,)
- zope.interface.directlyProvides(self, directlyProvided)
-
- # Store the actual parent in ``__parent``. Usually we would just override
- # the property to an actual value during binding, but because we overrode
- # ``__setattr__`` this is not possible anymore.
- __parent = None
- def __parent__(self):
- return self.__parent or zope.app.component.hooks.getSite()
- __parent__ = property(__parent__)
-
-
- def __bind__(self, parent):
- clone = self.__class__.__new__(self.__class__)
- clone.__dict__.update(self.__dict__)
- clone.__parent = parent
- return clone
-
-
- def get(self, key, default=None):
- id = self.__id__ and self.__id__ + '.' + key or key
- group = zope.component.queryUtility(IPreferenceGroup, id, default)
- if group is default:
- return default
- return group.__bind__(self)
-
-
- def items(self):
- cutoff = self.__id__ and len(self.__id__)+1 or 0
- utilities = zope.component.getUtilitiesFor(IPreferenceGroup)
- return [(id[cutoff:], group.__bind__(self))
- for id, group in utilities
- if id != self.__id__ and \
- id.startswith(self.__id__) and \
- id[cutoff:].find('.') == -1]
-
- def __getitem__(self, key):
- """See zope.container.interfaces.IReadContainer"""
- default = object()
- obj = self.get(key, default)
- if obj is default:
- raise KeyError(key)
- return obj
-
- def __contains__(self, key):
- """See zope.container.interfaces.IReadContainer"""
- return self.get(key) is not None
-
- def keys(self):
- """See zope.container.interfaces.IReadContainer"""
- return [id for id, group in self.items()]
-
- def __iter__(self):
- """See zope.container.interfaces.IReadContainer"""
- return self.values().__iter__()
-
- def values(self):
- """See zope.container.interfaces.IReadContainer"""
- return [group for id, group in self.items()]
-
- def __len__(self):
- """See zope.container.interfaces.IReadContainer"""
- return len(self.items())
-
- def __getattr__(self, key):
- # Try to find a sub-group of the given id
- group = self.get(key)
- if group is not None:
- return group
-
- # Try to find a preference of the given name
- if self.__schema__ and key in self.__schema__:
- marker = object()
- value = self.data.get(key, marker)
- if value is marker:
- # Try to find a default preference provider
- provider = zope.component.queryUtility(
- IDefaultPreferenceProvider,
- context=self
- )
- if provider is None:
- return self.__schema__[key].default
- defaultGroup = provider.getDefaultPreferenceGroup(self.__id__)
- return getattr(defaultGroup, key)
- return value
-
- # Nothing found, raise an attribute error
- raise AttributeError("'%s' is not a preference or sub-group." % key)
-
- def __setattr__(self, key, value):
- if self.__schema__ and key in self.__schema__:
- # Validate the value
- bound = self.__schema__[key].bind(self)
- bound.validate(value)
- # Assign value
- self.data[key] = value
- else:
- self.__dict__[key] = value
- # If the schema changed, we really need to change the security
- # checker as well.
- if key is '__schema__':
- checker = PreferenceGroupChecker(self)
- self.__dict__['__Security_checker__'] = checker
-
- def __delattr__(self, key):
- if self.__schema__ and key in self.__schema__:
- del self.data[key]
- else:
- del self.__dict__[key]
-
- def data(self):
- # TODO: what if we have multiple participations?
- principal = getInteraction().participations[0].principal
- ann = zope.component.getMultiAdapter((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__]
- data = property(data)
-
-
-def PreferenceGroupChecker(instance):
- """A function that generates a custom security checker.
-
- The attributes available in a preference group are dynamically generated
- based on the group schema and the available sub-groups. Thus, the
- permission dictionaries have to be generated at runtime and are unique for
- each preference group instance.
- """
- read_perm_dict = {}
- write_perm_dict = {}
-
- # Make sure that the attributes from IPreferenceGroup and IReadContainer
- # are public.
- for attrName in ('__id__', '__schema__', '__title__', '__description__',
- 'get', 'items', 'keys', 'values',
- '__getitem__', '__contains__', '__iter__', '__len__'):
- read_perm_dict[attrName] = CheckerPublic
-
- # Make the attributes generated from the schema available as well.
- if instance.__schema__ is not None:
- for name in getFields(instance.__schema__):
- read_perm_dict[name] = CheckerPublic
- write_perm_dict[name] = CheckerPublic
-
- # Make all sub-groups available as well.
- for name in instance.keys():
- read_perm_dict[name] = CheckerPublic
- write_perm_dict[name] = CheckerPublic
-
- return Checker(read_perm_dict, write_perm_dict)
-
-
-def UserPreferences(context=None):
- """Adapts an ``ILocation`` object to the ``IUserPreferences`` interface."""
- if context is None:
- context = zope.component.getSiteManager()
- rootGroup = zope.component.getUtility(IPreferenceGroup)
- rootGroup = rootGroup.__bind__(context)
- rootGroup.__name__ = '++preferences++'
- zope.interface.alsoProvides(rootGroup, IContainmentRoot)
- return rootGroup
-
-class preferencesNamespace(object):
- """Used to traverse to the root preferences group."""
-
- def __init__(self, ob, request=None):
- self.context = ob
-
- def traverse(self, name, ignore):
- rootGroup = zope.component.getUtility(IPreferenceGroup)
- rootGroup = rootGroup.__bind__(self.context)
- rootGroup.__name__ = '++preferences++'
- zope.interface.alsoProvides(rootGroup, IContainmentRoot)
- return name and rootGroup[name] or rootGroup
+# BBB
+from zope.preference.preference import (
+ PreferenceGroup,
+ PreferenceGroupChecker,
+ UserPreferences,
+ preferencesNamespace,
+ )
Modified: zope.app.preference/trunk/src/zope/app/preference/tests.py
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/tests.py 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/tests.py 2010-06-12 11:45:38 UTC (rev 113388)
@@ -17,33 +17,21 @@
"""
from zope.app.testing import setup, functional
from zope.component import testing
-import doctest
import unittest
import zope.app.preference.testing
def setUp(test):
- testing.setUp(test)
setup.setUpTestAsModule(test, 'zope.app.preference.README')
-def ftest_setUp(test):
- setup.setUpTestAsModule(test, 'zope.app.preference.zmi')
-
-
def tearDown(test):
testing.tearDown(test)
setup.tearDownTestAsModule(test)
def test_suite():
- browser_tests = functional.FunctionalDocFileSuite(
- 'zmi.txt', setUp=ftest_setUp, tearDown=tearDown)
- browser_tests.layer = zope.app.preference.testing.PreferencesLayer
-
- return unittest.TestSuite((
- doctest.DocFileSuite('README.txt',
- setUp=setUp, tearDown=tearDown,
- optionflags=doctest.NORMALIZE_WHITESPACE),
- browser_tests,
- ))
+ tests = functional.FunctionalDocFileSuite(
+ 'README.txt', setUp=setUp, tearDown=tearDown)
+ tests.layer = zope.app.preference.testing.PreferencesLayer
+ return unittest.TestSuite((tests,))
Deleted: zope.app.preference/trunk/src/zope/app/preference/zmi.txt
===================================================================
--- zope.app.preference/trunk/src/zope/app/preference/zmi.txt 2010-06-12 11:44:21 UTC (rev 113387)
+++ zope.app.preference/trunk/src/zope/app/preference/zmi.txt 2010-06-12 11:45:38 UTC (rev 113388)
@@ -1,153 +0,0 @@
-=======
-Browser
-=======
-
-This package also provides a user interface, so the user can edit the
-preferences.
-
-Set up
-------
-
-To show the user interface functions we need some setup beforehand:
-
- >>> from zope.testbrowser.testing import Browser
- >>> browser = Browser()
-
-As the preferences cannot be defined through the web we have to define
-them in python code:
-
- >>> import zope.interface
- >>> import zope.schema
- >>> 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)
-
-The preference schema is usually registered using a ZCML statement:
-
- >>> from zope.configuration import xmlconfig
- >>> import zope.app.preference
- >>> context = xmlconfig.file('meta.zcml', zope.app.preference)
-
- >>> context = xmlconfig.string('''
- ... <configure
- ... xmlns="http://namespaces.zope.org/zope"
- ... i18n_domain="test">
- ...
- ... <preferenceGroup
- ... id="ZMISettings"
- ... title="ZMI Settings"
- ... schema="zope.app.preference.zmi.IZMIUserSettings"
- ... category="true"
- ... />
- ...
- ... </configure>''', context)
-
-Editing Preferences
--------------------
-
-The preferences are accessable in the ``++preferences++`` namespace:
-
- >>> browser.open('http://localhost/++preferences++')
-
-The page shows a form which allows editing the preference values:
-
- >>> browser.getControl('E-mail').value = 'hans at example.com'
- >>> browser.getControl('Skin').displayOptions
- ['Rotterdam', 'ZopeTop', 'Basic']
- >>> browser.getControl('Skin').displayValue = ['ZopeTop']
- >>> browser.getControl('Show Zope Logo').selected
- True
- >>> browser.getControl('Show Zope Logo').click()
-
-After selecting `Change` the values get persisted:
-
- >>> browser.getControl('Change').click()
- >>> browser.url
- 'http://localhost/++preferences++/@@index.html'
- >>> browser.getControl('E-mail').value
- 'hans at example.com'
- >>> browser.getControl('Skin').displayValue
- ['ZopeTop']
- >>> browser.getControl('Show Zope Logo').selected
- False
-
-The preference group is shown in a tree. It has a link to the form:
-
- >>> browser.getLink('ZMISettings').click()
- >>> browser.url
- 'http://localhost/++preferences++/ZMISettings/@@index.html'
- >>> browser.getControl('E-mail').value
- 'hans at example.com'
-
-
-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:
-
- >>> class IFolderSettings(zope.interface.Interface):
- ... """Basic Folder Settings"""
- ...
- ... shownFields = zope.schema.Set(
- ... title=u"Shown Fields",
- ... description=u"Fields shown in the table.",
- ... value_type=zope.schema.Choice(['name', 'size', 'creator']),
- ... default=set(['name', 'size']))
- ...
- ... sortedBy = zope.schema.Choice(
- ... title=u"Sorted By",
- ... description=u"Data field to sort by.",
- ... values=['name', 'size', 'creator'],
- ... default='name')
-
-And register it:
-
- >>> context = xmlconfig.string('''
- ... <configure
- ... xmlns="http://namespaces.zope.org/zope"
- ... i18n_domain="test">
- ...
- ... <preferenceGroup
- ... id="ZMISettings.Folder"
- ... title="Folder Content View Settings"
- ... schema="zope.app.preference.zmi.IFolderSettings"
- ... />
- ...
- ... </configure>''', context)
-
-The sub-group is displayed inside the parent group as a form:
-
- >>> browser.reload()
- >>> browser.getControl('Shown Fields').displayOptions
- ['name', 'size', 'creator']
- >>> browser.getControl('Shown Fields').displayValue
- ['name', 'size']
- >>> browser.getControl('Shown Fields').displayValue = ['size', 'creator']
- >>> browser.getControl('Sorted By').displayOptions
- ['name', 'size', 'creator']
- >>> browser.getControl('Sorted By').displayValue = ['creator']
-
-Selecing `Change` persists these values, too:
-
- >>> browser.getControl('Change').click()
- >>> browser.getControl('Shown Fields').displayValue
- ['size', 'creator']
- >>> browser.getControl('Sorted By').displayValue
- ['creator']
More information about the checkins
mailing list